make_ext4fs.c revision 8aef66d2125af8de7672a12895276802fcc1948f
1ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* 2ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * Copyright (C) 2010 The Android Open Source Project 3ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * 4ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * Licensed under the Apache License, Version 2.0 (the "License"); 5ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * you may not use this file except in compliance with the License. 6ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * You may obtain a copy of the License at 7ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * 8ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * http://www.apache.org/licenses/LICENSE-2.0 9ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * 10ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * Unless required by applicable law or agreed to in writing, software 11ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * distributed under the License is distributed on an "AS IS" BASIS, 12ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * See the License for the specific language governing permissions and 14ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * limitations under the License. 15ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross */ 16ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 17ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#define _GNU_SOURCE 18ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 19ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <sys/types.h> 20ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <sys/ioctl.h> 21ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <sys/stat.h> 227a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross#include <sys/ioctl.h> 23ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <limits.h> 24ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <arpa/inet.h> 25ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <fcntl.h> 26ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <stdlib.h> 27ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <strings.h> 28ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <string.h> 29ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <stdio.h> 30ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <dirent.h> 31ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <libgen.h> 32ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 334b83b8acdcc4dad375adaf0f3b41fc41b22ee742Colin Cross#if defined(__linux__) 34ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <linux/fs.h> 35ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#elif defined(__APPLE__) && defined(__MACH__) 36ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <sys/disk.h> 37ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#endif 38ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 39ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "make_ext4fs.h" 407a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross#include "output_file.h" 41ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "ext4_utils.h" 42ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "allocate.h" 43ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "ext_utils.h" 44ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "backed_block.h" 45ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "contents.h" 46ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "extent.h" 47ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "indirect.h" 48ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "uuid.h" 49ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 50ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "jbd2.h" 51ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "ext4.h" 52ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 53ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#ifdef ANDROID 54ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <private/android_filesystem_config.h> 55ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#endif 56ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 57ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* TODO: Not implemented: 58ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross Allocating blocks in the same block group as the file inode 59ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross Hash or binary tree directories 607a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross Special files: sockets, devices, fifos 61ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross */ 62ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 63ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossint force = 0; 64ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 65ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstruct fs_info info; 66ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstruct fs_aux_info aux_info; 67ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 68ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Write the filesystem image to a file */ 697a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Crossstatic void write_ext4_image(const char *filename, int gz) 70ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 71ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int ret = 0; 727a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross struct output_file *out = open_output_file(filename, gz); 73ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross off_t off; 74ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 757a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross if (!out) 76ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 77ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 787a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross write_data_block(out, 1024, (u8*)aux_info.sb, 1024); 79ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 807a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross write_data_block(out, (aux_info.first_data_block + 1) * info.block_size, 817a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross (u8*)aux_info.bg_desc, 827a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross aux_info.bg_desc_blocks * info.block_size); 83ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 847a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross for_each_data_block(write_data_block, write_data_file, out); 85ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 867a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross write_data_block(out, info.len - 1, (u8*)"", 1); 87ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 887a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross close_output_file(out); 89ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 90ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 91ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Compute the rest of the parameters of the filesystem from the basic info */ 92ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void ext4_create_fs_aux_info() 93ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 94ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.first_data_block = (info.block_size > 1024) ? 0 : 1; 95ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.len_blocks = info.len / info.block_size; 96ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.inode_table_blocks = DIV_ROUND_UP(info.inodes_per_group * info.inode_size, 978aef66d2125af8de7672a12895276802fcc1948fColin Cross info.block_size); 98ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.groups = DIV_ROUND_UP(aux_info.len_blocks - aux_info.first_data_block, 998aef66d2125af8de7672a12895276802fcc1948fColin Cross info.blocks_per_group); 100ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.blocks_per_ind = info.block_size / sizeof(u32); 101ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.blocks_per_dind = aux_info.blocks_per_ind * aux_info.blocks_per_ind; 102ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.blocks_per_tind = aux_info.blocks_per_dind * aux_info.blocks_per_dind; 103ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 104ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc_blocks = 1058aef66d2125af8de7672a12895276802fcc1948fColin Cross DIV_ROUND_UP(aux_info.groups * sizeof(struct ext2_group_desc), 1068aef66d2125af8de7672a12895276802fcc1948fColin Cross info.block_size); 107ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 108ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc_reserve_blocks = 1098aef66d2125af8de7672a12895276802fcc1948fColin Cross DIV_ROUND_UP(aux_info.groups * 1024 * sizeof(struct ext2_group_desc), 1108aef66d2125af8de7672a12895276802fcc1948fColin Cross info.block_size) - aux_info.bg_desc_blocks; 111ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 112ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (aux_info.bg_desc_reserve_blocks > aux_info.blocks_per_ind) 113ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc_reserve_blocks = aux_info.blocks_per_ind; 114ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 115ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.default_i_flags = EXT4_NOATIME_FL; 116ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 117ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 last_group_size = aux_info.len_blocks % info.blocks_per_group; 118ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 last_header_size = 2 + aux_info.inode_table_blocks; 119ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (ext4_bg_has_super_block(aux_info.groups - 1)) 120ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross last_header_size += 1 + aux_info.bg_desc_blocks + 121ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc_reserve_blocks; 122ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (last_group_size > 0 && last_group_size < last_header_size) { 123ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.groups--; 124ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.len_blocks -= last_group_size; 125ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 126ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 127ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.sb = calloc(info.block_size, 1); 128ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (!aux_info.sb) 129ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error_errno("calloc"); 130ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 131ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc = calloc(info.block_size, aux_info.bg_desc_blocks); 132ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (!aux_info.bg_desc) 133ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error_errno("calloc"); 134ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 135ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 136ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossvoid ext4_free_fs_aux_info() 137ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 138ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free(aux_info.sb); 139ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free(aux_info.bg_desc); 140ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 141ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 142ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Fill in the superblock memory buffer based on the filesystem parameters */ 143ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void ext4_fill_in_sb() 144ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 145ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross unsigned int i; 146ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct ext4_super_block *sb = aux_info.sb; 147ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 148ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_inodes_count = info.inodes_per_group * aux_info.groups; 149ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_blocks_count_lo = aux_info.len_blocks; 150ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_r_blocks_count_lo = 0; 151ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_free_blocks_count_lo = 0; 152ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_free_inodes_count = 0; 153ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_first_data_block = aux_info.first_data_block; 154ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_log_block_size = log_2(info.block_size / 1024); 155ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_obso_log_frag_size = log_2(info.block_size / 1024); 156ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_blocks_per_group = info.blocks_per_group; 157ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_obso_frags_per_group = info.blocks_per_group; 158ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_inodes_per_group = info.inodes_per_group; 159ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_mtime = 0; 160ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_wtime = 0; 161ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_mnt_count = 0; 162ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_max_mnt_count = 0xFFFF; 163ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_magic = EXT4_SUPER_MAGIC; 164ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_state = EXT4_VALID_FS; 165ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_errors = EXT4_ERRORS_RO; 166ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_minor_rev_level = 0; 167ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_lastcheck = 0; 168ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_checkinterval = 0; 169ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_creator_os = EXT4_OS_LINUX; 170ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_rev_level = EXT4_DYNAMIC_REV; 171ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_def_resuid = EXT4_DEF_RESUID; 172ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_def_resgid = EXT4_DEF_RESGID; 173ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 174ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_first_ino = EXT4_GOOD_OLD_FIRST_INO; 175ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_inode_size = info.inode_size; 176ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_block_group_nr = 0; 177ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_feature_compat = info.feat_compat; 178ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_feature_incompat = info.feat_incompat; 179ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_feature_ro_compat = info.feat_ro_compat; 180ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross generate_uuid("extandroid/make_ext4fs", info.label, sb->s_uuid); 181ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name)); 182ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross strncpy(sb->s_volume_name, info.label, sizeof(sb->s_volume_name)); 183ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted)); 184ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_algorithm_usage_bitmap = 0; 185ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 186ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_reserved_gdt_blocks = aux_info.bg_desc_reserve_blocks; 187ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_prealloc_blocks = 0; 188ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_prealloc_dir_blocks = 0; 189ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 190ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross //memcpy(sb->s_journal_uuid, sb->s_uuid, sizeof(sb->s_journal_uuid)); 191ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (info.feat_compat & EXT4_FEATURE_COMPAT_HAS_JOURNAL) 192ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_journal_inum = EXT4_JOURNAL_INO; 193ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_journal_dev = 0; 194ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_last_orphan = 0; 195ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_hash_seed[0] = 0; /* FIXME */ 196ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_def_hash_version = DX_HASH_TEA; 197ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_reserved_char_pad = EXT4_JNL_BACKUP_BLOCKS; 198ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_desc_size = sizeof(struct ext2_group_desc); 199ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_default_mount_opts = 0; /* FIXME */ 200ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_first_meta_bg = 0; 201ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_mkfs_time = 0; 202ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross //sb->s_jnl_blocks[17]; /* FIXME */ 203ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 204ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_blocks_count_hi = aux_info.len_blocks >> 32; 205ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_r_blocks_count_hi = 0; 206ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_free_blocks_count_hi = 0; 2078aef66d2125af8de7672a12895276802fcc1948fColin Cross sb->s_min_extra_isize = sizeof(struct ext4_inode) - 2088aef66d2125af8de7672a12895276802fcc1948fColin Cross EXT4_GOOD_OLD_INODE_SIZE; 2098aef66d2125af8de7672a12895276802fcc1948fColin Cross sb->s_want_extra_isize = sizeof(struct ext4_inode) - 2108aef66d2125af8de7672a12895276802fcc1948fColin Cross EXT4_GOOD_OLD_INODE_SIZE; 211ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_flags = 0; 212ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_raid_stride = 0; 213ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_mmp_interval = 0; 214ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_mmp_block = 0; 215ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_raid_stripe_width = 0; 216ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_log_groups_per_flex = 0; 217ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross sb->s_kbytes_written = 0; 218ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 219ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (i = 0; i < aux_info.groups; i++) { 2208aef66d2125af8de7672a12895276802fcc1948fColin Cross u64 group_start_block = aux_info.first_data_block + i * 2218aef66d2125af8de7672a12895276802fcc1948fColin Cross info.blocks_per_group; 222ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 header_size = 0; 223ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (ext4_bg_has_super_block(i)) { 224ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (i != 0) { 225ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross queue_data_block((u8 *)sb, info.block_size, group_start_block); 226ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross queue_data_block((u8 *)aux_info.bg_desc, 2278aef66d2125af8de7672a12895276802fcc1948fColin Cross aux_info.bg_desc_blocks * info.block_size, 2288aef66d2125af8de7672a12895276802fcc1948fColin Cross group_start_block + 1); 229ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 230ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross header_size = 1 + aux_info.bg_desc_blocks + aux_info.bg_desc_reserve_blocks; 231ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 232ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 233ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc[i].bg_block_bitmap = group_start_block + header_size; 234ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc[i].bg_inode_bitmap = group_start_block + header_size + 1; 235ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc[i].bg_inode_table = group_start_block + header_size + 2; 236ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 237ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc[i].bg_free_blocks_count = sb->s_blocks_per_group; 238ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc[i].bg_free_inodes_count = sb->s_inodes_per_group; 239ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc[i].bg_used_dirs_count = 0; 240ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 241ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 242ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 243ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void ext4_create_resize_inode() 244ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 245ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct block_allocation *reserve_inode_alloc = create_allocation(); 246ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 reserve_inode_len = 0; 247ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross unsigned int i; 248ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 249ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct ext4_inode *inode = get_inode(EXT4_RESIZE_INO); 250ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (inode == NULL) { 251ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to get resize inode"); 252ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 253ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 254ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 255ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (i = 0; i < aux_info.groups; i++) { 256ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (ext4_bg_has_super_block(i)) { 257ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u64 group_start_block = aux_info.first_data_block + i * 2588aef66d2125af8de7672a12895276802fcc1948fColin Cross info.blocks_per_group; 259ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 reserved_block_start = group_start_block + 1 + 2608aef66d2125af8de7672a12895276802fcc1948fColin Cross aux_info.bg_desc_blocks; 261ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 reserved_block_len = aux_info.bg_desc_reserve_blocks; 262ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross append_region(reserve_inode_alloc, reserved_block_start, 2638aef66d2125af8de7672a12895276802fcc1948fColin Cross reserved_block_len, i); 264ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserve_inode_len += reserved_block_len; 265ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 266ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 267ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 268ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode_attach_resize(inode, reserve_inode_alloc); 269ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 270ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR; 271ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_links_count = 1; 272ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 273ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free_alloc(reserve_inode_alloc); 274ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 275ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 276ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Allocate the blocks to hold a journal inode and connect them to the 277ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross reserved journal inode */ 278ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void ext4_create_journal_inode() 279ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 280ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct ext4_inode *inode = get_inode(EXT4_JOURNAL_INO); 281ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (inode == NULL) { 282ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to get journal inode"); 283ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 284ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 285ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 286ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u8 *journal_data = inode_allocate_data_extents(inode, 287ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.journal_blocks * info.block_size, 2888aef66d2125af8de7672a12895276802fcc1948fColin Cross info.block_size); 289ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (!journal_data) { 290ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to allocate extents for journal data"); 291ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return; 292ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 293ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 294ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR; 295ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode->i_links_count = 1; 296ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 297ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross journal_superblock_t *jsb = (journal_superblock_t *)journal_data; 298ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross jsb->s_header.h_magic = htonl(JBD2_MAGIC_NUMBER); 299ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross jsb->s_header.h_blocktype = htonl(JBD2_SUPERBLOCK_V2); 300ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross jsb->s_blocksize = htonl(info.block_size); 301ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross jsb->s_maxlen = htonl(info.journal_blocks); 302ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross jsb->s_nr_users = htonl(1); 303ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross jsb->s_first = htonl(1); 304ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross jsb->s_sequence = htonl(1); 305ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 306ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross memcpy(aux_info.sb->s_jnl_blocks, &inode->i_block, sizeof(inode->i_block)); 307ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 308ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 309ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Update the number of free blocks and inodes in the filesystem and in each 310ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross block group */ 311ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void ext4_update_free() 312ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 313ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross unsigned int i; 314ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 315ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (i = 0; i < aux_info.groups; i++) { 316ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 bg_free_blocks = get_free_blocks(i); 317ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 bg_free_inodes = get_free_inodes(i); 318ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 319ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc[i].bg_free_blocks_count = bg_free_blocks; 320ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.sb->s_free_blocks_count_lo += bg_free_blocks; 321ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 322ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc[i].bg_free_inodes_count = bg_free_inodes; 323ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.sb->s_free_inodes_count += bg_free_inodes; 324ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 325ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.bg_desc[i].bg_used_dirs_count += get_directories(i); 326ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 327ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 328ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 329ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic int filter_dot(const struct dirent *d) 330ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 331ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return (strcmp(d->d_name, "..") && strcmp(d->d_name, ".")); 332ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 333ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 334ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u32 build_default_directory_structure() 335ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 336ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 inode; 337ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 root_inode; 338ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct dentry dentries = { 339ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross .filename = "lost+found", 340ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross .file_type = EXT4_FT_DIR, 341ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross .mode = S_IRWXU, 342ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross .uid = 0, 343ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross .gid = 0 344ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross }; 345ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross root_inode = make_directory(0, 1, &dentries, 1); 346ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode = make_directory(root_inode, 0, NULL, 0); 347ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross *dentries.inode = inode; 348ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 349ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return root_inode; 350ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 351ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 352ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Read a local directory and create the same tree in the generated filesystem. 353ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross Calls itself recursively with each directory in the given directory */ 354ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u32 build_directory_structure(const char *full_path, const char *dir_path, 355ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 dir_inode, int android) 356ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 357ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int entries = 0; 358ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct dentry *dentries; 359ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct dirent **namelist; 360ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct stat stat; 361ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int ret; 362ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int i; 363ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 inode; 364ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 entry_inode; 365ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 dirs = 0; 366ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 3678aef66d2125af8de7672a12895276802fcc1948fColin Cross entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort); 368ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (entries < 0) { 369ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error_errno("scandir"); 370ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return EXT4_ALLOCATE_FAILED; 371ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 372ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 373ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries = calloc(entries, sizeof(struct dentry)); 374ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (dentries == NULL) 375ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error_errno("malloc"); 376ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 377ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (i = 0; i < entries; i++) { 378ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].filename = strdup(namelist[i]->d_name); 379ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (dentries[i].filename == NULL) 380ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross critical_error_errno("strdup"); 381ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 382ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross asprintf(&dentries[i].path, "%s/%s", dir_path, namelist[i]->d_name); 383ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross asprintf(&dentries[i].full_path, "%s/%s", full_path, namelist[i]->d_name); 384ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 385ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free(namelist[i]); 386ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 387ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ret = lstat(dentries[i].full_path, &stat); 388ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (ret < 0) { 389ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error_errno("lstat"); 390ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross i--; 391ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross entries--; 392ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross continue; 393ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 394ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 395ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].size = stat.st_size; 396ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].mode = stat.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO); 397ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (android) { 398ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#ifdef ANDROID 399ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross unsigned int mode = 0; 400ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross unsigned int uid = 0; 401ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross unsigned int gid = 0; 402ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int dir = S_ISDIR(stat.st_mode); 403ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fs_config(dentries[i].path, dir, &uid, &gid, &mode); 404ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].mode = mode; 405ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].uid = uid; 406ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].gid = gid; 407ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#else 408ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("can't set android permissions - built without android support"); 409ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#endif 410ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 411ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 412ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (S_ISREG(stat.st_mode)) { 413ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].file_type = EXT4_FT_REG_FILE; 414ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } else if (S_ISDIR(stat.st_mode)) { 415ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].file_type = EXT4_FT_DIR; 416ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dirs++; 417ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } else if (S_ISCHR(stat.st_mode)) { 418ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].file_type = EXT4_FT_CHRDEV; 419ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } else if (S_ISBLK(stat.st_mode)) { 420ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].file_type = EXT4_FT_BLKDEV; 421ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } else if (S_ISFIFO(stat.st_mode)) { 422ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].file_type = EXT4_FT_FIFO; 423ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } else if (S_ISSOCK(stat.st_mode)) { 424ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].file_type = EXT4_FT_SOCK; 425ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } else if (S_ISLNK(stat.st_mode)) { 426ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].file_type = EXT4_FT_SYMLINK; 427ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].link = calloc(info.block_size, 1); 428ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross readlink(dentries[i].full_path, dentries[i].link, info.block_size - 1); 429ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } else { 430ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("unknown file type on %s", dentries[i].path); 431ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross i--; 432ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross entries--; 433ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 434ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 435ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free(namelist); 436ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 437ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode = make_directory(dir_inode, entries, dentries, dirs); 438ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 439ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross for (i = 0; i < entries; i++) { 440ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (dentries[i].file_type == EXT4_FT_REG_FILE) { 441ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross entry_inode = make_file(dentries[i].full_path, dentries[i].size); 442ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } else if (dentries[i].file_type == EXT4_FT_DIR) { 443ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross entry_inode = build_directory_structure(dentries[i].full_path, 444ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].path, inode, android); 445ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } else if (dentries[i].file_type == EXT4_FT_SYMLINK) { 446ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross entry_inode = make_link(dentries[i].full_path, dentries[i].link); 447ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } else { 448ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("unknown file type on %s", dentries[i].path); 449ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross entry_inode = 0; 450ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 451ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross *dentries[i].inode = entry_inode; 452ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 453ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ret = inode_set_permissions(entry_inode, dentries[i].mode, 454ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross dentries[i].uid, dentries[i].gid); 455ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (ret) 456ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to set permissions on %s\n", dentries[i].path); 457ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 458ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free(dentries[i].path); 459ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free(dentries[i].full_path); 460ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free(dentries[i].link); 461ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free((void *)dentries[i].filename); 462ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 463ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 464ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross free(dentries); 465ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return inode; 466ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 467ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 468ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u32 compute_block_size() 469ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 470ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return 4096; 471ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 472ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 473ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u32 compute_blocks_per_group() 474ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 475ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return info.block_size * 8; 476ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 477ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 478ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u32 compute_inodes() 479ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 480ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return DIV_ROUND_UP(info.len, info.block_size) / 4; 481ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 482ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 483ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u32 compute_inodes_per_group() 484ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 485ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 blocks = DIV_ROUND_UP(info.len, info.block_size); 486ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 block_groups = DIV_ROUND_UP(blocks, info.blocks_per_group); 487ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return DIV_ROUND_UP(info.inodes, block_groups); 488ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 489ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 490ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u64 get_block_device_size(const char *filename) 491ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 492ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int fd = open(filename, O_RDONLY); 493ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u64 size = 0; 494ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int ret; 495ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 496ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (fd < 0) 497ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return 0; 498ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 4994b83b8acdcc4dad375adaf0f3b41fc41b22ee742Colin Cross#if defined(__linux__) 500ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ret = ioctl(fd, BLKGETSIZE64, &size); 501ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#elif defined(__APPLE__) && defined(__MACH__) 502ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ret = ioctl(fd, DKIOCGETBLOCKCOUNT, &size); 503ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#else 504ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return 0; 505ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#endif 506ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 507ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross close(fd); 508ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 509ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (ret) 510ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return 0; 511ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 512ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return size; 513ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 514ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 515ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u64 get_file_size(const char *filename) 516ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 517ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross struct stat buf; 518ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int ret; 519ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 520ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ret = stat(filename, &buf); 521ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (ret) 522ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return 0; 523ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 524ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (S_ISREG(buf.st_mode)) 525ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return buf.st_size; 526ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross else if (S_ISBLK(buf.st_mode)) 527ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return get_block_device_size(filename); 528ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross else 529ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return 0; 530ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 531ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 532ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic void usage(char *path) 533ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 534ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fprintf(stderr, "%s [ -l <len> ] [ -j <journal size> ] [ -b <block_size> ]\n", basename(path)); 535ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fprintf(stderr, " [ -g <blocks per group> ] [ -i <inodes> ] [ -I <inode size> ]\n"); 536ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fprintf(stderr, " [ -L <label> ] [ -f ] [ -a <android mountpoint> ]\n"); 537ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fprintf(stderr, " <filename> [<directory>]\n"); 538ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 539ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 540ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u64 parse_num(const char *arg) 541ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 542ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross char *endptr; 543ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u64 num = strtoull(arg, &endptr, 10); 544ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (*endptr == 'k' || *endptr == 'K') 545ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross num *= 1024LL; 546ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross else if (*endptr == 'm' || *endptr == 'M') 547ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross num *= 1024LL * 1024LL; 548ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross else if (*endptr == 'g' || *endptr == 'G') 549ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross num *= 1024LL * 1024LL * 1024LL; 550ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 551ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return num; 552ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 553ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 554ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossint main(int argc, char **argv) 555ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{ 556ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int opt; 557ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross const char *filename = NULL; 558ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross const char *directory = NULL; 559ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross char *mountpoint = ""; 560ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross int android = 0; 5617a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross int gzip = 0; 562ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u32 root_inode_num; 563ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross u16 root_mode; 564ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 5657a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:fz")) != -1) { 566ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross switch (opt) { 567ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross case 'l': 568ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.len = parse_num(optarg); 569ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross break; 570ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross case 'j': 571ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.journal_blocks = parse_num(optarg); 572ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross break; 573ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross case 'b': 574ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.block_size = parse_num(optarg); 575ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross break; 576ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross case 'g': 577ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.blocks_per_group = parse_num(optarg); 578ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross break; 579ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross case 'i': 580ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.inodes = parse_num(optarg); 581ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross break; 582ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross case 'I': 583ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.inode_size = parse_num(optarg); 584ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross break; 585ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross case 'L': 586ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.label = optarg; 587ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross break; 588ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross case 'f': 589ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross force = 1; 590ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross break; 591ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross case 'a': 592ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross android = 1; 593ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross mountpoint = optarg; 594ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross break; 5957a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross case 'z': 5967a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross gzip = 1; 5977a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross break; 598ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross default: /* '?' */ 599ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross usage(argv[0]); 600ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross exit(EXIT_FAILURE); 601ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 602ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 603ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 604ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (optind >= argc) { 605ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fprintf(stderr, "Expected filename after options\n"); 606ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross usage(argv[0]); 607ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross exit(EXIT_FAILURE); 608ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 609ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 610ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross filename = argv[optind++]; 611ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 612ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (optind < argc) 613ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross directory = argv[optind++]; 614ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 615ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (optind < argc) { 616ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fprintf(stderr, "Unexpected argument: %s\n", argv[optind]); 617ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross usage(argv[0]); 618ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross exit(EXIT_FAILURE); 619ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 620ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 621ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (info.len == 0) 622ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.len = get_file_size(filename); 623ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 624ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (info.len <= 0) { 625ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross fprintf(stderr, "Need size of filesystem\n"); 626ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross usage(argv[0]); 627ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross exit(EXIT_FAILURE); 628ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross } 629ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 630ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (info.journal_blocks > 0) 631ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.feat_compat = EXT4_FEATURE_COMPAT_HAS_JOURNAL; 632ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 633ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (info.block_size <= 0) 634ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.block_size = compute_block_size(); 635ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 636ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (info.blocks_per_group <= 0) 637ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.blocks_per_group = compute_blocks_per_group(); 638ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 639ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (info.inodes <= 0) 640ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.inodes = compute_inodes(); 641ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 642ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (info.inode_size <= 0) 643ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.inode_size = 256; 644ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 645ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (info.label == NULL) 646ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.label = ""; 647ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 648ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.inodes_per_group = compute_inodes_per_group(); 649ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 650ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.feat_compat |= 651ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross EXT4_FEATURE_COMPAT_RESIZE_INODE; 652ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 653ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.feat_ro_compat |= 654ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER | 655ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross EXT4_FEATURE_RO_COMPAT_LARGE_FILE; 656ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 657ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross info.feat_incompat |= 658ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross EXT4_FEATURE_INCOMPAT_EXTENTS | 659ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross EXT4_FEATURE_INCOMPAT_FILETYPE; 660ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 661ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 662ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross printf("Creating filesystem with parameters:\n"); 663ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross printf(" Size: %llu\n", info.len); 664ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross printf(" Block size: %d\n", info.block_size); 665ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross printf(" Blocks per group: %d\n", info.blocks_per_group); 666ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross printf(" Inodes per group: %d\n", info.inodes_per_group); 667ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross printf(" Inode size: %d\n", info.inode_size); 668ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross printf(" Label: %s\n", info.label); 669ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 670ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ext4_create_fs_aux_info(); 671ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 672ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross printf(" Blocks: %llu\n", aux_info.len_blocks); 673ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross printf(" Block groups: %d\n", aux_info.groups); 674ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross printf(" Reserved block group size: %d\n", aux_info.bg_desc_reserve_blocks); 675ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 676ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross block_allocator_init(); 677ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 678ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ext4_fill_in_sb(); 679ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 680ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (reserve_inodes(0, 10) == EXT4_ALLOCATE_FAILED) 681ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross error("failed to reserve first 10 inodes"); 682ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 683ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (info.feat_compat & EXT4_FEATURE_COMPAT_HAS_JOURNAL) 684ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ext4_create_journal_inode(); 685ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 686ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (info.feat_compat & EXT4_FEATURE_COMPAT_RESIZE_INODE) 687ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ext4_create_resize_inode(); 688ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 689ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross if (directory) 690ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross root_inode_num = build_directory_structure(directory, mountpoint, 0, android); 691ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross else 692ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross root_inode_num = build_default_directory_structure(); 693ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 694ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross root_mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 695ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross inode_set_permissions(root_inode_num, root_mode, 0, 0); 696ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 697ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross ext4_update_free(); 698ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 699ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross printf("Created filesystem with %d/%d inodes and %d/%d blocks\n", 700ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.sb->s_inodes_count - aux_info.sb->s_free_inodes_count, 701ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.sb->s_inodes_count, 702ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo, 703ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross aux_info.sb->s_blocks_count_lo); 704ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 7057a8bee7653c393d8da0e28668cb51d3ccab793e8Colin Cross write_ext4_image(filename, gzip); 706ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross 707ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross return 0; 708ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross} 709