18642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland/*
28642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland * Copyright (C) 2010 The Android Open Source Project
38642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland *
48642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland * Licensed under the Apache License, Version 2.0 (the "License");
58642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland * you may not use this file except in compliance with the License.
68642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland * You may obtain a copy of the License at
78642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland *
88642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland *      http://www.apache.org/licenses/LICENSE-2.0
98642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland *
108642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland * Unless required by applicable law or agreed to in writing, software
118642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland * distributed under the License is distributed on an "AS IS" BASIS,
128642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland * See the License for the specific language governing permissions and
148642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland * limitations under the License.
158642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland */
168642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
178642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#define _GNU_SOURCE
188642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
198642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include <dirent.h>
208642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include <libgen.h>
218642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include <stdio.h>
228642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include <stdlib.h>
238642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include <string.h>
248642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include <unistd.h>
258642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include <sys/stat.h>
268642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include <sys/types.h>
278642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
288642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include "make_ext4fs.h"
298642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include "output_file.h"
308642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include "ext4_utils.h"
318642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include "allocate.h"
328642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include "contents.h"
338642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include "uuid.h"
348642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
358642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#ifdef ANDROID
368642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#include <private/android_filesystem_config.h>
378642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#endif
388642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
398642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland/* TODO: Not implemented:
408642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland   Allocating blocks in the same block group as the file inode
418642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland   Hash or binary tree directories
428642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland   Special files: sockets, devices, fifos
438642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland */
448642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
458642b7fba54727a38f751516bcdc452fb09ef610Brian Swetlandstatic int filter_dot(const struct dirent *d)
468642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland{
478642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	return (strcmp(d->d_name, "..") && strcmp(d->d_name, "."));
488642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland}
498642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
508642b7fba54727a38f751516bcdc452fb09ef610Brian Swetlandstatic u32 build_default_directory_structure()
518642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland{
528642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	u32 inode;
538642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	u32 root_inode;
548642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	struct dentry dentries = {
558642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			.filename = "lost+found",
568642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			.file_type = EXT4_FT_DIR,
578642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			.mode = S_IRWXU,
588642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			.uid = 0,
598642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			.gid = 0,
608642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			.mtime = 0,
618642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	};
628642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	root_inode = make_directory(0, 1, &dentries, 1);
638642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	inode = make_directory(root_inode, 0, NULL, 0);
648642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	*dentries.inode = inode;
658642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	inode_set_permissions(inode, dentries.mode,
668642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		dentries.uid, dentries.gid, dentries.mtime);
678642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
688642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	return root_inode;
698642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland}
708642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
718642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland/* Read a local directory and create the same tree in the generated filesystem.
728642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland   Calls itself recursively with each directory in the given directory */
738642b7fba54727a38f751516bcdc452fb09ef610Brian Swetlandstatic u32 build_directory_structure(const char *full_path, const char *dir_path,
748642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		u32 dir_inode, int android)
758642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland{
768642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	int entries = 0;
778642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	struct dentry *dentries;
788642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	struct dirent **namelist;
798642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	struct stat stat;
808642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	int ret;
818642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	int i;
828642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	u32 inode;
838642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	u32 entry_inode;
848642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	u32 dirs = 0;
858642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
868642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort);
878642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (entries < 0) {
888642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		error_errno("scandir");
898642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		return EXT4_ALLOCATE_FAILED;
908642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	}
918642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
928642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	dentries = calloc(entries, sizeof(struct dentry));
938642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (dentries == NULL)
948642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		critical_error_errno("malloc");
958642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
968642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	for (i = 0; i < entries; i++) {
978642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		dentries[i].filename = strdup(namelist[i]->d_name);
988642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		if (dentries[i].filename == NULL)
998642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			critical_error_errno("strdup");
1008642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
1018642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		asprintf(&dentries[i].path, "%s/%s", dir_path, namelist[i]->d_name);
1028642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		asprintf(&dentries[i].full_path, "%s/%s", full_path, namelist[i]->d_name);
1038642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
1048642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		free(namelist[i]);
1058642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
1068642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		ret = lstat(dentries[i].full_path, &stat);
1078642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		if (ret < 0) {
1088642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			error_errno("lstat");
1098642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			i--;
1108642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			entries--;
1118642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			continue;
1128642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		}
1138642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
1148642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		dentries[i].size = stat.st_size;
1158642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		dentries[i].mode = stat.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
1168642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		dentries[i].mtime = stat.st_mtime;
1178642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		if (android) {
1188642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#ifdef ANDROID
1198642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			unsigned int mode = 0;
1208642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			unsigned int uid = 0;
1218642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			unsigned int gid = 0;
1228642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			int dir = S_ISDIR(stat.st_mode);
1238642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			fs_config(dentries[i].path, dir, &uid, &gid, &mode);
1248642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dentries[i].mode = mode;
1258642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dentries[i].uid = uid;
1268642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dentries[i].gid = gid;
1278642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#else
1288642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			error("can't set android permissions - built without android support");
1298642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland#endif
1308642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		}
1318642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
1328642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		if (S_ISREG(stat.st_mode)) {
1338642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dentries[i].file_type = EXT4_FT_REG_FILE;
1348642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		} else if (S_ISDIR(stat.st_mode)) {
1358642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dentries[i].file_type = EXT4_FT_DIR;
1368642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dirs++;
1378642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		} else if (S_ISCHR(stat.st_mode)) {
1388642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dentries[i].file_type = EXT4_FT_CHRDEV;
1398642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		} else if (S_ISBLK(stat.st_mode)) {
1408642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dentries[i].file_type = EXT4_FT_BLKDEV;
1418642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		} else if (S_ISFIFO(stat.st_mode)) {
1428642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dentries[i].file_type = EXT4_FT_FIFO;
1438642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		} else if (S_ISSOCK(stat.st_mode)) {
1448642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dentries[i].file_type = EXT4_FT_SOCK;
1458642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		} else if (S_ISLNK(stat.st_mode)) {
1468642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dentries[i].file_type = EXT4_FT_SYMLINK;
1478642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dentries[i].link = calloc(info.block_size, 1);
1488642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			readlink(dentries[i].full_path, dentries[i].link, info.block_size - 1);
1498642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		} else {
1508642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			error("unknown file type on %s", dentries[i].path);
1518642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			i--;
1528642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			entries--;
1538642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		}
1548642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	}
1558642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	free(namelist);
1568642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
1578642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	inode = make_directory(dir_inode, entries, dentries, dirs);
1588642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
1598642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	for (i = 0; i < entries; i++) {
1608642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		if (dentries[i].file_type == EXT4_FT_REG_FILE) {
1618642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			entry_inode = make_file(dentries[i].full_path, dentries[i].size);
1628642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		} else if (dentries[i].file_type == EXT4_FT_DIR) {
1638642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			entry_inode = build_directory_structure(dentries[i].full_path,
1648642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland					dentries[i].path, inode, android);
1658642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		} else if (dentries[i].file_type == EXT4_FT_SYMLINK) {
1668642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			entry_inode = make_link(dentries[i].full_path, dentries[i].link);
1678642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		} else {
1688642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			error("unknown file type on %s", dentries[i].path);
1698642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			entry_inode = 0;
1708642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		}
1718642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		*dentries[i].inode = entry_inode;
1728642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
1738642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		ret = inode_set_permissions(entry_inode, dentries[i].mode,
1748642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dentries[i].uid, dentries[i].gid,
1758642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			dentries[i].mtime);
1768642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		if (ret)
1778642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			error("failed to set permissions on %s\n", dentries[i].path);
1788642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
1798642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		free(dentries[i].path);
1808642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		free(dentries[i].full_path);
1818642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		free(dentries[i].link);
1828642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		free((void *)dentries[i].filename);
1838642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	}
1848642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
1858642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	free(dentries);
1868642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	return inode;
1878642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland}
1888642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
1898642b7fba54727a38f751516bcdc452fb09ef610Brian Swetlandstatic u32 compute_block_size()
1908642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland{
1918642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	return 4096;
1928642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland}
1938642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
1948642b7fba54727a38f751516bcdc452fb09ef610Brian Swetlandstatic u32 compute_journal_blocks()
1958642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland{
1968642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	u32 journal_blocks = DIV_ROUND_UP(info.len, info.block_size) / 64;
1978642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (journal_blocks < 1024)
1988642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		journal_blocks = 1024;
1998642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (journal_blocks > 32768)
2008642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		journal_blocks = 32768;
2018642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	return journal_blocks;
2028642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland}
2038642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2048642b7fba54727a38f751516bcdc452fb09ef610Brian Swetlandstatic u32 compute_blocks_per_group()
2058642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland{
2068642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	return info.block_size * 8;
2078642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland}
2088642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2098642b7fba54727a38f751516bcdc452fb09ef610Brian Swetlandstatic u32 compute_inodes()
2108642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland{
2118642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	return DIV_ROUND_UP(info.len, info.block_size) / 4;
2128642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland}
2138642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2148642b7fba54727a38f751516bcdc452fb09ef610Brian Swetlandstatic u32 compute_inodes_per_group()
2158642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland{
2168642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	u32 blocks = DIV_ROUND_UP(info.len, info.block_size);
2178642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	u32 block_groups = DIV_ROUND_UP(blocks, info.blocks_per_group);
2188642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	return DIV_ROUND_UP(info.inodes, block_groups);
2198642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland}
2208642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2218642b7fba54727a38f751516bcdc452fb09ef610Brian Swetlandvoid reset_ext4fs_info() {
2228642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland    // Reset all the global data structures used by make_ext4fs so it
2238642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland    // can be called again.
2248642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland    memset(&info, 0, sizeof(info));
2258642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland    memset(&aux_info, 0, sizeof(aux_info));
2268642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland    free_data_blocks();
2278642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland}
2288642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2298642b7fba54727a38f751516bcdc452fb09ef610Brian Swetlandint make_ext4fs(const char *filename, const char *directory,
2308642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland                char *mountpoint, int android, int gzip, int sparse)
2318642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland{
2328642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland        u32 root_inode_num;
2338642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland        u16 root_mode;
2348642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2358642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (info.len == 0)
2368642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		info.len = get_file_size(filename);
2378642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2388642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (info.len <= 0) {
2398642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		fprintf(stderr, "Need size of filesystem\n");
2408642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland                return EXIT_FAILURE;
2418642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	}
2428642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2438642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (info.block_size <= 0)
2448642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		info.block_size = compute_block_size();
2458642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2468642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (info.journal_blocks == 0)
2478642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		info.journal_blocks = compute_journal_blocks();
2488642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2498642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (info.no_journal == 0)
2508642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		info.feat_compat = EXT4_FEATURE_COMPAT_HAS_JOURNAL;
2518642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	else
2528642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		info.journal_blocks = 0;
2538642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2548642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (info.blocks_per_group <= 0)
2558642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		info.blocks_per_group = compute_blocks_per_group();
2568642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2578642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (info.inodes <= 0)
2588642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		info.inodes = compute_inodes();
2598642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2608642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (info.inode_size <= 0)
2618642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		info.inode_size = 256;
2628642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2638642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (info.label == NULL)
2648642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		info.label = "";
2658642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2668642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	info.inodes_per_group = compute_inodes_per_group();
2678642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2688642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	info.feat_compat |=
2698642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			EXT4_FEATURE_COMPAT_RESIZE_INODE;
2708642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2718642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	info.feat_ro_compat |=
2728642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER |
2738642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			EXT4_FEATURE_RO_COMPAT_LARGE_FILE;
2748642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2758642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	info.feat_incompat |=
2768642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			EXT4_FEATURE_INCOMPAT_EXTENTS |
2778642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			EXT4_FEATURE_INCOMPAT_FILETYPE;
2788642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2798642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2808642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	printf("Creating filesystem with parameters:\n");
2818642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	printf("    Size: %llu\n", info.len);
2828642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	printf("    Block size: %d\n", info.block_size);
2838642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	printf("    Blocks per group: %d\n", info.blocks_per_group);
2848642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	printf("    Inodes per group: %d\n", info.inodes_per_group);
2858642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	printf("    Inode size: %d\n", info.inode_size);
2868642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	printf("    Journal blocks: %d\n", info.journal_blocks);
2878642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	printf("    Label: %s\n", info.label);
2888642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2898642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	ext4_create_fs_aux_info();
2908642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2918642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	printf("    Blocks: %llu\n", aux_info.len_blocks);
2928642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	printf("    Block groups: %d\n", aux_info.groups);
2938642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	printf("    Reserved block group size: %d\n", aux_info.bg_desc_reserve_blocks);
2948642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2958642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	block_allocator_init();
2968642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2978642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	ext4_fill_in_sb();
2988642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
2998642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (reserve_inodes(0, 10) == EXT4_ALLOCATE_FAILED)
3008642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		error("failed to reserve first 10 inodes");
3018642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
3028642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (info.feat_compat & EXT4_FEATURE_COMPAT_HAS_JOURNAL)
3038642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		ext4_create_journal_inode();
3048642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
3058642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (info.feat_compat & EXT4_FEATURE_COMPAT_RESIZE_INODE)
3068642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		ext4_create_resize_inode();
3078642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
3088642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	if (directory)
3098642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		root_inode_num = build_directory_structure(directory, mountpoint, 0, android);
3108642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	else
3118642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland		root_inode_num = build_default_directory_structure();
3128642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
3138642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	root_mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
3148642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	inode_set_permissions(root_inode_num, root_mode, 0, 0, 0);
3158642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
3168642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	ext4_update_free();
3178642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
3188642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	printf("Created filesystem with %d/%d inodes and %d/%d blocks\n",
3198642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			aux_info.sb->s_inodes_count - aux_info.sb->s_free_inodes_count,
3208642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			aux_info.sb->s_inodes_count,
3218642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo,
3228642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland			aux_info.sb->s_blocks_count_lo);
3238642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
3248642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	write_ext4_image(filename, gzip, sparse);
3258642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland
3268642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland	return 0;
3278642b7fba54727a38f751516bcdc452fb09ef610Brian Swetland}
328