From 7c2d21b4c28360f5e058e1632d87028f6b43e90a Mon Sep 17 00:00:00 2001 From: Jin Qian Date: Thu, 2 Nov 2017 12:08:29 -0700 Subject: ext4_utils: delete make_ext4fs relavant code and script make_ext4fs has been replaced with mke2fs. Bug: 64395169 Change-Id: Iad3a8346ca211e4d5a5ab7046c2bdd199292a867 --- ext4_utils/Android.bp | 2 - ext4_utils/Android.mk | 75 --- ext4_utils/contents.c | 1 - ext4_utils/ext4fixup.c | 817 ------------------------ ext4_utils/ext4fixup.h | 20 - ext4_utils/ext4fixup_main.c | 69 --- ext4_utils/include/ext4_utils/ext4_utils.h | 8 - ext4_utils/include/ext4_utils/make_ext4fs.h | 51 -- ext4_utils/make_ext4fs.c | 931 ---------------------------- ext4_utils/make_ext4fs_main.c | 276 --------- ext4_utils/mkuserimg.sh | 158 ----- ext4_utils/setup_fs.c | 86 --- ext4_utils/test_ext4fixup | 71 --- 13 files changed, 2565 deletions(-) delete mode 100644 ext4_utils/ext4fixup.c delete mode 100644 ext4_utils/ext4fixup.h delete mode 100644 ext4_utils/ext4fixup_main.c delete mode 100644 ext4_utils/include/ext4_utils/make_ext4fs.h delete mode 100644 ext4_utils/make_ext4fs.c delete mode 100644 ext4_utils/make_ext4fs_main.c delete mode 100755 ext4_utils/mkuserimg.sh delete mode 100644 ext4_utils/setup_fs.c delete mode 100755 ext4_utils/test_ext4fixup (limited to 'ext4_utils') diff --git a/ext4_utils/Android.bp b/ext4_utils/Android.bp index ff17edbc..df53cd75 100644 --- a/ext4_utils/Android.bp +++ b/ext4_utils/Android.bp @@ -5,8 +5,6 @@ cc_library { defaults: ["system-extras-cflags-defaults"], host_supported: true, srcs: [ - "make_ext4fs.c", - "ext4fixup.c", "ext4_utils.c", "allocate.c", "contents.c", diff --git a/ext4_utils/Android.mk b/ext4_utils/Android.mk index 6f26dd64..94d080ff 100644 --- a/ext4_utils/Android.mk +++ b/ext4_utils/Android.mk @@ -6,25 +6,6 @@ LOCAL_PATH:= $(call my-dir) # -- All host/targets including windows # -include $(CLEAR_VARS) -LOCAL_SRC_FILES := make_ext4fs_main.c -LOCAL_MODULE := make_ext4fs -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/include -LOCAL_SHARED_LIBRARIES += libcutils -LOCAL_STATIC_LIBRARIES += \ - libext4_utils \ - libsparse \ - libz -LOCAL_LDLIBS_windows += -lws2_32 -LOCAL_SHARED_LIBRARIES_darwin += libselinux -LOCAL_SHARED_LIBRARIES_linux += libselinux -LOCAL_CFLAGS_darwin := -DHOST -LOCAL_CFLAGS_linux := -DHOST -LOCAL_CFLAGS += -Wall -Werror -include $(BUILD_HOST_EXECUTABLE) - - include $(CLEAR_VARS) LOCAL_SRC_FILES := blk_alloc_to_base_fs.c LOCAL_MODULE := blk_alloc_to_base_fs @@ -40,62 +21,6 @@ include $(BUILD_HOST_EXECUTABLE) ifneq ($(HOST_OS),windows) -include $(CLEAR_VARS) -LOCAL_SRC_FILES := make_ext4fs_main.c -LOCAL_MODULE := make_ext4fs -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/include -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libext2_uuid \ - libext4_utils \ - libselinux \ - libz -LOCAL_CFLAGS := -DREAL_UUID -Wall -Werror -include $(BUILD_EXECUTABLE) - - -include $(CLEAR_VARS) -LOCAL_SRC_FILES := setup_fs.c -LOCAL_MODULE := setup_fs -LOCAL_SHARED_LIBRARIES += libcutils -LOCAL_CFLAGS := -Wall -Werror -include $(BUILD_EXECUTABLE) - - -include $(CLEAR_VARS) -LOCAL_SRC_FILES := ext4fixup_main.c -LOCAL_CFLAGS := -Wall -Werror -LOCAL_MODULE := ext4fixup -LOCAL_SHARED_LIBRARIES += \ - libext4_utils \ - libsparse \ - libz -include $(BUILD_EXECUTABLE) - - -include $(CLEAR_VARS) -LOCAL_SRC_FILES := ext4fixup_main.c -LOCAL_CFLAGS := -Wall -Werror -LOCAL_MODULE := ext4fixup -LOCAL_STATIC_LIBRARIES += \ - libext4_utils \ - libsparse \ - libz -include $(BUILD_HOST_EXECUTABLE) - - -include $(CLEAR_VARS) -LOCAL_MODULE := mkuserimg.sh -LOCAL_SRC_FILES := mkuserimg.sh -LOCAL_MODULE_CLASS := EXECUTABLES -# We don't need any additional suffix. -LOCAL_MODULE_SUFFIX := -LOCAL_BUILT_MODULE_STEM := $(notdir $(LOCAL_SRC_FILES)) -LOCAL_IS_HOST_MODULE := true -include $(BUILD_PREBUILT) - - include $(CLEAR_VARS) LOCAL_MODULE := mkuserimg_mke2fs.sh LOCAL_SRC_FILES := mkuserimg_mke2fs.sh diff --git a/ext4_utils/contents.c b/ext4_utils/contents.c index a2cd3b88..73810f32 100644 --- a/ext4_utils/contents.c +++ b/ext4_utils/contents.c @@ -22,7 +22,6 @@ #include "allocate.h" #include "ext4_utils/ext4_utils.h" -#include "ext4_utils/make_ext4fs.h" #include "extent.h" #include "indirect.h" diff --git a/ext4_utils/ext4fixup.c b/ext4_utils/ext4fixup.c deleted file mode 100644 index 508e8bd6..00000000 --- a/ext4_utils/ext4fixup.c +++ /dev/null @@ -1,817 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ext4fixup.h" - -#ifndef _LARGEFILE64_SOURCE -#define _LARGEFILE64_SOURCE 1 -#endif - -#include -#include -#include -#include - -#include - -#include "allocate.h" -#include "ext4_utils/ext4_extents.h" -#include "ext4_utils/ext4_utils.h" -#include "ext4_utils/make_ext4fs.h" - -#ifndef _WIN32 -#include -#endif - -#if defined(__APPLE__) && defined(__MACH__) -#define lseek64 lseek -#define off64_t off_t -#endif - -/* The inode block count for a file/directory is in units of 512 byte blocks, - * _NOT_ the filesystem block size! - */ -#define INODE_BLOCK_SIZE 512 - -#define MAX_EXT4_BLOCK_SIZE 4096 - -/* The two modes the recurse_dir() can be in */ -#define SANITY_CHECK_PASS 1 -#define MARK_INODE_NUMS 2 -#define UPDATE_INODE_NUMS 3 - -/* Magic numbers to indicate what state the update process is in */ -#define MAGIC_STATE_MARKING_INUMS 0x7000151515565512ll -#define MAGIC_STATE_UPDATING_INUMS 0x6121131211735123ll -#define MAGIC_STATE_UPDATING_SB 0x15e1715151558477ll - -/* Internal state variables corresponding to the magic numbers */ -#define STATE_UNSET 0 -#define STATE_MARKING_INUMS 1 -#define STATE_UPDATING_INUMS 2 -#define STATE_UPDATING_SB 3 - -/* Used for automated testing of this programs ability to stop and be restarted wthout error */ -static int bail_phase = 0; -static int bail_loc = 0; -static int bail_count = 0; -static int count = 0; - -/* global flags */ -static int verbose = 0; -static int no_write = 0; - -static int new_inodes_per_group = 0; - -static int no_write_fixup_state = 0; - -static int compute_new_inum(unsigned int old_inum) -{ - unsigned int group, offset; - - group = (old_inum - 1) / info.inodes_per_group; - offset = (old_inum -1) % info.inodes_per_group; - - return (group * new_inodes_per_group) + offset + 1; -} - -static int get_fs_fixup_state(int fd) -{ - unsigned long long magic; - int ret, len; - - if (no_write) { - return no_write_fixup_state; - } - - lseek64(fd, 0, SEEK_SET); - len = read(fd, &magic, sizeof(magic)); - if (len != sizeof(magic)) { - critical_error("cannot read fixup_state\n"); - } - - switch (magic) { - case MAGIC_STATE_MARKING_INUMS: - ret = STATE_MARKING_INUMS; - break; - case MAGIC_STATE_UPDATING_INUMS: - ret = STATE_UPDATING_INUMS; - break; - case MAGIC_STATE_UPDATING_SB: - ret = STATE_UPDATING_SB; - break; - default: - ret = STATE_UNSET; - } - return ret; -} - -static int set_fs_fixup_state(int fd, int state) -{ - unsigned long long magic; - struct ext4_super_block sb; - int len; - - if (no_write) { - no_write_fixup_state = state; - return 0; - } - - switch (state) { - case STATE_MARKING_INUMS: - magic = MAGIC_STATE_MARKING_INUMS; - break; - case STATE_UPDATING_INUMS: - magic = MAGIC_STATE_UPDATING_INUMS; - break; - case STATE_UPDATING_SB: - magic = MAGIC_STATE_UPDATING_SB; - break; - case STATE_UNSET: - default: - magic = 0ll; - break; - } - - lseek64(fd, 0, SEEK_SET); - len = write(fd, &magic, sizeof(magic)); - if (len != sizeof(magic)) { - critical_error("cannot write fixup_state\n"); - } - - read_sb(fd, &sb); - if (magic) { - /* If we are in the process of updating the filesystem, make it unmountable */ - sb.s_desc_size |= 1; - } else { - /* we are done, so make the filesystem mountable again */ - sb.s_desc_size &= ~1; - } - - if (!no_write) { - write_sb(fd, 1024, &sb); - } - - return 0; -} - -static int read_inode(int fd, unsigned int inum, struct ext4_inode *inode) -{ - unsigned int bg_num, bg_offset; - off64_t inode_offset; - int len; - - bg_num = (inum-1) / info.inodes_per_group; - bg_offset = (inum-1) % info.inodes_per_group; - - inode_offset = ((unsigned long long)aux_info.bg_desc[bg_num].bg_inode_table * info.block_size) + - (bg_offset * info.inode_size); - - if (lseek64(fd, inode_offset, SEEK_SET) < 0) { - critical_error_errno("failed to seek to inode %d\n", inum); - } - - len=read(fd, inode, sizeof(*inode)); - if (len != sizeof(*inode)) { - critical_error_errno("failed to read inode %d\n", inum); - } - - return 0; -} - -static int read_block(int fd, unsigned long long block_num, void *block) -{ - off64_t off; - unsigned int len; - - off = block_num * info.block_size; - - if (lseek64(fd, off, SEEK_SET) , 0) { - critical_error_errno("failed to seek to block %lld\n", block_num); - } - - len=read(fd, block, info.block_size); - if (len != info.block_size) { - critical_error_errno("failed to read block %lld\n", block_num); - } - - return 0; -} - -static int write_block(int fd, unsigned long long block_num, void *block) -{ - off64_t off; - unsigned int len; - - if (no_write) { - return 0; - } - - off = block_num * info.block_size; - - if (lseek64(fd, off, SEEK_SET) < 0) { - critical_error_errno("failed to seek to block %lld\n", block_num); - } - - len=write(fd, block, info.block_size); - if (len != info.block_size) { - critical_error_errno("failed to write block %lld\n", block_num); - } - - return 0; -} - -static void check_inode_bitmap(int fd, unsigned int bg_num) -{ - unsigned int inode_bitmap_block_num; - unsigned char block[MAX_EXT4_BLOCK_SIZE]; - int i, bitmap_updated = 0; - - /* Using the bg_num, aux_info.bg_desc[], info.inodes_per_group and - * new_inodes_per_group, retrieve the inode bitmap, and make sure - * the bits between the old and new size are clear - */ - inode_bitmap_block_num = aux_info.bg_desc[bg_num].bg_inode_bitmap; - - read_block(fd, inode_bitmap_block_num, block); - - for (i = info.inodes_per_group; i < new_inodes_per_group; i++) { - if (bitmap_get_bit(block, i)) { - bitmap_clear_bit(block, i); - bitmap_updated = 1; - } - } - - if (bitmap_updated) { - if (verbose) { - printf("Warning: updated inode bitmap for block group %d\n", bg_num); - } - write_block(fd, inode_bitmap_block_num, block); - } - - return; -} - -/* Update the superblock and bgdesc of the specified block group */ -static int update_superblocks_and_bg_desc(int fd, int state) -{ - off64_t ret; - struct ext4_super_block sb; - unsigned int num_block_groups, total_new_inodes; - unsigned int i; - - - read_sb(fd, &sb); - - /* Compute how many more inodes are now available */ - num_block_groups = DIV_ROUND_UP(aux_info.len_blocks, info.blocks_per_group); - total_new_inodes = num_block_groups * (new_inodes_per_group - sb.s_inodes_per_group); - - if (verbose) { - printf("created %d additional inodes\n", total_new_inodes); - } - - /* Update the free inodes count in each block group descriptor */ - for (i = 0; i < num_block_groups; i++) { - if (state == STATE_UPDATING_SB) { - aux_info.bg_desc[i].bg_free_inodes_count += (new_inodes_per_group - sb.s_inodes_per_group); - } - check_inode_bitmap(fd, i); - } - - /* First some sanity checks */ - if ((sb.s_inodes_count + total_new_inodes) != (new_inodes_per_group * num_block_groups)) { - critical_error("Failed sanity check on new inode count\n"); - } - if (new_inodes_per_group % (info.block_size/info.inode_size)) { - critical_error("Failed sanity check on new inode per group alignment\n"); - } - - /* Update the free inodes count in the superblock */ - sb.s_inodes_count += total_new_inodes; - sb.s_free_inodes_count += total_new_inodes; - sb.s_inodes_per_group = new_inodes_per_group; - - for (i = 0; i < aux_info.groups; i++) { - if (ext4_bg_has_super_block(i)) { - unsigned int sb_offset; - - if (i == 0) { - /* The first superblock is offset by 1K to leave room for boot sectors */ - sb_offset = 1024; - } else { - sb_offset = 0; - } - - sb.s_block_group_nr = i; - /* Don't write out the backup superblocks with the bit set in the s_desc_size - * which prevents the filesystem from mounting. The bit for the primary - * superblock will be cleared on the final call to set_fs_fixup_state() */ - if (i != 0) { - sb.s_desc_size &= ~1; - } - - if (!no_write) { - write_sb(fd, - (unsigned long long)i - * info.blocks_per_group * info.block_size - + sb_offset, - &sb); - } - - ret = lseek64(fd, ((unsigned long long)i * info.blocks_per_group * info.block_size) + - (info.block_size * (aux_info.first_data_block + 1)), SEEK_SET); - if (ret < 0) - critical_error_errno("failed to seek to block group descriptors"); - - if (!no_write) { - ret = write(fd, aux_info.bg_desc, info.block_size * aux_info.bg_desc_blocks); - if (ret < 0) - critical_error_errno("failed to write block group descriptors"); - if (ret != (int)info.block_size * (int)aux_info.bg_desc_blocks) - critical_error("failed to write all of block group descriptors"); - } - } - if ((bail_phase == 4) && ((unsigned int)bail_count == i)) { - critical_error("bailing at phase 4\n"); - } - } - - return 0; -} - - -static int get_direct_blocks(struct ext4_inode *inode, unsigned long long *block_list, - unsigned int *count) -{ - unsigned int i = 0; - unsigned int ret = 0; - unsigned int sectors_per_block; - - sectors_per_block = info.block_size / INODE_BLOCK_SIZE; - while ((i < (inode->i_blocks_lo / sectors_per_block)) && (i < EXT4_NDIR_BLOCKS)) { - block_list[i] = inode->i_block[i]; - i++; - } - - *count += i; - - if ((inode->i_blocks_lo / sectors_per_block) > EXT4_NDIR_BLOCKS) { - ret = 1; - } - - return ret; -} - -static int get_indirect_blocks(int fd, struct ext4_inode *inode, - unsigned long long *block_list, unsigned int *count) -{ - unsigned int i; - unsigned int *indirect_block; - unsigned int sectors_per_block; - - sectors_per_block = info.block_size / INODE_BLOCK_SIZE; - - indirect_block = (unsigned int *)malloc(info.block_size); - if (indirect_block == 0) { - critical_error("failed to allocate memory for indirect_block\n"); - } - - read_block(fd, inode->i_block[EXT4_NDIR_BLOCKS], indirect_block); - - for(i = 0; i < (inode->i_blocks_lo / sectors_per_block - EXT4_NDIR_BLOCKS); i++) { - block_list[EXT4_NDIR_BLOCKS+i] = indirect_block[i]; - } - - *count += i; - - free(indirect_block); - - return 0; -} - -static int get_block_list_indirect(int fd, struct ext4_inode *inode, unsigned long long *block_list) -{ - unsigned int count=0; - - if (get_direct_blocks(inode, block_list, &count)) { - get_indirect_blocks(fd, inode, block_list, &count); - } - - return count; -} - -static int get_extent_ents(struct ext4_extent_header *ext_hdr, unsigned long long *block_list) -{ - int i, j; - struct ext4_extent *extent; - off64_t fs_block_num; - - if (ext_hdr->eh_depth != 0) { - critical_error("get_extent_ents called with eh_depth != 0\n"); - } - - /* The extent entries immediately follow the header, so add 1 to the pointer - * and cast it to an extent pointer. - */ - extent = (struct ext4_extent *)(ext_hdr + 1); - - for (i = 0; i < ext_hdr->eh_entries; i++) { - fs_block_num = ((off64_t)extent->ee_start_hi << 32) | extent->ee_start_lo; - for (j = 0; j < extent->ee_len; j++) { - block_list[extent->ee_block+j] = fs_block_num+j; - } - extent++; - } - - return 0; -} - -static int get_extent_idx(int fd, struct ext4_extent_header *ext_hdr, unsigned long long *block_list) -{ - int i; - struct ext4_extent_idx *extent_idx; - struct ext4_extent_header *tmp_ext_hdr; - off64_t fs_block_num; - unsigned char block[MAX_EXT4_BLOCK_SIZE]; - - /* Sanity check */ - if (ext_hdr->eh_depth == 0) { - critical_error("get_extent_idx called with eh_depth == 0\n"); - } - - /* The extent entries immediately follow the header, so add 1 to the pointer - * and cast it to an extent pointer. - */ - extent_idx = (struct ext4_extent_idx *)(ext_hdr + 1); - - for (i = 0; i < ext_hdr->eh_entries; i++) { - fs_block_num = ((off64_t)extent_idx->ei_leaf_hi << 32) | extent_idx->ei_leaf_lo; - read_block(fd, fs_block_num, block); - tmp_ext_hdr = (struct ext4_extent_header *)block; - - if (tmp_ext_hdr->eh_depth == 0) { - get_extent_ents(tmp_ext_hdr, block_list); /* leaf node, fill in block_list */ - } else { - get_extent_idx(fd, tmp_ext_hdr, block_list); /* recurse down the tree */ - } - } - - return 0; -} - -static int get_block_list_extents(int fd, struct ext4_inode *inode, unsigned long long *block_list) -{ - struct ext4_extent_header *extent_hdr; - - extent_hdr = (struct ext4_extent_header *)inode->i_block; - - if (extent_hdr->eh_magic != EXT4_EXT_MAGIC) { - critical_error("extent header has unexpected magic value 0x%4.4x\n", - extent_hdr->eh_magic); - } - - if (extent_hdr->eh_depth == 0) { - get_extent_ents((struct ext4_extent_header *)inode->i_block, block_list); - return 0; - } - - get_extent_idx(fd, (struct ext4_extent_header *)inode->i_block, block_list); - - return 0; -} - -static int is_entry_dir(int fd, struct ext4_dir_entry_2 *dirp, int pass) -{ - struct ext4_inode inode; - int ret = 0; - - if (dirp->file_type == EXT4_FT_DIR) { - ret = 1; - } else if (dirp->file_type == EXT4_FT_UNKNOWN) { - /* Somebody was too lazy to fill in the dir entry, - * so we have to go fetch it from the inode. Grrr. - */ - /* if UPDATE_INODE_NUMS pass and the inode high bit is not - * set return false so we don't recurse down the tree that is - * already updated. Otherwise, fetch inode, and return answer. - */ - if ((pass == UPDATE_INODE_NUMS) && !(dirp->inode & 0x80000000)) { - ret = 0; - } else { - read_inode(fd, (dirp->inode & 0x7fffffff), &inode); - if (S_ISDIR(inode.i_mode)) { - ret = 1; - } - } - } - - return ret; -} - -static int recurse_dir(int fd, struct ext4_inode *inode, char *dirbuf, int dirsize, int mode) -{ - unsigned long long *block_list; - unsigned int num_blocks; - struct ext4_dir_entry_2 *dirp, *prev_dirp = 0; - char name[256]; - unsigned int i, leftover_space, is_dir; - struct ext4_inode tmp_inode; - int tmp_dirsize; - char *tmp_dirbuf; - - switch (mode) { - case SANITY_CHECK_PASS: - case MARK_INODE_NUMS: - case UPDATE_INODE_NUMS: - break; - default: - critical_error("recurse_dir() called witn unknown mode!\n"); - } - - if (dirsize % info.block_size) { - critical_error("dirsize %d not a multiple of block_size %d. This is unexpected!\n", - dirsize, info.block_size); - } - - num_blocks = dirsize / info.block_size; - - block_list = malloc((num_blocks + 1) * sizeof(*block_list)); - if (block_list == 0) { - critical_error("failed to allocate memory for block_list\n"); - } - - if (inode->i_flags & EXT4_EXTENTS_FL) { - get_block_list_extents(fd, inode, block_list); - } else { - /* A directory that requires doubly or triply indirect blocks in huge indeed, - * and will almost certainly not exist, especially since make_ext4fs only creates - * directories with extents, and the kernel will too, but check to make sure the - * directory is not that big and give an error if so. Our limit is 12 direct blocks, - * plus block_size/4 singly indirect blocks, which for a filesystem with 4K blocks - * is a directory 1036 blocks long, or 4,243,456 bytes long! Assuming an average - * filename length of 20 (which I think is generous) thats 20 + 8 bytes overhead - * per entry, or 151,552 entries in the directory! - */ - if (num_blocks > (info.block_size / 4 + EXT4_NDIR_BLOCKS)) { - critical_error("Non-extent based directory is too big!\n"); - } - get_block_list_indirect(fd, inode, block_list); - } - - /* Read in all the blocks for this directory */ - for (i = 0; i < num_blocks; i++) { - read_block(fd, block_list[i], dirbuf + (i * info.block_size)); - } - - dirp = (struct ext4_dir_entry_2 *)dirbuf; - while (dirp < (struct ext4_dir_entry_2 *)(dirbuf + dirsize)) { - count++; - leftover_space = (char *)(dirbuf + dirsize) - (char *)dirp; - if (((mode == SANITY_CHECK_PASS) || (mode == UPDATE_INODE_NUMS)) && - (leftover_space <= 8) && prev_dirp) { - /* This is a bug in an older version of make_ext4fs, where it - * didn't properly include the rest of the block in rec_len. - * Update rec_len on the previous entry to include the rest of - * the block and exit the loop. - */ - if (verbose) { - printf("fixing up short rec_len for diretory entry for %s\n", name); - } - prev_dirp->rec_len += leftover_space; - break; - } - - if (dirp->inode == 0) { - /* This is the last entry in the directory */ - break; - } - - strncpy(name, dirp->name, dirp->name_len); - name[dirp->name_len]='\0'; - - /* Only recurse on pass UPDATE_INODE_NUMS if the high bit is set. - * Otherwise, this inode entry has already been updated - * and we'll do the wrong thing. Also don't recurse on . or .., - * and certainly not on non-directories! - */ - /* Hrm, looks like filesystems made by fastboot on stingray set the file_type - * flag, but the lost+found directory has the type set to Unknown, which - * seems to imply I need to read the inode and get it. - */ - is_dir = is_entry_dir(fd, dirp, mode); - if ( is_dir && (strcmp(name, ".") && strcmp(name, "..")) && - ((mode == SANITY_CHECK_PASS) || (mode == MARK_INODE_NUMS) || - ((mode == UPDATE_INODE_NUMS) && (dirp->inode & 0x80000000))) ) { - /* A directory! Recurse! */ - read_inode(fd, dirp->inode & 0x7fffffff, &tmp_inode); - - if (!S_ISDIR(tmp_inode.i_mode)) { - critical_error("inode %d for name %s does not point to a directory\n", - dirp->inode & 0x7fffffff, name); - } - if (verbose) { - printf("inode %d %s use extents\n", dirp->inode & 0x7fffffff, - (tmp_inode.i_flags & EXT4_EXTENTS_FL) ? "does" : "does not"); - } - - tmp_dirsize = tmp_inode.i_blocks_lo * INODE_BLOCK_SIZE; - if (verbose) { - printf("dir size = %d bytes\n", tmp_dirsize); - } - - tmp_dirbuf = malloc(tmp_dirsize); - if (tmp_dirbuf == 0) { - critical_error("failed to allocate memory for tmp_dirbuf\n"); - } - - recurse_dir(fd, &tmp_inode, tmp_dirbuf, tmp_dirsize, mode); - - free(tmp_dirbuf); - } - - if (verbose) { - if (is_dir) { - printf("Directory %s\n", name); - } else { - printf("Non-directory %s\n", name); - } - } - - /* Process entry based on current mode. Either set high bit or change inode number */ - if (mode == MARK_INODE_NUMS) { - dirp->inode |= 0x80000000; - } else if (mode == UPDATE_INODE_NUMS) { - if (dirp->inode & 0x80000000) { - dirp->inode = compute_new_inum(dirp->inode & 0x7fffffff); - } - } - - if ((bail_phase == mode) && (bail_loc == 1) && (bail_count == count)) { - critical_error("Bailing at phase %d, loc 1 and count %d\n", mode, count); - } - - /* Point dirp at the next entry */ - prev_dirp = dirp; - dirp = (struct ext4_dir_entry_2*)((char *)dirp + dirp->rec_len); - } - - /* Write out all the blocks for this directory */ - for (i = 0; i < num_blocks; i++) { - write_block(fd, block_list[i], dirbuf + (i * info.block_size)); - if ((bail_phase == mode) && (bail_loc == 2) && (bail_count <= count)) { - critical_error("Bailing at phase %d, loc 2 and count %d\n", mode, count); - } - } - - free(block_list); - - return 0; -} - -int ext4fixup(char *fsdev) -{ - return ext4fixup_internal(fsdev, 0, 0, 0, 0, 0); -} - -int ext4fixup_internal(char *fsdev, int v_flag, int n_flag, - int stop_phase, int stop_loc, int stop_count) -{ - int fd; - struct ext4_inode root_inode; - unsigned int dirsize; - char *dirbuf; - - if (setjmp(setjmp_env)) - return EXIT_FAILURE; /* Handle a call to longjmp() */ - - verbose = v_flag; - no_write = n_flag; - - bail_phase = stop_phase; - bail_loc = stop_loc; - bail_count = stop_count; - - fd = open(fsdev, O_RDWR); - - if (fd < 0) - critical_error_errno("failed to open filesystem image"); - - read_ext(fd, verbose); - - if (info.feat_incompat & EXT4_FEATURE_INCOMPAT_RECOVER) { - critical_error("Filesystem needs recovery first, mount and unmount to do that\n"); - } - - /* Clear the low bit which is set while this tool is in progress. - * If the tool crashes, it will still be set when we restart. - * The low bit is set to make the filesystem unmountable while - * it is being fixed up. Also allow 0, which means the old ext2 - * size is in use. - */ - if (((aux_info.sb->s_desc_size & ~1) != sizeof(struct ext2_group_desc)) && - ((aux_info.sb->s_desc_size & ~1) != 0)) - critical_error("error: bg_desc_size != sizeof(struct ext2_group_desc)\n"); - - if ((info.feat_incompat & EXT4_FEATURE_INCOMPAT_FILETYPE) == 0) { - critical_error("Expected filesystem to have filetype flag set\n"); - } - -#if 0 // If we have to fix the directory rec_len issue, we can't use this check - /* Check to see if the inodes/group is copacetic */ - if (info.inodes_per_blockgroup % (info.block_size/info.inode_size) == 0) { - /* This filesystem has either already been updated, or was - * made correctly. - */ - if (verbose) { - printf("%s: filesystem correct, no work to do\n", me); - } - exit(0); - } -#endif - - /* Compute what the new value of inodes_per_blockgroup will be when we're done */ - new_inodes_per_group=EXT4_ALIGN(info.inodes_per_group,(info.block_size/info.inode_size)); - - read_inode(fd, EXT4_ROOT_INO, &root_inode); - - if (!S_ISDIR(root_inode.i_mode)) { - critical_error("root inode %d does not point to a directory\n", EXT4_ROOT_INO); - } - if (verbose) { - printf("inode %d %s use extents\n", EXT4_ROOT_INO, - (root_inode.i_flags & EXT4_EXTENTS_FL) ? "does" : "does not"); - } - - dirsize = root_inode.i_blocks_lo * INODE_BLOCK_SIZE; - if (verbose) { - printf("root dir size = %d bytes\n", dirsize); - } - - dirbuf = malloc(dirsize); - if (dirbuf == 0) { - critical_error("failed to allocate memory for dirbuf\n"); - } - - /* Perform a sanity check pass first, try to catch any errors that will occur - * before we actually change anything, so we don't leave a filesystem in a - * corrupted, unrecoverable state. Set no_write, make it quiet, and do a recurse - * pass and a update_superblock pass. Set flags back to requested state when done. - * Only perform sanity check if the state is unset. If the state is _NOT_ unset, - * then the tool has already been run and interrupted, and it presumably ran and - * passed sanity checked before it got interrupted. It is _NOT_ safe to run sanity - * check if state is unset because it assumes inodes are to be computed using the - * old inodes/group, but some inode numbers may be updated to the new number. - */ - if (get_fs_fixup_state(fd) == STATE_UNSET) { - verbose = 0; - no_write = 1; - recurse_dir(fd, &root_inode, dirbuf, dirsize, SANITY_CHECK_PASS); - update_superblocks_and_bg_desc(fd, STATE_UNSET); - verbose = v_flag; - no_write = n_flag; - - set_fs_fixup_state(fd, STATE_MARKING_INUMS); - } - - if (get_fs_fixup_state(fd) == STATE_MARKING_INUMS) { - count = 0; /* Reset debugging counter */ - if (!recurse_dir(fd, &root_inode, dirbuf, dirsize, MARK_INODE_NUMS)) { - set_fs_fixup_state(fd, STATE_UPDATING_INUMS); - } - } - - if (get_fs_fixup_state(fd) == STATE_UPDATING_INUMS) { - count = 0; /* Reset debugging counter */ - if (!recurse_dir(fd, &root_inode, dirbuf, dirsize, UPDATE_INODE_NUMS)) { - set_fs_fixup_state(fd, STATE_UPDATING_SB); - } - } - - if (get_fs_fixup_state(fd) == STATE_UPDATING_SB) { - /* set the new inodes/blockgroup number, - * and sets the state back to 0. - */ - if (!update_superblocks_and_bg_desc(fd, STATE_UPDATING_SB)) { - set_fs_fixup_state(fd, STATE_UNSET); - } - } - - close(fd); - free(dirbuf); - - return 0; -} diff --git a/ext4_utils/ext4fixup.h b/ext4_utils/ext4fixup.h deleted file mode 100644 index 6ea21132..00000000 --- a/ext4_utils/ext4fixup.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -int ext4fixup(char *fsdev); -int ext4fixup_internal(char *fsdev, int v_flag, int n_flag, - int stop_phase, int stop_loc, int stop_count); - diff --git a/ext4_utils/ext4fixup_main.c b/ext4_utils/ext4fixup_main.c deleted file mode 100644 index f4428cbf..00000000 --- a/ext4_utils/ext4fixup_main.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include "ext4fixup.h" - -static void usage(char *me) -{ - fprintf(stderr, "%s: usage: %s [-vn] \n", me, me); -} - -int main(int argc, char **argv) -{ - int opt; - int verbose = 0; - int no_write = 0; - char *fsdev; - char *me; - int stop_phase = 0, stop_loc = 0, stop_count = 0; - - me = basename(argv[0]); - - while ((opt = getopt(argc, argv, "vnd:")) != -1) { - switch (opt) { - case 'v': - verbose = 1; - break; - case 'n': - no_write = 1; - break; - case 'd': - sscanf(optarg, "%d,%d,%d", &stop_phase, &stop_loc, &stop_count); - break; - } - } - - if (optind >= argc) { - fprintf(stderr, "expected image or block device after options\n"); - usage(me); - exit(EXIT_FAILURE); - } - - fsdev = argv[optind++]; - - if (optind < argc) { - fprintf(stderr, "Unexpected argument: %s\n", argv[optind]); - usage(me); - exit(EXIT_FAILURE); - } - - return ext4fixup_internal(fsdev, verbose, no_write, stop_phase, stop_loc, stop_count); -} diff --git a/ext4_utils/include/ext4_utils/ext4_utils.h b/ext4_utils/include/ext4_utils/ext4_utils.h index 17a8056b..12d2c0c8 100644 --- a/ext4_utils/include/ext4_utils/ext4_utils.h +++ b/ext4_utils/include/ext4_utils/ext4_utils.h @@ -162,14 +162,6 @@ u16 ext4_crc16(u16 crc_in, const void *buf, int size); typedef void (*fs_config_func_t)(const char *path, int dir, const char *target_out_path, unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities); -struct selabel_handle; - -int make_ext4fs_internal(int fd, const char *directory, const char *_target_out_directory, - const char *mountpoint, fs_config_func_t fs_config_func, int gzip, - int sparse, int crc, int wipe, int real_uuid, - struct selabel_handle *sehnd, int verbose, time_t fixed_time, - FILE* block_list_file, FILE* base_alloc_file_in, FILE* base_alloc_file_out); - int read_ext(int fd, int verbose); #ifdef __cplusplus diff --git a/ext4_utils/include/ext4_utils/make_ext4fs.h b/ext4_utils/include/ext4_utils/make_ext4fs.h deleted file mode 100644 index 44e94810..00000000 --- a/ext4_utils/include/ext4_utils/make_ext4fs.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _MAKE_EXT4FS_H_ -#define _MAKE_EXT4FS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -struct selabel_handle; - -int make_ext4fs(const char *filename, long long len, - const char *mountpoint, struct selabel_handle *sehnd); -int make_ext4fs_directory_align(const char *filename, long long len, - const char *mountpoint, struct selabel_handle *sehnd, - const char *directory, unsigned eraseblk, - unsigned logicalblk); -int make_ext4fs_directory(const char *filename, long long len, - const char *mountpoint, struct selabel_handle *sehnd, - const char *directory); -int make_ext4fs_sparse_fd(int fd, long long len, - const char *mountpoint, struct selabel_handle *sehnd); -int make_ext4fs_sparse_fd_directory(int fd, long long len, - const char *mountpoint, struct selabel_handle *sehnd, - const char *directory); -int make_ext4fs_sparse_fd_align(int fd, long long len, - const char *mountpoint, struct selabel_handle *sehnd, - unsigned eraseblk, unsigned logicalblk); -int make_ext4fs_sparse_fd_directory_align(int fd, long long len, - const char *mountpoint, struct selabel_handle *sehnd, - const char *directory, unsigned eraseblk, unsigned logicalblk); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext4_utils/make_ext4fs.c b/ext4_utils/make_ext4fs.c deleted file mode 100644 index cadf55c1..00000000 --- a/ext4_utils/make_ext4fs.c +++ /dev/null @@ -1,931 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ext4_utils/make_ext4fs.h" - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "allocate.h" -#include "contents.h" -#include "ext4_utils/ext4_utils.h" -#include "ext4_utils/wipe.h" - -#ifdef _WIN32 - -#include - -/* These match the Linux definitions of these flags. - L_xx is defined to avoid conflicting with the win32 versions. -*/ -#undef S_IRWXU -#undef S_IRGRP -#undef S_IWGRP -#undef S_IXGRP -#undef S_IRWXG -#undef S_IROTH -#undef S_IWOTH -#undef S_IXOTH -#undef S_IRWXO -#undef S_ISUID -#undef S_ISGID -#undef S_ISVTX - -#define L_S_IRUSR 00400 -#define L_S_IWUSR 00200 -#define L_S_IXUSR 00100 -#define S_IRWXU (L_S_IRUSR | L_S_IWUSR | L_S_IXUSR) -#define S_IRGRP 00040 -#define S_IWGRP 00020 -#define S_IXGRP 00010 -#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) -#define S_IROTH 00004 -#define S_IWOTH 00002 -#define S_IXOTH 00001 -#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) -#define S_ISUID 0004000 -#define S_ISGID 0002000 -#define S_ISVTX 0001000 - -#else - -#include -#include - -#define O_BINARY 0 - -#endif - -#undef MAX_PATH -#define MAX_PATH 4096 -#define MAX_BLK_MAPPING_STR 1000 - -const int blk_file_major_ver = 1; -const int blk_file_minor_ver = 0; -const char *blk_file_header_fmt = "Base EXT4 version %d.%d"; - -/* TODO: Not implemented: - Allocating blocks in the same block group as the file inode - Hash or binary tree directories - Special files: sockets, devices, fifos - */ - -static int filter_dot(const struct dirent *d) -{ - return (strcmp(d->d_name, "..") && strcmp(d->d_name, ".")); -} - -static u32 build_default_directory_structure(const char *dir_path, - struct selabel_handle *sehnd) -{ - u32 inode; - u32 root_inode; - struct dentry dentries = { - .filename = "lost+found", - .file_type = EXT4_FT_DIR, - .mode = S_IRWXU, - .uid = 0, - .gid = 0, - .mtime = 0, - }; - root_inode = make_directory(0, 1, &dentries, 1); - inode = make_directory(root_inode, 0, NULL, 0); - *dentries.inode = inode; - inode_set_permissions(inode, dentries.mode, - dentries.uid, dentries.gid, dentries.mtime); - -#ifndef _WIN32 - if (sehnd) { - char *path = NULL; - char *secontext = NULL; - - asprintf(&path, "%slost+found", dir_path); - if (selabel_lookup(sehnd, &secontext, path, S_IFDIR) < 0) { - error("cannot lookup security context for %s", path); - } else { - inode_set_selinux(inode, secontext); - freecon(secontext); - } - free(path); - } -#endif - - return root_inode; -} - -#ifndef _WIN32 -/* Read a local directory and create the same tree in the generated filesystem. - Calls itself recursively with each directory in the given directory. - full_path is an absolute or relative path, with a trailing slash, to the - directory on disk that should be copied, or NULL if this is a directory - that does not exist on disk (e.g. lost+found). - dir_path is an absolute path, with trailing slash, to the same directory - if the image were mounted at the specified mount point */ -static u32 build_directory_structure(const char *full_path, const char *dir_path, const char *target_out_path, - u32 dir_inode, fs_config_func_t fs_config_func, - struct selabel_handle *sehnd, int verbose, time_t fixed_time) -{ - int entries = 0; - struct dentry *dentries; - struct dirent **namelist = NULL; - struct stat stat; - int ret; - int i, j; - u32 inode; - u32 entry_inode; - u32 dirs = 0; - bool needs_lost_and_found = false; - - if (full_path) { - entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort); - if (entries < 0) { -#ifdef __GLIBC__ - /* The scandir function implemented in glibc has a bug that makes it - erroneously fail with ENOMEM under certain circumstances. - As a workaround we can retry the scandir call with the same arguments. - GLIBC BZ: https://sourceware.org/bugzilla/show_bug.cgi?id=17804 */ - if (errno == ENOMEM) - entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort); -#endif - if (entries < 0) { - error_errno("scandir"); - return EXT4_ALLOCATE_FAILED; - } - } - } - - if (dir_inode == 0) { - /* root directory, check if lost+found already exists */ - for (i = 0; i < entries; i++) - if (strcmp(namelist[i]->d_name, "lost+found") == 0) - break; - if (i == entries) - needs_lost_and_found = true; - } - - dentries = calloc(entries, sizeof(struct dentry)); - if (dentries == NULL) - critical_error_errno("malloc"); - - for (i = j = 0; i < entries; i++, j++) { - dentries[i].filename = strdup(namelist[j]->d_name); - if (dentries[i].filename == NULL) - critical_error_errno("strdup"); - - asprintf(&dentries[i].path, "%s%s", dir_path, namelist[j]->d_name); - asprintf(&dentries[i].full_path, "%s%s", full_path, namelist[j]->d_name); - - free(namelist[j]); - - ret = lstat(dentries[i].full_path, &stat); - if (ret < 0) { - error_errno("lstat"); - free(dentries[i].filename); - i--; - continue; - } - - dentries[i].size = stat.st_size; - dentries[i].mode = stat.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO); - if (fixed_time == -1) { - dentries[i].mtime = stat.st_mtime; - } else { - dentries[i].mtime = fixed_time; - } - uint64_t capabilities; - if (fs_config_func != NULL) { -#ifdef ANDROID - unsigned int mode = 0; - unsigned int uid = 0; - unsigned int gid = 0; - int dir = S_ISDIR(stat.st_mode); - fs_config_func(dentries[i].path, dir, target_out_path, &uid, &gid, &mode, &capabilities); - dentries[i].mode = mode; - dentries[i].uid = uid; - dentries[i].gid = gid; - dentries[i].capabilities = capabilities; -#else - error("can't set android permissions - built without android support"); -#endif - } -#ifndef _WIN32 - if (sehnd) { - if (selabel_lookup(sehnd, &dentries[i].secon, dentries[i].path, stat.st_mode) < 0) { - error("cannot lookup security context for %s", dentries[i].path); - } - - if (dentries[i].secon && verbose) - printf("Labeling %s as %s\n", dentries[i].path, dentries[i].secon); - } -#endif - - if (S_ISREG(stat.st_mode)) { - dentries[i].file_type = EXT4_FT_REG_FILE; - } else if (S_ISDIR(stat.st_mode)) { - dentries[i].file_type = EXT4_FT_DIR; - dirs++; - } else if (S_ISCHR(stat.st_mode)) { - dentries[i].file_type = EXT4_FT_CHRDEV; - } else if (S_ISBLK(stat.st_mode)) { - dentries[i].file_type = EXT4_FT_BLKDEV; - } else if (S_ISFIFO(stat.st_mode)) { - dentries[i].file_type = EXT4_FT_FIFO; - } else if (S_ISSOCK(stat.st_mode)) { - dentries[i].file_type = EXT4_FT_SOCK; - } else if (S_ISLNK(stat.st_mode)) { - dentries[i].file_type = EXT4_FT_SYMLINK; - dentries[i].link = calloc(info.block_size, 1); - readlink(dentries[i].full_path, dentries[i].link, info.block_size - 1); - } else { - error("unknown file type on %s", dentries[i].path); - free(dentries[i].filename); - i--; - } - } - entries -= j - i; - free(namelist); - - if (needs_lost_and_found) { - /* insert a lost+found directory at the beginning of the dentries */ - struct dentry *tmp = calloc(entries + 1, sizeof(struct dentry)); - memset(tmp, 0, sizeof(struct dentry)); - memcpy(tmp + 1, dentries, entries * sizeof(struct dentry)); - dentries = tmp; - - dentries[0].filename = strdup("lost+found"); - asprintf(&dentries[0].path, "%slost+found", dir_path); - dentries[0].full_path = NULL; - dentries[0].size = 0; - dentries[0].mode = S_IRWXU; - dentries[0].file_type = EXT4_FT_DIR; - dentries[0].uid = 0; - dentries[0].gid = 0; - if (sehnd) { - if (selabel_lookup(sehnd, &dentries[0].secon, dentries[0].path, dentries[0].mode) < 0) - error("cannot lookup security context for %s", dentries[0].path); - } - entries++; - dirs++; - } - - inode = make_directory(dir_inode, entries, dentries, dirs); - - for (i = 0; i < entries; i++) { - if (dentries[i].file_type == EXT4_FT_REG_FILE) { - entry_inode = make_file(dentries[i].full_path, dentries[i].size); - } else if (dentries[i].file_type == EXT4_FT_DIR) { - char *subdir_full_path = NULL; - char *subdir_dir_path; - if (dentries[i].full_path) { - ret = asprintf(&subdir_full_path, "%s/", dentries[i].full_path); - if (ret < 0) - critical_error_errno("asprintf"); - } - ret = asprintf(&subdir_dir_path, "%s/", dentries[i].path); - if (ret < 0) - critical_error_errno("asprintf"); - entry_inode = build_directory_structure(subdir_full_path, subdir_dir_path, target_out_path, - inode, fs_config_func, sehnd, verbose, fixed_time); - free(subdir_full_path); - free(subdir_dir_path); - } else if (dentries[i].file_type == EXT4_FT_SYMLINK) { - entry_inode = make_link(dentries[i].link); - } else { - error("unknown file type on %s", dentries[i].path); - entry_inode = 0; - } - *dentries[i].inode = entry_inode; - - ret = inode_set_permissions(entry_inode, dentries[i].mode, - dentries[i].uid, dentries[i].gid, - dentries[i].mtime); - if (ret) - error("failed to set permissions on %s\n", dentries[i].path); - - /* - * It's important to call inode_set_selinux() before - * inode_set_capabilities(). Extended attributes need to - * be stored sorted order, and we guarantee this by making - * the calls in the proper order. - * Please see xattr_assert_sane() in contents.c - */ - ret = inode_set_selinux(entry_inode, dentries[i].secon); - if (ret) - error("failed to set SELinux context on %s\n", dentries[i].path); - ret = inode_set_capabilities(entry_inode, dentries[i].capabilities); - if (ret) - error("failed to set capability on %s\n", dentries[i].path); - - free(dentries[i].path); - free(dentries[i].full_path); - free(dentries[i].link); - free((void *)dentries[i].filename); - free(dentries[i].secon); - } - - free(dentries); - return inode; -} -#endif - -static u32 compute_block_size() -{ - return 4096; -} - -static u32 compute_journal_blocks() -{ - u32 journal_blocks = DIV_ROUND_UP(info.len, info.block_size) / 64; - if (journal_blocks < 1024) - journal_blocks = 1024; - if (journal_blocks > 32768) - journal_blocks = 32768; - return journal_blocks; -} - -static u32 compute_blocks_per_group() -{ - return info.block_size * 8; -} - -static u32 compute_inodes() -{ - return DIV_ROUND_UP(info.len, info.block_size) / 4; -} - -static u32 compute_inodes_per_group() -{ - u32 blocks = DIV_ROUND_UP(info.len, info.block_size); - u32 block_groups = DIV_ROUND_UP(blocks, info.blocks_per_group); - u32 inodes = DIV_ROUND_UP(info.inodes, block_groups); - inodes = EXT4_ALIGN(inodes, (info.block_size / info.inode_size)); - - /* After properly rounding up the number of inodes/group, - * make sure to update the total inodes field in the info struct. - */ - info.inodes = inodes * block_groups; - - return inodes; -} - -static u32 compute_bg_desc_reserve_blocks() -{ - u32 blocks = DIV_ROUND_UP(info.len, info.block_size); - u32 block_groups = DIV_ROUND_UP(blocks, info.blocks_per_group); - u32 bg_desc_blocks = DIV_ROUND_UP(block_groups * sizeof(struct ext2_group_desc), - info.block_size); - - u32 bg_desc_reserve_blocks = - DIV_ROUND_UP(block_groups * 1024 * sizeof(struct ext2_group_desc), - info.block_size) - bg_desc_blocks; - - if (bg_desc_reserve_blocks > info.block_size / sizeof(u32)) - bg_desc_reserve_blocks = info.block_size / sizeof(u32); - - return bg_desc_reserve_blocks; -} - -void reset_ext4fs_info() { - // Reset all the global data structures used by make_ext4fs so it - // can be called again. - memset(&info, 0, sizeof(info)); - memset(&aux_info, 0, sizeof(aux_info)); - - if (ext4_sparse_file) { - sparse_file_destroy(ext4_sparse_file); - ext4_sparse_file = NULL; - } -} - -int make_ext4fs_sparse_fd(int fd, long long len, - const char *mountpoint, struct selabel_handle *sehnd) -{ - return make_ext4fs_sparse_fd_align(fd, len, mountpoint, sehnd, 0, 0); -} - -int make_ext4fs_sparse_fd_align(int fd, long long len, - const char *mountpoint, struct selabel_handle *sehnd, - unsigned eraseblk, unsigned logicalblk) -{ - return make_ext4fs_sparse_fd_directory_align(fd, len, mountpoint, sehnd, NULL, - eraseblk, logicalblk); -} - -int make_ext4fs_sparse_fd_directory(int fd, long long len, - const char *mountpoint, struct selabel_handle *sehnd, - const char *directory) -{ - return make_ext4fs_sparse_fd_directory_align(fd, len, mountpoint, sehnd, directory, 0, 0); -} - -int make_ext4fs_sparse_fd_directory_align(int fd, long long len, - const char *mountpoint, struct selabel_handle *sehnd, - const char *directory, unsigned eraseblk, unsigned logicalblk) -{ - reset_ext4fs_info(); - info.len = len; - info.flash_erase_block_size = eraseblk; - info.flash_logical_block_size = logicalblk; - - return make_ext4fs_internal(fd, directory, NULL, mountpoint, NULL, - 0, 1, 0, 0, 0, - sehnd, 0, -1, NULL, NULL, NULL); -} - -int make_ext4fs(const char *filename, long long len, - const char *mountpoint, struct selabel_handle *sehnd) -{ - return make_ext4fs_directory(filename, len, mountpoint, sehnd, NULL); -} - -int make_ext4fs_directory(const char *filename, long long len, - const char *mountpoint, struct selabel_handle *sehnd, - const char *directory) -{ - return make_ext4fs_directory_align(filename, len, mountpoint, sehnd, directory, 0, 0); -} - -int make_ext4fs_directory_align(const char *filename, long long len, - const char *mountpoint, struct selabel_handle *sehnd, - const char *directory, unsigned eraseblk, - unsigned logicalblk) -{ - int fd; - int status; - - reset_ext4fs_info(); - info.len = len; - info.flash_erase_block_size = eraseblk; - info.flash_logical_block_size = logicalblk; - - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); - if (fd < 0) { - error_errno("open"); - return EXIT_FAILURE; - } - - status = make_ext4fs_internal(fd, directory, NULL, mountpoint, NULL, - 0, 0, 0, 1, 0, - sehnd, 0, -1, NULL, NULL, NULL); - close(fd); - - return status; -} - -/* return a newly-malloc'd string that is a copy of str. The new string - is guaranteed to have a trailing slash. If absolute is true, the new string - is also guaranteed to have a leading slash. -*/ -static char *canonicalize_slashes(const char *str, bool absolute) -{ - char *ret; - int len = strlen(str); - int newlen = len; - char *ptr; - - if (len == 0) { - if (absolute) - return strdup("/"); - else - return strdup(""); - } - - if (str[0] != '/' && absolute) { - newlen++; - } - if (str[len - 1] != '/') { - newlen++; - } - ret = malloc(newlen + 1); - if (!ret) { - critical_error("malloc"); - } - - ptr = ret; - if (str[0] != '/' && absolute) { - *ptr++ = '/'; - } - - strcpy(ptr, str); - ptr += len; - - if (str[len - 1] != '/') { - *ptr++ = '/'; - } - - if (ptr != ret + newlen) { - critical_error("assertion failed\n"); - } - - *ptr = '\0'; - - return ret; -} - -static char *canonicalize_abs_slashes(const char *str) -{ - return canonicalize_slashes(str, true); -} - -static char *canonicalize_rel_slashes(const char *str) -{ - return canonicalize_slashes(str, false); -} - -static int compare_chunks(const void* chunk1, const void* chunk2) { - struct region* c1 = (struct region*) chunk1; - struct region* c2 = (struct region*) chunk2; - return c1->block - c2->block; -} - -static int get_block_group(u32 block) { - unsigned int i, group = 0; - - for(i = 0; i < aux_info.groups; i++) { - if (block >= aux_info.bgs[i].first_block) - group = i; - else - break; - } - return group; -} - -static void extract_base_fs_allocations(const char *directory, const char *mountpoint, - FILE* base_alloc_file_in) { -#define err_msg "base file badly formatted" -#ifndef _WIN32 - // FORMAT Version 1.0: filename blk_mapping - const char *base_alloc_file_in_format = "%s %s"; - const int base_file_format_param_count = 2; - - char stored_file_name[MAX_PATH], real_file_name[MAX_PATH], file_map[MAX_BLK_MAPPING_STR]; - struct block_allocation *fs_alloc; - struct block_group_info *bgs = aux_info.bgs; - int major_version = 0, minor_version = 0; - unsigned int i; - char *base_file_line = NULL; - size_t base_file_line_len = 0; - - printf("[v%d.%d] Generating an Incremental EXT4 image\n", - blk_file_major_ver, blk_file_minor_ver); - if (base_fs_allocations == NULL) - base_fs_allocations = create_allocation(); - fs_alloc = base_fs_allocations; - - fscanf(base_alloc_file_in, blk_file_header_fmt, &major_version, &minor_version); - if (major_version == 0) { - critical_error("Invalid base file"); - } - - if (major_version != blk_file_major_ver) { - critical_error("Incompatible base file: version required is %d.X", - blk_file_major_ver); - } - - if (minor_version < blk_file_minor_ver) { - critical_error("Incompatible base file: version required is %d.%d or above", - blk_file_major_ver, blk_file_minor_ver); - } - - while (getline(&base_file_line, &base_file_line_len, base_alloc_file_in) != -1) { - if (sscanf(base_file_line, base_alloc_file_in_format, &stored_file_name, &file_map) - != base_file_format_param_count) { - continue; - } - if (strlen(stored_file_name) < strlen(mountpoint)) { - continue; - } - snprintf(real_file_name, MAX_PATH, "%s%s", directory, stored_file_name + strlen(mountpoint)); - if (!access(real_file_name, R_OK)) { - char *block_range, *end_string; - int real_file_fd; - int start_block, end_block; - u32 block_file_size; - u32 real_file_block_size; - struct stat buf; - - if (lstat(real_file_name, &buf) == -1) - critical_error(err_msg); - - if (!S_ISREG(buf.st_mode)) - continue; - - real_file_fd = open(real_file_name, O_RDONLY); - if (real_file_fd == -1) { - critical_error(err_msg); - } - real_file_block_size = get_file_size(real_file_fd); - close(real_file_fd); - real_file_block_size = DIV_ROUND_UP(real_file_block_size, info.block_size); - fs_alloc->filename = strdup(real_file_name); - block_range = strtok_r(file_map, ",", &end_string); - while (block_range && real_file_block_size) { - int block_group; - char *range, *end_token = NULL; - range = strtok_r(block_range, "-", &end_token); - if (!range) { - critical_error(err_msg); - } - start_block = parse_num(range); - range = strtok_r(NULL, "-", &end_token); - if (!range) { - end_block = start_block; - } else { - end_block = parse_num(range); - } - // Assummption is that allocations are within the same block group - block_group = get_block_group(start_block); - if (block_group != get_block_group(end_block)) { - critical_error("base file allocation's end block is in a different " - "block group than start block. did you change fs params?"); - } - block_range = strtok_r(NULL, ",", &end_string); - int bg_first_block = bgs[block_group].first_block; - int min_bg_bound = bgs[block_group].chunks[0].block + bgs[block_group].chunks[0].len; - int max_bg_bound = bgs[block_group].chunks[bgs[block_group].chunk_count - 1].block; - - if (min_bg_bound >= start_block - bg_first_block || - max_bg_bound <= end_block - bg_first_block) { - continue; - } - block_file_size = end_block - start_block + 1; - if (block_file_size > real_file_block_size) { - block_file_size = real_file_block_size; - } - append_region(fs_alloc, start_block, block_file_size, block_group); - reserve_bg_chunk(block_group, start_block - bgs[block_group].first_block, block_file_size); - real_file_block_size -= block_file_size; - } - if (reserve_blocks_for_allocation(fs_alloc) < 0) - critical_error("failed to reserve base fs allocation"); - fs_alloc->next = create_allocation(); - fs_alloc = fs_alloc->next; - } - } - - for (i = 0; i < aux_info.groups; i++) { - qsort(bgs[i].chunks, bgs[i].chunk_count, sizeof(struct region), compare_chunks); - } - - free(base_file_line); - -#else - return; -#endif -#undef err_msg -} - -void generate_base_alloc_file_out(FILE* base_alloc_file_out, char* dir, char* mountpoint, - struct block_allocation* p) -{ - size_t dirlen = dir ? strlen(dir) : 0; - fprintf(base_alloc_file_out, blk_file_header_fmt, blk_file_major_ver, blk_file_minor_ver); - fputc('\n', base_alloc_file_out); - while (p) { - if (dir && strncmp(p->filename, dir, dirlen) == 0) { - // substitute mountpoint for the leading directory in the filename, in the output file - fprintf(base_alloc_file_out, "%s%s", mountpoint, p->filename + dirlen); - } else { - fprintf(base_alloc_file_out, "%s", p->filename); - } - print_blocks(base_alloc_file_out, p, ','); - struct block_allocation* pn = p->next; - p = pn; - } -} - -int make_ext4fs_internal(int fd, const char *_directory, const char *_target_out_directory, - const char *_mountpoint, fs_config_func_t fs_config_func, int gzip, - int sparse, int crc, int wipe, int real_uuid, - struct selabel_handle *sehnd, int verbose, time_t fixed_time, - FILE* block_list_file, FILE* base_alloc_file_in, FILE* base_alloc_file_out) -{ - u32 root_inode_num; - u16 root_mode; - char *mountpoint; - char *directory = NULL; - char *target_out_directory = NULL; - struct block_allocation* p; - - if (setjmp(setjmp_env)) - return EXIT_FAILURE; /* Handle a call to longjmp() */ - - info.block_device = is_block_device_fd(fd); - - if (info.block_device && (sparse || gzip || crc)) { - fprintf(stderr, "No sparse/gzip/crc allowed for block device\n"); - return EXIT_FAILURE; - } - - if (_mountpoint == NULL) { - mountpoint = strdup(""); - } else { - mountpoint = canonicalize_abs_slashes(_mountpoint); - } - - if (_directory) { - directory = canonicalize_rel_slashes(_directory); - } - - if (_target_out_directory) { - target_out_directory = canonicalize_rel_slashes(_target_out_directory); - } - - if (info.len <= 0) - info.len = get_file_size(fd); - - if (info.block_size <= 0) - info.block_size = compute_block_size(); - - /* Round down the filesystem length to be a multiple of the block size */ - info.len &= ~((u64)info.block_size - 1); - - if (info.len <= 0) { - fprintf(stderr, "filesystem size too small\n"); - free(mountpoint); - return EXIT_FAILURE; - } - - if (info.journal_blocks == 0) - info.journal_blocks = compute_journal_blocks(); - - if (info.no_journal == 0) - info.feat_compat = EXT4_FEATURE_COMPAT_HAS_JOURNAL; - else - info.journal_blocks = 0; - - if (info.blocks_per_group <= 0) - info.blocks_per_group = compute_blocks_per_group(); - - if (info.inodes <= 0) - info.inodes = compute_inodes(); - - if (info.inode_size <= 0) - info.inode_size = 256; - - if (info.label == NULL) - info.label = ""; - - info.inodes_per_group = compute_inodes_per_group(); - - info.feat_compat |= - EXT4_FEATURE_COMPAT_RESIZE_INODE | - EXT4_FEATURE_COMPAT_EXT_ATTR; - - info.feat_ro_compat |= - EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER | - EXT4_FEATURE_RO_COMPAT_LARGE_FILE | - EXT4_FEATURE_RO_COMPAT_GDT_CSUM; - - info.feat_incompat |= - EXT4_FEATURE_INCOMPAT_EXTENTS | - EXT4_FEATURE_INCOMPAT_FILETYPE; - - - info.bg_desc_reserve_blocks = compute_bg_desc_reserve_blocks(); - - printf("Creating filesystem with parameters:\n"); - printf(" Size: %"PRIu64"\n", info.len); - printf(" Block size: %d\n", info.block_size); - printf(" Blocks per group: %d\n", info.blocks_per_group); - printf(" Inodes per group: %d\n", info.inodes_per_group); - printf(" Inode size: %d\n", info.inode_size); - printf(" Journal blocks: %d\n", info.journal_blocks); - printf(" Label: %s\n", info.label); - - ext4_create_fs_aux_info(); - - printf(" Blocks: %"PRIext4u64"\n", aux_info.len_blocks); - printf(" Block groups: %d\n", aux_info.groups); - printf(" Reserved block group size: %d\n", info.bg_desc_reserve_blocks); - - ext4_sparse_file = sparse_file_new(info.block_size, info.len); - - block_allocator_init(); - - ext4_fill_in_sb(real_uuid); - - if (base_alloc_file_in) { - extract_base_fs_allocations(directory, mountpoint, base_alloc_file_in); - } - if (reserve_inodes(0, 10) == EXT4_ALLOCATE_FAILED) - error("failed to reserve first 10 inodes"); - - if (info.feat_compat & EXT4_FEATURE_COMPAT_HAS_JOURNAL) - ext4_create_journal_inode(); - - if (info.feat_compat & EXT4_FEATURE_COMPAT_RESIZE_INODE) - ext4_create_resize_inode(); - -#ifdef _WIN32 - // Windows needs only 'create an empty fs image' functionality - assert(!directory); - root_inode_num = build_default_directory_structure(mountpoint, sehnd); -#else - if (directory) - root_inode_num = build_directory_structure(directory, mountpoint, target_out_directory, 0, - fs_config_func, sehnd, verbose, fixed_time); - else - root_inode_num = build_default_directory_structure(mountpoint, sehnd); -#endif - - root_mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - inode_set_permissions(root_inode_num, root_mode, 0, 0, 0); - -#ifndef _WIN32 - if (sehnd) { - char *secontext = NULL; - - if (selabel_lookup(sehnd, &secontext, mountpoint, S_IFDIR) < 0) { - error("cannot lookup security context for %s", mountpoint); - } - if (secontext) { - if (verbose) { - printf("Labeling %s as %s\n", mountpoint, secontext); - } - inode_set_selinux(root_inode_num, secontext); - } - freecon(secontext); - } -#endif - - ext4_update_free(); - - // TODO: Consider migrating the OTA tools to the new base alloc file format - // used for generating incremental images (see go/incremental-ext4) - if (block_list_file) { - size_t dirlen = directory ? strlen(directory) : 0; - struct block_allocation* p = get_saved_allocation_chain(); - while (p) { - if (directory && strncmp(p->filename, directory, dirlen) == 0) { - // substitute mountpoint for the leading directory in the filename, in the output file - fprintf(block_list_file, "%s%s", mountpoint, p->filename + dirlen); - } else { - fprintf(block_list_file, "%s", p->filename); - } - print_blocks(block_list_file, p, ' '); - struct block_allocation* pn = p->next; - p = pn; - } - } - - if (base_alloc_file_out) { - struct block_allocation* p = get_saved_allocation_chain(); - generate_base_alloc_file_out(base_alloc_file_out, directory, mountpoint, p); - } - - printf("Created filesystem with %d/%d inodes and %d/%d blocks\n", - aux_info.sb->s_inodes_count - aux_info.sb->s_free_inodes_count, - aux_info.sb->s_inodes_count, - aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo, - aux_info.sb->s_blocks_count_lo); - - if (wipe && WIPE_IS_SUPPORTED) { - wipe_block_device(fd, info.len); - } - - write_ext4_image(fd, gzip, sparse, crc); - - sparse_file_destroy(ext4_sparse_file); - ext4_sparse_file = NULL; - - p = get_saved_allocation_chain(); - while (p) { - struct block_allocation* pn = p->next; - free_alloc(p); - p = pn; - } - - free(mountpoint); - free(directory); - - return 0; -} diff --git a/ext4_utils/make_ext4fs_main.c b/ext4_utils/make_ext4fs_main.c deleted file mode 100644 index 77930cd4..00000000 --- a/ext4_utils/make_ext4fs_main.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#if defined(__linux__) -#include -#elif defined(__APPLE__) && defined(__MACH__) -#include -#endif - -#ifdef ANDROID -#include -#include -#endif - -#ifndef _WIN32 -#include -#include -#if !defined(HOST) -#include -#endif -#else -struct selabel_handle; -#endif - -#include "ext4_utils/ext4_utils.h" -#include "ext4_utils/make_ext4fs.h" - -#ifndef _WIN32 /* O_BINARY is windows-specific flag */ -#define O_BINARY 0 -#endif - -extern struct fs_info info; - - -static void usage(char *path) -{ - fprintf(stderr, "%s [ -l ] [ -j ] [ -b ]\n", basename(path)); - fprintf(stderr, " [ -g ] [ -i ] [ -I ]\n"); - fprintf(stderr, " [ -e ] [ -o ]\n"); - fprintf(stderr, " [ -L