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