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