12068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project/* vi: set sw=8 ts=8: */
22068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// genext2fs.c
32068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//
42068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// ext2 filesystem generator for embedded systems
52068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// Copyright (C) 2000 Xavier Bestel <xavier.bestel@free.fr>
62068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//
72068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// Please direct support requests to genext2fs-devel@lists.sourceforge.net
82068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//
92068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 'du' portions taken from coreutils/du.c in busybox:
102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//	Copyright (C) 1999,2000 by Lineo, inc. and John Beppu
112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//	Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//	Copyright (C) 2002  Edward Betts <edward@debian.org>
132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//
142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// This program is free software; you can redistribute it and/or
152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// modify it under the terms of the GNU General Public License
162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// as published by the Free Software Foundation; version
172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 2 of the License.
182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//
192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// Changes:
202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	 3 Jun 2000	Initial release
212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	 6 Jun 2000	Bugfix: fs size multiple of 8
222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			Bugfix: fill blocks with inodes
232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	14 Jun 2000	Bugfix: bad chdir() with -d option
242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			Bugfix: removed size=8n constraint
252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			Changed -d file to -f file
262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			Added -e option
272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	22 Jun 2000	Changed types for 64bits archs
282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	24 Jun 2000	Added endianness swap
292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			Bugfix: bad dir name lookup
302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	03 Aug 2000	Bugfix: ind. blocks endian swap
312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	09 Aug 2000	Bugfix: symlinks endian swap
322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	01 Sep 2000	Bugfix: getopt returns int, not char	proski@gnu.org
332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	10 Sep 2000	Bugfix: device nodes endianness		xavier.gueguen@col.bsf.alcatel.fr
342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			Bugfix: getcwd values for Solaris	xavier.gueguen@col.bsf.alcatel.fr
352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			Bugfix: ANSI scanf for non-GNU C	xavier.gueguen@col.bsf.alcatel.fr
362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	28 Jun 2001	Bugfix: getcwd differs for Solaris/GNU	mike@sowbug.com
372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	 8 Mar 2002	Bugfix: endianness swap of x-indirects
382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	23 Mar 2002	Bugfix: test for IFCHR or IFBLK was flawed
392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	10 Oct 2002	Added comments,makefile targets,	vsundar@ixiacom.com
402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			endianess swap assert check.
412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			Copyright (C) 2002 Ixia communications
422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	12 Oct 2002	Added support for triple indirection	vsundar@ixiacom.com
432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			Copyright (C) 2002 Ixia communications
442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	14 Oct 2002	Added support for groups		vsundar@ixiacom.com
452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			Copyright (C) 2002 Ixia communications
462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	 5 Jan 2003	Bugfixes: reserved inodes should be set vsundar@usc.edu
472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			only in the first group; directory names
482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			need to be null padded at the end; and
492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			number of blocks per group should be a
502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			multiple of 8. Updated md5 values.
512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 	 6 Jan 2003	Erik Andersen <andersee@debian.org> added
522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			mkfs.jffs2 compatible device table support,
532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// 			along with -q, -P, -U
542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#include <config.h>
572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#include <stdio.h>
582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_SYS_TYPES_H
602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <sys/types.h>
612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if MAJOR_IN_MKDEV
642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <sys/mkdev.h>
652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#elif MAJOR_IN_SYSMACROS
662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <sys/sysmacros.h>
672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_SYS_STAT_H
702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <sys/stat.h>
712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if STDC_HEADERS
742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <stdlib.h>
752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <stddef.h>
762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#else
772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# if HAVE_STDLIB_H
782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#  include <stdlib.h>
792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# endif
802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# if HAVE_STDDEF_H
812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#  include <stddef.h>
822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# endif
832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_STRING_H
862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# if !STDC_HEADERS && HAVE_MEMORY_H
872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#  include <memory.h>
882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# endif
892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <string.h>
902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_STRINGS_H
932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <strings.h>
942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_INTTYPES_H
972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <inttypes.h>
982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#else
992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# if HAVE_STDINT_H
1002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#  include <stdint.h>
1012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# endif
1022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
1032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_UNISTD_H
1052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <unistd.h>
1062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
1072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_DIRENT_H
1092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <dirent.h>
1102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# define NAMLEN(dirent) strlen((dirent)->d_name)
1112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#else
1122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# define dirent direct
1132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# define NAMLEN(dirent) (dirent)->d_namlen
1142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# if HAVE_SYS_NDIR_H
1152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#  include <sys/ndir.h>
1162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# endif
1172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# if HAVE_SYS_DIR_H
1182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#  include <sys/dir.h>
1192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# endif
1202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# if HAVE_NDIR_H
1212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#  include <ndir.h>
1222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# endif
1232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
1242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_LIBGEN_H
1262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <libgen.h>
1272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
1282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#include <stdarg.h>
1302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#include <assert.h>
1312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#include <time.h>
1322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#include <ctype.h>
1332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#include <errno.h>
1342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_FCNTL_H
1362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <fcntl.h>
1372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
1382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_GETOPT_H
1402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <getopt.h>
1412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
1422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_LIMITS_H
1442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# include <limits.h>
1452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
1462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#include <private/android_filesystem_config.h>
1482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectunsigned source_path_len = 0;
1492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstruct stats {
1512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	unsigned long nblocks;
1522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	unsigned long ninodes;
1532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project};
1542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// block size
1562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define BLOCKSIZE         1024
1582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define BLOCKS_PER_GROUP  8192
1592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define INODES_PER_GROUP  8192
1602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project/* Percentage of blocks that are reserved.*/
1612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define RESERVED_BLOCKS       5/100
1622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define MAX_RESERVED_BLOCKS  25/100
1632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// inode block size (why is it != BLOCKSIZE ?!?)
1662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project/* The field i_blocks in the ext2 inode stores the number of data blocks
1672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   but in terms of 512 bytes. That is what INODE_BLOCKSIZE represents.
1682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   INOBLK is the number of such blocks in an actual disk block            */
1692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define INODE_BLOCKSIZE   512
1712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define INOBLK            (BLOCKSIZE / INODE_BLOCKSIZE)
1722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// reserved inodes
1742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define EXT2_BAD_INO         1     // Bad blocks inode
1762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define EXT2_ROOT_INO        2     // Root inode
1772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define EXT2_ACL_IDX_INO     3     // ACL inode
1782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define EXT2_ACL_DATA_INO    4     // ACL inode
1792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define EXT2_BOOT_LOADER_INO 5     // Boot loader inode
1802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define EXT2_UNDEL_DIR_INO   6     // Undelete directory inode
1812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define EXT2_FIRST_INO       11    // First non reserved inode
1822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// magic number for ext2
1842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define EXT2_MAGIC_NUMBER  0xEF53
1862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// direct/indirect block addresses
1892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define EXT2_NDIR_BLOCKS   11                    // direct blocks
1912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define EXT2_IND_BLOCK     12                    // indirect block
1922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define EXT2_DIND_BLOCK    13                    // double indirect block
1932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define EXT2_TIND_BLOCK    14                    // triple indirect block
1942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define EXT2_INIT_BLOCK    0xFFFFFFFF            // just initialized (not really a block address)
1952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// end of a block walk
1972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
1982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define WALK_END           0xFFFFFFFE
1992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// file modes
2012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IFMT    0170000	// format mask
2032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IFSOCK  0140000	// socket
2042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IFLNK   0120000	// symbolic link
2052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IFREG   0100000	// regular file
2062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IFBLK   0060000	// block device
2082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IFDIR   0040000	// directory
2092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IFCHR   0020000	// character device
2102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IFIFO   0010000	// fifo
2112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IMASK   0007777	// *all* perms mask for everything below
2132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_ISUID   0004000	// SUID
2152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_ISGID   0002000	// SGID
2162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_ISVTX   0001000	// sticky bit
2172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IRWXU   0000700	// entire "user" mask
2192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IRUSR   0000400	// read
2202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IWUSR   0000200	// write
2212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IXUSR   0000100	// execute
2222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IRWXG   0000070	// entire "group" mask
2242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IRGRP   0000040	// read
2252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IWGRP   0000020	// write
2262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IXGRP   0000010	// execute
2272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IRWXO   0000007	// entire "other" mask
2292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IROTH   0000004	// read
2302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IWOTH   0000002	// write
2312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define FM_IXOTH   0000001	// execute
2322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// options
2342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define OP_HOLES     0x01       // make files with holes
2362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project/* Defines for accessing group details */
2382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// Number of groups in the filesystem
2402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define GRP_NBGROUPS(fs) \
2412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	(((fs)->sb.s_blocks_count - fs->sb.s_first_data_block + \
2422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  (fs)->sb.s_blocks_per_group - 1) / (fs)->sb.s_blocks_per_group)
2432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// Get group block bitmap (bbm) given the group number
2452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define GRP_GET_GROUP_BBM(fs,grp) ( get_blk((fs),(fs)->gd[(grp)].bg_block_bitmap) )
2462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// Get group inode bitmap (ibm) given the group number
2482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define GRP_GET_GROUP_IBM(fs,grp) ( get_blk((fs),(fs)->gd[(grp)].bg_inode_bitmap) )
2492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// Given an inode number find the group it belongs to
2512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define GRP_GROUP_OF_INODE(fs,nod) ( ((nod)-1) / (fs)->sb.s_inodes_per_group)
2522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//Given an inode number get the inode bitmap that covers it
2542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define GRP_GET_INODE_BITMAP(fs,nod) \
2552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	( GRP_GET_GROUP_IBM((fs),GRP_GROUP_OF_INODE((fs),(nod))) )
2562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//Given an inode number find its offset within the inode bitmap that covers it
2582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define GRP_IBM_OFFSET(fs,nod) \
2592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	( (nod) - GRP_GROUP_OF_INODE((fs),(nod))*(fs)->sb.s_inodes_per_group )
2602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// Given a block number find the group it belongs to
2622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define GRP_GROUP_OF_BLOCK(fs,blk) ( ((blk)-1) / (fs)->sb.s_blocks_per_group)
2632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//Given a block number get the block bitmap that covers it
2652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define GRP_GET_BLOCK_BITMAP(fs,blk) \
2662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	( GRP_GET_GROUP_BBM((fs),GRP_GROUP_OF_BLOCK((fs),(blk))) )
2672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//Given a block number find its offset within the block bitmap that covers it
2692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define GRP_BBM_OFFSET(fs,blk) \
2702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	( (blk) - GRP_GROUP_OF_BLOCK((fs),(blk))*(fs)->sb.s_blocks_per_group )
2712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// used types
2742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecttypedef signed char int8;
2762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecttypedef unsigned char uint8;
2772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecttypedef signed short int16;
2782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecttypedef unsigned short uint16;
2792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecttypedef signed int int32;
2802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecttypedef unsigned int uint32;
2812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// the GNU C library has a wonderful scanf("%as", string) which will
2842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// allocate the string with the right size, good to avoid buffer
2852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// overruns. the following macros use it if available or use a
2862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// hacky workaround
2872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// moreover it will define a snprintf() like a sprintf(), i.e.
2882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// without the buffer overrun checking, to work around bugs in
2892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// older solaris. Note that this is still not very portable, in that
2902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// the return value cannot be trusted.
2912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
2922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if 0 // SCANF_CAN_MALLOC
2932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// C99 define "a" for floating point, so you can have runtime surprise
2942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// according the library versions
2952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# define SCANF_PREFIX "a"
2962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# define SCANF_STRING(s) (&s)
2972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#else
2982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# define SCANF_PREFIX "511"
2992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# define SCANF_STRING(s) (s = malloc(512))
3002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif /* SCANF_CAN_MALLOC */
3012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
3022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if PREFER_PORTABLE_SNPRINTF
3032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic inline int
3042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectportable_snprintf(char *str, size_t n, const char *fmt, ...)
3052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
3062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int ret;
3072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	va_list ap;
3082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	va_start(ap, fmt);
3092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	ret = vsprintf(str, fmt, ap);
3102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	va_end(ap);
3112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return ret;
3122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
3132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# define SNPRINTF portable_snprintf
3142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#else
3152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project# define SNPRINTF snprintf
3162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif /* PREFER_PORTABLE_SNPRINTF */
3172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
3182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if !HAVE_GETLINE
3192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// getline() replacement for Darwin and Solaris etc.
3202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// This code uses backward seeks (unless rchunk is set to 1) which can't work
3212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// on pipes etc. However, add2fs_from_file() only calls getline() for
3222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// regular files, so a larger rchunk and backward seeks are okay.
3232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
3242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectssize_t
3252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectgetdelim(char **lineptr, size_t *n, int delim, FILE *stream)
3262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
3272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char *p;                    // reads stored here
3282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	size_t const rchunk = 512;  // number of bytes to read
3292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	size_t const mchunk = 512;  // number of extra bytes to malloc
3302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	size_t m = rchunk + 1;      // initial buffer size
3312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
3322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (*lineptr) {
3332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if (*n < m) {
3342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*lineptr = (char*)realloc(*lineptr, m);
3352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if (!*lineptr) return -1;
3362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*n = m;
3372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
3382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	} else {
3392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		*lineptr = (char*)malloc(m);
3402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if (!*lineptr) return -1;
3412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		*n = m;
3422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
3432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
3442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	m = 0; // record length including seperator
3452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
3462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	do {
3472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		size_t i;     // number of bytes read etc
3482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		size_t j = 0; // number of bytes searched
3492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
3502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		p = *lineptr + m;
3512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
3522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		i = fread(p, 1, rchunk, stream);
3532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if (i < rchunk && ferror(stream))
3542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			return -1;
3552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		while (j < i) {
3562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			++j;
3572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if (*p++ == (char)delim) {
3582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				*p = '\0';
3592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				if (j != i) {
3602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					if (fseek(stream, j - i, SEEK_CUR))
3612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						return -1;
3622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					if (feof(stream))
3632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						clearerr(stream);
3642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				}
3652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				m += j;
3662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				return m;
3672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
3682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
3692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
3702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		m += j;
3712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if (feof(stream)) {
3722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if (m) return m;
3732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if (!i) return -1;
3742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
3752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
3762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		// allocate space for next read plus possible null terminator
3772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		i = ((m + (rchunk + 1 > mchunk ? rchunk + 1 : mchunk) +
3782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		      mchunk - 1) / mchunk) * mchunk;
3792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if (i != *n) {
3802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*lineptr = (char*)realloc(*lineptr, i);
3812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if (!*lineptr) return -1;
3822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*n = i;
3832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
3842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	} while (1);
3852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
3862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define getline(a,b,c) getdelim(a,b,'\n',c)
3872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif /* HAVE_GETLINE */
3882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
3892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// Convert a numerical string to a float, and multiply the result by an
3902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// IEC or SI multiplier if provided; supported multipliers are Ki, Mi, Gi, k, M
3912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// and G.
3922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
3932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectfloat
3942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source ProjectSI_atof(const char *nptr)
3952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
3962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	float f = 0;
3972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	float m = 1;
3982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char *suffixptr;
3992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
4002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_STRTOF
4012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	f = strtof(nptr, &suffixptr);
4022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#else
4032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	f = (float)strtod(nptr, &suffixptr);
4042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif /* HAVE_STRTOF */
4052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
4062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (*suffixptr) {
4072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if (!strcmp(suffixptr, "Ki"))
4082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			m = 1 << 10;
4092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		else if (!strcmp(suffixptr, "Mi"))
4102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			m = 1 << 20;
4112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		else if (!strcmp(suffixptr, "Gi"))
4122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			m = 1 << 30;
4132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		else if (!strcmp(suffixptr, "k"))
4142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			m = 1000;
4152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		else if (!strcmp(suffixptr, "M"))
4162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			m = 1000 * 1000;
4172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		else if (!strcmp(suffixptr, "G"))
4182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			m = 1000 * 1000 * 1000;
4192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
4202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return f * m;
4212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
4222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
4232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// endianness swap
4242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
4252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic inline uint16
4262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectswab16(uint16 val)
4272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
4282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return (val >> 8) | (val << 8);
4292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
4302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
4312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic inline uint32
4322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectswab32(uint32 val)
4332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
4342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return ((val>>24) | ((val>>8)&0xFF00) |
4352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			((val<<8)&0xFF0000) | (val<<24));
4362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
4372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
4382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
4392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// on-disk structures
4402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// this trick makes me declare things only once
4412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// (once for the structures, once for the endianness swap)
4422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
4432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define superblock_decl \
4442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_inodes_count)        /* Count of inodes in the filesystem */ \
4452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_blocks_count)        /* Count of blocks in the filesystem */ \
4462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_r_blocks_count)      /* Count of the number of reserved blocks */ \
4472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_free_blocks_count)   /* Count of the number of free blocks */ \
4482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_free_inodes_count)   /* Count of the number of free inodes */ \
4492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_first_data_block)    /* The first block which contains data */ \
4502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_log_block_size)      /* Indicator of the block size */ \
4512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	decl32(s_log_frag_size)        /* Indicator of the size of the fragments */ \
4522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_blocks_per_group)    /* Count of the number of blocks in each block group */ \
4532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_frags_per_group)     /* Count of the number of fragments in each block group */ \
4542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_inodes_per_group)    /* Count of the number of inodes in each block group */ \
4552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_mtime)               /* The time that the filesystem was last mounted */ \
4562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_wtime)               /* The time that the filesystem was last written to */ \
4572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(s_mnt_count)           /* The number of times the file system has been mounted */ \
4582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	decl16(s_max_mnt_count)        /* The number of times the file system can be mounted */ \
4592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(s_magic)               /* Magic number indicating ex2fs */ \
4602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(s_state)               /* Flags indicating the current state of the filesystem */ \
4612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(s_errors)              /* Flags indicating the procedures for error reporting */ \
4622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(s_minor_rev_level)     /* The minor revision level of the filesystem */ \
4632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_lastcheck)           /* The time that the filesystem was last checked */ \
4642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_checkinterval)       /* The maximum time permissable between checks */ \
4652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_creator_os)          /* Indicator of which OS created the filesystem */ \
4662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(s_rev_level)           /* The revision level of the filesystem */ \
4672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(s_def_resuid)          /* The default uid for reserved blocks */ \
4682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(s_def_resgid)          /* The default gid for reserved blocks */
4692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
4702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define groupdescriptor_decl \
4712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(bg_block_bitmap)       /* Block number of the block bitmap */ \
4722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(bg_inode_bitmap)       /* Block number of the inode bitmap */ \
4732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(bg_inode_table)        /* Block number of the inode table */ \
4742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(bg_free_blocks_count)  /* Free blocks in the group */ \
4752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(bg_free_inodes_count)  /* Free inodes in the group */ \
4762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(bg_used_dirs_count)    /* Number of directories in the group */ \
4772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(bg_pad)
4782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
4792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define inode_decl \
4802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(i_mode)                /* Entry type and file mode */ \
4812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(i_uid)                 /* User id */ \
4822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(i_size)                /* File/dir size in bytes */ \
4832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(i_atime)               /* Last access time */ \
4842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(i_ctime)               /* Creation time */ \
4852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(i_mtime)               /* Last modification time */ \
4862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(i_dtime)               /* Deletion time */ \
4872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(i_gid)                 /* Group id */ \
4882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(i_links_count)         /* Number of (hard) links to this inode */ \
4892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(i_blocks)              /* Number of blocks used (1 block = 512 bytes) */ \
4902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(i_flags)               /* ??? */ \
4912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(i_reserved1) \
4922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	utdecl32(i_block,15)           /* Blocks table */ \
4932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(i_version)             /* ??? */ \
4942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(i_file_acl)            /* File access control list */ \
4952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(i_dir_acl)             /* Directory access control list */ \
4962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(i_faddr)               /* Fragment address */ \
4972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl8(i_frag)                 /* Fragments count*/ \
4982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl8(i_fsize)                /* Fragment size */ \
4992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(i_pad1)
5002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define directory_decl \
5022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl32(d_inode)               /* Inode entry */ \
5032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(d_rec_len)             /* Total size on record */ \
5042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	udecl16(d_name_len)            /* Size of entry name */
5052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define decl8(x) int8 x;
5072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define udecl8(x) uint8 x;
5082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define decl16(x) int16 x;
5092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define udecl16(x) uint16 x;
5102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define decl32(x) int32 x;
5112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define udecl32(x) uint32 x;
5122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define utdecl32(x,n) uint32 x[n];
5132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecttypedef struct
5152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
5162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	superblock_decl
5172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 s_reserved[235];       // Reserved
5182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project} superblock;
5192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecttypedef struct
5212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
5222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	groupdescriptor_decl
5232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bg_reserved[3];
5242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project} groupdescriptor;
5252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecttypedef struct
5272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
5282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	inode_decl
5292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 i_reserved2[2];
5302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project} inode;
5312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecttypedef struct
5332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
5342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	directory_decl
5352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char d_name[0];
5362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project} directory;
5372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecttypedef uint8 block[BLOCKSIZE];
5392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project/* blockwalker fields:
5412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   The blockwalker is used to access all the blocks of a file (including
5422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   the indirection blocks) through repeated calls to walk_bw.
5432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   bpdir -> index into the inode->i_block[]. Indicates level of indirection.
5452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   bnum -> total number of blocks so far accessed. including indirection
5462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project           blocks.
5472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   bpind,bpdind,bptind -> index into indirection blocks.
5482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   bpind, bpdind, bptind do *NOT* index into single, double and triple
5502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   indirect blocks resp. as you might expect from their names. Instead
5512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   they are in order the 1st, 2nd & 3rd index to be used
5522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   As an example..
5542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   To access data block number 70000:
5552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project        bpdir: 15 (we are doing triple indirection)
5562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project        bpind: 0 ( index into the triple indirection block)
5572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project        bpdind: 16 ( index into the double indirection block)
5582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project        bptind: 99 ( index into the single indirection block)
5592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	70000 = 12 + 256 + 256*256 + 16*256 + 100 (indexing starts from zero)
5602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   So,for double indirection bpind will index into the double indirection
5622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   block and bpdind into the single indirection block. For single indirection
5632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project   only bpind will be used.
5642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project*/
5652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecttypedef struct
5672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
5682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bnum;
5692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bpdir;
5702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bpind;
5712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bpdind;
5722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bptind;
5732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project} blockwalker;
5742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project/* Filesystem structure that support groups */
5772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if BLOCKSIZE == 1024
5782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecttypedef struct
5792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
5802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	block zero;            // The famous block 0
5812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	superblock sb;         // The superblock
5822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	groupdescriptor gd[0]; // The group descriptors
5832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project} filesystem;
5842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#else
5852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#error UNHANDLED BLOCKSIZE
5862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
5872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// now the endianness swap
5892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef decl8
5912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef udecl8
5922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef decl16
5932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef udecl16
5942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef decl32
5952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef udecl32
5962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef utdecl32
5972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
5982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define decl8(x)
5992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define udecl8(x)
6002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define decl16(x) this->x = swab16(this->x);
6012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define udecl16(x) this->x = swab16(this->x);
6022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define decl32(x) this->x = swab32(this->x);
6032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define udecl32(x) this->x = swab32(this->x);
6042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define utdecl32(x,n) { int i; for(i=0; i<n; i++) this->x[i] = swab32(this->x[i]); }
6052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
6062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define HDLINK_CNT   16
6072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic int32 hdlink_cnt = HDLINK_CNT;
6082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstruct hdlink_s
6092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
6102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32	src_inode;
6112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32	dst_nod;
6122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project};
6132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
6142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstruct hdlinks_s
6152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
6162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int32 count;
6172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	struct hdlink_s *hdl;
6182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project};
6192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
6202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic struct hdlinks_s hdlinks;
6212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
6222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
6232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectswap_sb(superblock *sb)
6242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
6252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define this sb
6262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	superblock_decl
6272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef this
6282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
6292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
6302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
6312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectswap_gd(groupdescriptor *gd)
6322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
6332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define this gd
6342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	groupdescriptor_decl
6352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef this
6362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
6372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
6382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
6392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectswap_nod(inode *nod)
6402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
6412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define this nod
6422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	inode_decl
6432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef this
6442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
6452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
6462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
6472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectswap_dir(directory *dir)
6482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
6492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define this dir
6502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	directory_decl
6512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef this
6522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
6532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
6542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
6552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectswap_block(block b)
6562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
6572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int i;
6582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 *blk = (uint32*)b;
6592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i = 0; i < BLOCKSIZE/4; i++)
6602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		blk[i] = swab32(blk[i]);
6612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
6622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
6632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef decl8
6642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef udecl8
6652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef decl16
6662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef udecl16
6672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef decl32
6682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef udecl32
6692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#undef utdecl32
6702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
6712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic char * app_name;
6722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic const char *const memory_exhausted = "memory exhausted";
6732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
6742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// error (un)handling
6752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
6762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectverror_msg(const char *s, va_list p)
6772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
6782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fflush(stdout);
6792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fprintf(stderr, "%s: ", app_name);
6802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	vfprintf(stderr, s, p);
6812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
6822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
6832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecterror_msg(const char *s, ...)
6842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
6852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	va_list p;
6862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	va_start(p, s);
6872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	verror_msg(s, p);
6882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	va_end(p);
6892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	putc('\n', stderr);
6902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
6912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
6922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
6932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projecterror_msg_and_die(const char *s, ...)
6942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
6952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	va_list p;
6962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	va_start(p, s);
6972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	verror_msg(s, p);
6982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	va_end(p);
6992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	putc('\n', stderr);
7002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	exit(EXIT_FAILURE);
7012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
7022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
7042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectvperror_msg(const char *s, va_list p)
7052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
7062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int err = errno;
7072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (s == 0)
7082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		s = "";
7092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	verror_msg(s, p);
7102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (*s)
7112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		s = ": ";
7122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fprintf(stderr, "%s%s\n", s, strerror(err));
7132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
7142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
7162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectperror_msg_and_die(const char *s, ...)
7172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
7182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	va_list p;
7192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	va_start(p, s);
7202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	vperror_msg(s, p);
7212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	va_end(p);
7222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	exit(EXIT_FAILURE);
7232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
7242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic FILE *
7262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectxfopen(const char *path, const char *mode)
7272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
7282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	FILE *fp;
7292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if ((fp = fopen(path, mode)) == NULL)
7302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perror_msg_and_die("%s", path);
7312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return fp;
7322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
7332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic char *
7352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectxstrdup(const char *s)
7362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
7372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char *t;
7382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (s == NULL)
7402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		return NULL;
7412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	t = strdup(s);
7422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (t == NULL)
7432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die(memory_exhausted);
7442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return t;
7452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
7462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void *
7482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectxrealloc(void *ptr, size_t size)
7492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
7502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	ptr = realloc(ptr, size);
7512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (ptr == NULL && size != 0)
7522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die(memory_exhausted);
7532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return ptr;
7542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
7552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic char *
7572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectxreadlink(const char *path)
7582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
7592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	static const int GROWBY = 80; /* how large we will grow strings by */
7602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char *buf = NULL;
7622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int bufsize = 0, readsize = 0;
7632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	do {
7652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		buf = xrealloc(buf, bufsize += GROWBY);
7662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		readsize = readlink(path, buf, bufsize); /* 1st try */
7672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if (readsize == -1) {
7682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			perror_msg_and_die("%s:%s", app_name, path);
7692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
7702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
7712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	while (bufsize < readsize + 1);
7722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	buf[readsize] = '\0';
7742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return buf;
7752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
7762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectint
7782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectis_hardlink(ino_t inode)
7792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
7802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int i;
7812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i = 0; i < hdlinks.count; i++) {
7832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(hdlinks.hdl[i].src_inode == inode)
7842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			return i;
7852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
7862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return -1;
7872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
7882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// printf helper macro
7902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define plural(a) (a), ((a) > 1) ? "s" : ""
7912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
7922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// temporary working block
7932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic inline uint8 *
7942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectget_workblk(void)
7952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
7962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	unsigned char* b=calloc(1,BLOCKSIZE);
7972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return b;
7982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
7992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic inline void
8002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectfree_workblk(block b)
8012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
8022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	free(b);
8032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
8042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
8052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project/* Rounds qty upto a multiple of siz. siz should be a power of 2 */
8062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic inline uint32
8072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectrndup(uint32 qty, uint32 siz)
8082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
8092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return (qty + (siz - 1)) & ~(siz - 1);
8102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
8112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
8122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// check if something is allocated in the bitmap
8132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic inline uint32
8142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectallocated(block b, uint32 item)
8152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
8162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return b[(item-1) / 8] & (1 << ((item-1) % 8));
8172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
8182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
8192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// return a given block from a filesystem
8202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic inline uint8 *
8212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectget_blk(filesystem *fs, uint32 blk)
8222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
8232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return (uint8*)fs + blk*BLOCKSIZE;
8242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
8252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
8262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// return a given inode from a filesystem
8272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic inline inode *
8282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectget_nod(filesystem *fs, uint32 nod)
8292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
8302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int grp,offset;
8312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	inode *itab;
8322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
8332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	offset = GRP_IBM_OFFSET(fs,nod);
8342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	grp = GRP_GROUP_OF_INODE(fs,nod);
8352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	itab = (inode *)get_blk(fs, fs->gd[grp].bg_inode_table);
8362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return itab+offset-1;
8372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
8382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
8392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// allocate a given block/inode in the bitmap
8402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// allocate first free if item == 0
8412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic uint32
8422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectallocate(block b, uint32 item)
8432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
8442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!item)
8452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
8462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		int i;
8472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		uint8 bits;
8482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(i = 0; i < BLOCKSIZE; i++)
8492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if((bits = b[i]) != (uint8)-1)
8502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
8512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				int j;
8522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				for(j = 0; j < 8; j++)
8532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					if(!(bits & (1 << j)))
8542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						break;
8552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				item = i * 8 + j + 1;
8562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
8572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
8582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(i == BLOCKSIZE)
8592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			return 0;
8602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
8612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	b[(item-1) / 8] |= (1 << ((item-1) % 8));
8622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return item;
8632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
8642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
8652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// deallocate a given block/inode
8662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
8672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectdeallocate(block b, uint32 item)
8682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
8692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	b[(item-1) / 8] &= ~(1 << ((item-1) % 8));
8702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
8712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
8722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// allocate a block
8732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic uint32
8742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectalloc_blk(filesystem *fs, uint32 nod)
8752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
8762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bk=0;
8772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 grp,nbgroups;
8782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
8792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	grp = GRP_GROUP_OF_INODE(fs,nod);
8802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	nbgroups = GRP_NBGROUPS(fs);
8812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!(bk = allocate(get_blk(fs,fs->gd[grp].bg_block_bitmap), 0))) {
8822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(grp=0;grp<nbgroups && !bk;grp++)
8832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			bk=allocate(get_blk(fs,fs->gd[grp].bg_block_bitmap),0);
8842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		grp--;
8852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
8862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (!bk)
8872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("couldn't allocate a block (no free space)");
8882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!(fs->gd[grp].bg_free_blocks_count--))
8892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("group descr %d. free blocks count == 0 (corrupted fs?)",grp);
8902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!(fs->sb.s_free_blocks_count--))
8912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("superblock free blocks count == 0 (corrupted fs?)");
8922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return fs->sb.s_blocks_per_group*grp + bk;
8932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
8942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
8952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// free a block
8962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
8972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectfree_blk(filesystem *fs, uint32 bk)
8982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
8992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 grp;
9002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
9012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	grp = bk / fs->sb.s_blocks_per_group;
9022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	bk %= fs->sb.s_blocks_per_group;
9032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	deallocate(get_blk(fs,fs->gd[grp].bg_block_bitmap), bk);
9042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->gd[grp].bg_free_blocks_count++;
9052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_free_blocks_count++;
9062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
9072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
9082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// allocate an inode
9092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic uint32
9102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectalloc_nod(filesystem *fs)
9112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
9122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 nod,best_group=0;
9132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 grp,nbgroups,avefreei;
9142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
9152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	nbgroups = GRP_NBGROUPS(fs);
9162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
9172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* Distribute inodes amongst all the blocks                           */
9182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* For every block group with more than average number of free inodes */
9192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* find the one with the most free blocks and allocate node there     */
9202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* Idea from find_group_dir in fs/ext2/ialloc.c in 2.4.19 kernel      */
9212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* We do it for all inodes.                                           */
9222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	avefreei  =  fs->sb.s_free_inodes_count / nbgroups;
9232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(grp=0; grp<nbgroups; grp++) {
9242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if (fs->gd[grp].bg_free_inodes_count < avefreei ||
9252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		    fs->gd[grp].bg_free_inodes_count == 0)
9262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			continue;
9272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if (!best_group ||
9282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			fs->gd[grp].bg_free_blocks_count > fs->gd[best_group].bg_free_blocks_count)
9292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			best_group = grp;
9302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
9312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (!(nod = allocate(get_blk(fs,fs->gd[best_group].bg_inode_bitmap),0)))
9322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("couldn't allocate an inode (no free inode)");
9332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!(fs->gd[best_group].bg_free_inodes_count--))
9342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("group descr. free blocks count == 0 (corrupted fs?)");
9352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!(fs->sb.s_free_inodes_count--))
9362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("superblock free blocks count == 0 (corrupted fs?)");
9372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return fs->sb.s_inodes_per_group*best_group+nod;
9382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
9392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
9402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// print a bitmap allocation
9412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
9422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectprint_bm(block b, uint32 max)
9432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
9442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 i;
9452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0\n");
9462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i=1; i <= max; i++)
9472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
9482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		putchar(allocated(b, i) ? '*' : '.');
9492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(!(i % 100))
9502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			printf("\n");
9512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
9522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if((i-1) % 100)
9532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		printf("\n");
9542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
9552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
9562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// initalize a blockwalker (iterator for blocks list)
9572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic inline void
9582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectinit_bw(blockwalker *bw)
9592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
9602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	bw->bnum = 0;
9612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	bw->bpdir = EXT2_INIT_BLOCK;
9622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
9632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
9642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// return next block of inode (WALK_END for end)
9652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// if *create>0, append a newly allocated block at the end
9662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// if *create<0, free the block - warning, the metadata blocks contents is
9672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//				  used after being freed, so once you start
9682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//				  freeing blocks don't stop until the end of
9692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//				  the file. moreover, i_blocks isn't updated.
9702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project//				  in fact, don't do that, just use extend_blk
9712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// if hole!=0, create a hole in the file
9722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic uint32
9732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectwalk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
9742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
9752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 *bkref = 0;
9762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 *b;
9772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int extend = 0, reduce = 0;
9782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(create && (*create) < 0)
9792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		reduce = 1;
9802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(bw->bnum >= get_nod(fs, nod)->i_blocks / INOBLK)
9812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
9822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(create && (*create) > 0)
9832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
9842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			(*create)--;
9852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			extend = 1;
9862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
9872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		else
9882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			return WALK_END;
9892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
9902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// first direct block
9912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(bw->bpdir == EXT2_INIT_BLOCK)
9922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
9932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bkref = &get_nod(fs, nod)->i_block[bw->bpdir = 0];
9942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate first block
9952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*bkref = hole ? 0 : alloc_blk(fs,nod);
9962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free first block
9972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, *bkref);
9982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
9992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// direct block
10002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else if(bw->bpdir < EXT2_NDIR_BLOCKS)
10012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
10022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bkref = &get_nod(fs, nod)->i_block[++bw->bpdir];
10032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate block
10042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*bkref = hole ? 0 : alloc_blk(fs,nod);
10052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free block
10062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, *bkref);
10072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
10082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// first block in indirect block
10092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else if(bw->bpdir == EXT2_NDIR_BLOCKS)
10102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
10112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bnum++;
10122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpdir = EXT2_IND_BLOCK;
10132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpind = 0;
10142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate indirect block
10152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			get_nod(fs, nod)->i_block[bw->bpdir] = alloc_blk(fs,nod);
10162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free indirect block
10172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
10182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
10192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bkref = &b[bw->bpind];
10202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate first block
10212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*bkref = hole ? 0 : alloc_blk(fs,nod);
10222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free first block
10232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, *bkref);
10242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
10252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// block in indirect block
10262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else if((bw->bpdir == EXT2_IND_BLOCK) && (bw->bpind < BLOCKSIZE/4 - 1))
10272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
10282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpind++;
10292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
10302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bkref = &b[bw->bpind];
10312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate block
10322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*bkref = hole ? 0 : alloc_blk(fs,nod);
10332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free block
10342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, *bkref);
10352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
10362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// first block in first indirect block in first double indirect block
10372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else if(bw->bpdir == EXT2_IND_BLOCK)
10382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
10392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bnum += 2;
10402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpdir = EXT2_DIND_BLOCK;
10412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpind = 0;
10422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpdind = 0;
10432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate double indirect block
10442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			get_nod(fs, nod)->i_block[bw->bpdir] = alloc_blk(fs,nod);
10452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free double indirect block
10462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
10472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
10482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate first indirect block
10492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			b[bw->bpind] = alloc_blk(fs,nod);
10502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free  firstindirect block
10512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, b[bw->bpind]);
10522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, b[bw->bpind]);
10532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bkref = &b[bw->bpdind];
10542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate first block
10552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*bkref = hole ? 0 : alloc_blk(fs,nod);
10562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free first block
10572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, *bkref);
10582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
10592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// block in indirect block in double indirect block
10602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else if((bw->bpdir == EXT2_DIND_BLOCK) && (bw->bpdind < BLOCKSIZE/4 - 1))
10612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
10622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpdind++;
10632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
10642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, b[bw->bpind]);
10652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bkref = &b[bw->bpdind];
10662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate block
10672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*bkref = hole ? 0 : alloc_blk(fs,nod);
10682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free block
10692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, *bkref);
10702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
10712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// first block in indirect block in double indirect block
10722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else if((bw->bpdir == EXT2_DIND_BLOCK) && (bw->bpind < BLOCKSIZE/4 - 1))
10732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
10742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bnum++;
10752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpdind = 0;
10762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpind++;
10772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
10782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate indirect block
10792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			b[bw->bpind] = alloc_blk(fs,nod);
10802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free indirect block
10812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, b[bw->bpind]);
10822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, b[bw->bpind]);
10832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bkref = &b[bw->bpdind];
10842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate first block
10852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*bkref = hole ? 0 : alloc_blk(fs,nod);
10862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free first block
10872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, *bkref);
10882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
10892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
10902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* Adding support for triple indirection */
10912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* Just starting triple indirection. Allocate the indirection
10922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   blocks and the first data block
10932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	 */
10942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else if (bw->bpdir == EXT2_DIND_BLOCK)
10952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
10962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  	bw->bnum += 3;
10972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpdir = EXT2_TIND_BLOCK;
10982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpind = 0;
10992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpdind = 0;
11002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bptind = 0;
11012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate triple indirect block
11022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			get_nod(fs, nod)->i_block[bw->bpdir] = alloc_blk(fs,nod);
11032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free triple indirect block
11042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
11052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
11062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate first double indirect block
11072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			b[bw->bpind] = alloc_blk(fs,nod);
11082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free first double indirect block
11092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, b[bw->bpind]);
11102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, b[bw->bpind]);
11112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate first indirect block
11122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			b[bw->bpdind] = alloc_blk(fs,nod);
11132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free first indirect block
11142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, b[bw->bpind]);
11152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, b[bw->bpdind]);
11162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bkref = &b[bw->bptind];
11172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate first data block
11182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*bkref = hole ? 0 : alloc_blk(fs,nod);
11192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free first block
11202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, *bkref);
11212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
11222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* Still processing a single indirect block down the indirection
11232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   chain.Allocate a data block for it
11242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	 */
11252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else if ( (bw->bpdir == EXT2_TIND_BLOCK) &&
11262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		  (bw->bptind < BLOCKSIZE/4 -1) )
11272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
11282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bptind++;
11292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
11302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, b[bw->bpind]);
11312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, b[bw->bpdind]);
11322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bkref = &b[bw->bptind];
11332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate data block
11342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*bkref = hole ? 0 : alloc_blk(fs,nod);
11352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free block
11362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, *bkref);
11372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
11382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* Finished processing a single indirect block. But still in the
11392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   same double indirect block. Allocate new single indirect block
11402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   for it and a data block
11412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	 */
11422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else if ( (bw->bpdir == EXT2_TIND_BLOCK) &&
11432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		  (bw->bpdind < BLOCKSIZE/4 -1) )
11442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
11452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bnum++;
11462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bptind = 0;
11472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpdind++;
11482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
11492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, b[bw->bpind]);
11502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate single indirect block
11512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			b[bw->bpdind] = alloc_blk(fs,nod);
11522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free indirect block
11532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, b[bw->bpind]);
11542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, b[bw->bpdind]);
11552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bkref = &b[bw->bptind];
11562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate first data block
11572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*bkref = hole ? 0 : alloc_blk(fs,nod);
11582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free first block
11592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, *bkref);
11602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
11612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* Finished processing a double indirect block. Allocate the next
11622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   double indirect block and the single,data blocks for it
11632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	 */
11642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else if ( (bw->bpdir == EXT2_TIND_BLOCK) &&
11652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		  (bw->bpind < BLOCKSIZE/4 - 1) )
11662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
11672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bnum += 2;
11682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpdind = 0;
11692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bptind = 0;
11702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bpind++;
11712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
11722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate double indirect block
11732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			b[bw->bpind] = alloc_blk(fs,nod);
11742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free double indirect block
11752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, b[bw->bpind]);
11762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, b[bw->bpind]);
11772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate single indirect block
11782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			b[bw->bpdind] = alloc_blk(fs,nod);
11792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free indirect block
11802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, b[bw->bpind]);
11812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = (uint32*)get_blk(fs, b[bw->bpdind]);
11822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bkref = &b[bw->bptind];
11832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(extend) // allocate first block
11842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*bkref = hole ? 0 : alloc_blk(fs,nod);
11852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reduce) // free first block
11862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blk(fs, *bkref);
11872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
11882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else
11892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("file too big !");
11902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* End change for walking triple indirection */
11912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
11922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(*bkref)
11932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
11942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw->bnum++;
11952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(!reduce && !allocated(GRP_GET_BLOCK_BITMAP(fs,*bkref), GRP_BBM_OFFSET(fs,*bkref)))
11962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			error_msg_and_die("[block %d of inode %d is unallocated !]", *bkref, nod);
11972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
11982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(extend)
11992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		get_nod(fs, nod)->i_blocks = bw->bnum * INOBLK;
12002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return *bkref;
12012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
12022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
12032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// add blocks to an inode (file/dir/etc...)
12042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
12052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectextend_blk(filesystem *fs, uint32 nod, block b, int amount)
12062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
12072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int create = amount;
12082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	blockwalker bw, lbw;
12092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bk;
12102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	init_bw(&bw);
12112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(amount < 0)
12122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
12132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		uint32 i;
12142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(i = 0; i < get_nod(fs, nod)->i_blocks / INOBLK + amount; i++)
12152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			walk_bw(fs, nod, &bw, 0, 0);
12162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		while(walk_bw(fs, nod, &bw, &create, 0) != WALK_END)
12172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			/*nop*/;
12182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		get_nod(fs, nod)->i_blocks += amount * INOBLK;
12192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
12202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else
12212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
12222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		lbw = bw;
12232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
12242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			lbw = bw;
12252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bw = lbw;
12262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		while(create)
12272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
12282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			int i, copyb = 0;
12292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if(!(fs->sb.s_reserved[200] & OP_HOLES))
12302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				copyb = 1;
12312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			else
12322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				for(i = 0; i < BLOCKSIZE / 4; i++)
12332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					if(((int32*)(b + BLOCKSIZE * (amount - create)))[i])
12342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					{
12352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						copyb = 1;
12362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						break;
12372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					}
12382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if((bk = walk_bw(fs, nod, &bw, &create, !copyb)) == WALK_END)
12392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
12402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if(copyb)
12412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				memcpy(get_blk(fs, bk), b + BLOCKSIZE * (amount - create - 1), BLOCKSIZE);
12422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
12432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
12442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
12452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
12462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// link an entry (inode #) to a directory
12472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
12482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectadd2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
12492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
12502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	blockwalker bw;
12512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bk;
12522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint8 *b;
12532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	directory *d;
12542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int reclen, nlen;
12552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	inode *node;
12562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	inode *pnode;
12572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
12582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	pnode = get_nod(fs, dnod);
12592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if((pnode->i_mode & FM_IFMT) != FM_IFDIR)
12602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("can't add '%s' to a non-directory", name);
12612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!*name)
12622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("can't create an inode with an empty name");
12632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(strchr(name, '/'))
12642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("bad name '%s' (contains a slash)", name);
12652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	nlen = strlen(name);
12662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	reclen = sizeof(directory) + rndup(nlen, 4);
12672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(reclen > BLOCKSIZE)
12682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("bad name '%s' (too long)", name);
12692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	init_bw(&bw);
12702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	while((bk = walk_bw(fs, dnod, &bw, 0, 0)) != WALK_END) // for all blocks in dir
12712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
12722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = get_blk(fs, bk);
12732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		// for all dir entries in block
12742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))
12752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
12762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			// if empty dir entry, large enough, use it
12772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if((!d->d_inode) && (d->d_rec_len >= reclen))
12782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
12792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				d->d_inode = nod;
12802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				node = get_nod(fs, nod);
12812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				node->i_links_count++;
12822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				d->d_name_len = nlen;
12832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				strncpy(d->d_name, name, nlen);
12842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				return;
12852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
12862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			// if entry with enough room (last one?), shrink it & use it
12872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if(d->d_rec_len >= (sizeof(directory) + rndup(d->d_name_len, 4) + reclen))
12882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
12892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				reclen = d->d_rec_len;
12902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				d->d_rec_len = sizeof(directory) + rndup(d->d_name_len, 4);
12912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				reclen -= d->d_rec_len;
12922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				d = (directory*) (((int8*)d) + d->d_rec_len);
12932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				d->d_rec_len = reclen;
12942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				d->d_inode = nod;
12952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				node = get_nod(fs, nod);
12962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				node->i_links_count++;
12972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				d->d_name_len = nlen;
12982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				strncpy(d->d_name, name, nlen);
12992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				return;
13002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
13012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
13022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
13032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// we found no free entry in the directory, so we add a block
13042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!(b = get_workblk()))
13052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("get_workblk() failed.");
13062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	d = (directory*)b;
13072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	d->d_inode = nod;
13082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	node = get_nod(fs, nod);
13092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	node->i_links_count++;
13102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	d->d_rec_len = BLOCKSIZE;
13112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	d->d_name_len = nlen;
13122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	strncpy(d->d_name, name, nlen);
13132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	extend_blk(fs, dnod, b, 1);
13142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	get_nod(fs, dnod)->i_size += BLOCKSIZE;
13152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	free_workblk(b);
13162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
13172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
13182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// find an entry in a directory
13192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic uint32
13202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectfind_dir(filesystem *fs, uint32 nod, const char * name)
13212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
13222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	blockwalker bw;
13232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bk;
13242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int nlen = strlen(name);
13252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	init_bw(&bw);
13262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
13272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
13282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		directory *d;
13292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		uint8 *b;
13302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = get_blk(fs, bk);
13312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))
13322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if(d->d_inode && (nlen == d->d_name_len) && !strncmp(d->d_name, name, nlen))
13332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				return d->d_inode;
13342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
13352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return 0;
13362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
13372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
13382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// find the inode of a full path
13392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic uint32
13402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectfind_path(filesystem *fs, uint32 nod, const char * name)
13412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
13422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char *p, *n, *n2 = xstrdup(name);
13432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	n = n2;
13442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	while(*n == '/')
13452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
13462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		nod = EXT2_ROOT_INO;
13472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		n++;
13482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
13492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	while(*n)
13502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
13512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if((p = strchr(n, '/')))
13522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			(*p) = 0;
13532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(!(nod = find_dir(fs, nod, n)))
13542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
13552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(p)
13562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			n = p + 1;
13572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		else
13582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
13592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
13602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	free(n2);
13612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return nod;
13622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
13632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
13642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// chmod an inode
13652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectvoid
13662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectchmod_fs(filesystem *fs, uint32 nod, uint16 mode, uint16 uid, uint16 gid)
13672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
13682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	inode *node;
13692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	node = get_nod(fs, nod);
13702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	node->i_mode = (node->i_mode & ~FM_IMASK) | (mode & FM_IMASK);
13712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	node->i_uid = uid;
13722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	node->i_gid = gid;
13732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
13742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
13752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// create a simple inode
13762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic uint32
13772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectmknod_fs(filesystem *fs, uint32 parent_nod, const char *name, uint16 mode, uint16 uid, uint16 gid, uint8 major, uint8 minor, uint32 ctime, uint32 mtime)
13782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
13792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 nod;
13802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	inode *node;
13812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
13822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		nod = alloc_nod(fs);
13832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		node = get_nod(fs, nod);
13842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		node->i_mode = mode;
13852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		add2dir(fs, parent_nod, nod, name);
13862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		switch(mode & FM_IFMT)
13872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
13882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case FM_IFLNK:
13892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				mode = FM_IFLNK | FM_IRWXU | FM_IRWXG | FM_IRWXO;
13902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
13912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case FM_IFBLK:
13922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case FM_IFCHR:
13932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				((uint8*)get_nod(fs, nod)->i_block)[0] = minor;
13942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				((uint8*)get_nod(fs, nod)->i_block)[1] = major;
13952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
13962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case FM_IFDIR:
13972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				add2dir(fs, nod, nod, ".");
13982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				add2dir(fs, nod, parent_nod, "..");
13992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				fs->gd[GRP_GROUP_OF_INODE(fs,nod)].bg_used_dirs_count++;
14002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
14012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
14022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
14032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	node->i_uid = uid;
14042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	node->i_gid = gid;
14052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	node->i_atime = mtime;
14062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	node->i_ctime = ctime;
14072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	node->i_mtime = mtime;
14082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return nod;
14092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
14102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
14112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// make a full-fledged directory (i.e. with "." & "..")
14122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic inline uint32
14132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectmkdir_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode,
14142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uid_t uid, gid_t gid, uint32 ctime, uint32 mtime)
14152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
14162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return mknod_fs(fs, parent_nod, name, mode|FM_IFDIR, uid, gid, 0, 0, ctime, mtime);
14172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
14182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
14192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// make a symlink
14202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic uint32
14212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectmklink_fs(filesystem *fs, uint32 parent_nod, const char *name, size_t size, uint8 *b, uid_t uid, gid_t gid, uint32 ctime, uint32 mtime)
14222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
14232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 nod = mknod_fs(fs, parent_nod, name, FM_IFLNK | FM_IRWXU | FM_IRWXG | FM_IRWXO, uid, gid, 0, 0, ctime, mtime);
14242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	extend_blk(fs, nod, 0, - (int)get_nod(fs, nod)->i_blocks / INOBLK);
14252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	get_nod(fs, nod)->i_size = size;
14262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(size <= 4 * (EXT2_TIND_BLOCK+1))
14272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
14282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		strncpy((char*)get_nod(fs, nod)->i_block, (char*)b, size);
14292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		return nod;
14302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
14312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	extend_blk(fs, nod, b, rndup(size, BLOCKSIZE) / BLOCKSIZE);
14322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return nod;
14332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
14342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
14352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// make a file from a FILE*
14362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic uint32
14372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectmkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, size_t size, FILE *f, uid_t uid, gid_t gid, uint32 ctime, uint32 mtime)
14382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
14392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint8 * b;
14402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 nod = mknod_fs(fs, parent_nod, name, mode|FM_IFREG, uid, gid, 0, 0, ctime, mtime);
14412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	extend_blk(fs, nod, 0, - (int)get_nod(fs, nod)->i_blocks / INOBLK);
14422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	get_nod(fs, nod)->i_size = size;
14432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (size) {
14442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(!(b = (uint8*)calloc(rndup(size, BLOCKSIZE), 1)))
14452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			error_msg_and_die("not enough mem to read file '%s'", name);
14462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(f)
14472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			fread(b, size, 1, f); // FIXME: ugly. use mmap() ...
14482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		extend_blk(fs, nod, b, rndup(size, BLOCKSIZE) / BLOCKSIZE);
14492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		free(b);
14502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
14512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return nod;
14522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
14532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
14542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// retrieves a mode info from a struct stat
14552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic uint32
14562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectget_mode(struct stat *st)
14572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
14582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 mode = 0;
14592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
14602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(st->st_mode & S_IRUSR)
14612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode |= FM_IRUSR;
14622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(st->st_mode & S_IWUSR)
14632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode |= FM_IWUSR;
14642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(st->st_mode & S_IXUSR)
14652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode |= FM_IXUSR;
14662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(st->st_mode & S_IRGRP)
14672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode |= FM_IRGRP;
14682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(st->st_mode & S_IWGRP)
14692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode |= FM_IWGRP;
14702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(st->st_mode & S_IXGRP)
14712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode |= FM_IXGRP;
14722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(st->st_mode & S_IROTH)
14732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode |= FM_IROTH;
14742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(st->st_mode & S_IWOTH)
14752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode |= FM_IWOTH;
14762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(st->st_mode & S_IXOTH)
14772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode |= FM_IXOTH;
14782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(st->st_mode & S_ISUID)
14792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode |= FM_ISUID;
14802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(st->st_mode & S_ISGID)
14812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode |= FM_ISGID;
14822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(st->st_mode & S_ISVTX)
14832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode |= FM_ISVTX;
14842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return mode;
14852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
14862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
14872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// add or fixup entries to the filesystem from a text file
14882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project/*  device table entries take the form of:
14892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project    <path>	<type> <mode>	<uid>	<gid>	<major>	<minor>	<start>	<inc>	<count>
14902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project    /dev/mem     c    640       0       0         1       1       0     0         -
14912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
14922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project    type can be one of:
14932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	f	A regular file
14942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	d	Directory
14952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	c	Character special device file
14962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	b	Block special device file
14972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	p	Fifo (named pipe)
14982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
14992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project    I don't bother with symlinks (permissions are irrelevant), hard
15002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project    links (special cases of regular files), or sockets (why bother).
15012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
15022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project    Regular files must exist in the target root directory.  If a char,
15032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project    block, fifo, or directory does not exist, it will be created.
15042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project*/
15052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
15062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
15072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectadd2fs_from_file(filesystem *fs, uint32 this_nod, FILE * fh, uint32 fs_timestamp, struct stats *stats)
15082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
15092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	unsigned long mode, uid, gid, major, minor;
15102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	unsigned long start, increment, count;
15112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 nod, ctime, mtime;
15122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char *c, type, *path = NULL, *path2 = NULL, *dir, *name, *line = NULL;
15132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	size_t len;
15142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	struct stat st;
15152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int nbargs, lineno = 0;
15162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
15172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fstat(fileno(fh), &st);
15182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	ctime = fs_timestamp;
15192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	mtime = st.st_mtime;
15202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	while(getline(&line, &len, fh) >= 0)
15212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
15222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode = uid = gid = major = minor = 0;
15232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		start = 0; increment = 1; count = 0;
15242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		lineno++;
15252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if((c = strchr(line, '#')))
15262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*c = 0;
15272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if (path) {
15282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free(path);
15292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			path = NULL;
15302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
15312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if (path2) {
15322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free(path2);
15332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			path2 = NULL;
15342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
15352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		nbargs = sscanf (line, "%" SCANF_PREFIX "s %c %lo %lu %lu %lu %lu %lu %lu %lu",
15362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					SCANF_STRING(path), &type, &mode, &uid, &gid, &major, &minor,
15372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					&start, &increment, &count);
15382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(nbargs < 3)
15392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
15402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if(nbargs > 0)
15412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				error_msg("device table line %d skipped: bad format for entry '%s'", lineno, path);
15422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			continue;
15432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
15442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode &= FM_IMASK;
15452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		path2 = strdup(path);
15462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		name = basename(path);
15472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		dir = dirname(path2);
15482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if((!strcmp(name, ".")) || (!strcmp(name, "..")))
15492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
15502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			error_msg("device table line %d skipped", lineno);
15512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			continue;
15522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
15532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(fs)
15542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
15552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if(!(nod = find_path(fs, this_nod, dir)))
15562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
15572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				error_msg("device table line %d skipped: can't find directory '%s' to create '%s''", lineno, dir, name);
15582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				continue;
15592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
15602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
15612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		else
15622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			nod = 0;
15632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		switch (type)
15642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
15652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'd':
15662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				mode |= FM_IFDIR;
15672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
15682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'f':
15692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				mode |= FM_IFREG;
15702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
15712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'p':
15722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				mode |= FM_IFIFO;
15732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
15742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 's':
15752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				mode |= FM_IFSOCK;
15762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
15772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'c':
15782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				mode |= FM_IFCHR;
15792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
15802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'b':
15812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				mode |= FM_IFBLK;
15822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
15832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			default:
15842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				error_msg("device table line %d skipped: bad type '%c' for entry '%s'", lineno, type, name);
15852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				continue;
15862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
15872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(stats) {
15882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if(count > 0)
15892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				stats->ninodes += count - start;
15902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			else
15912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				stats->ninodes++;
15922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		} else {
15932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if(count > 0)
15942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
15952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				char *dname;
15962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				unsigned long i;
15972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				unsigned len;
15982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				len = strlen(name) + 10;
15992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				dname = malloc(len + 1);
16002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				for(i = start; i < count; i++)
16012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				{
16022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					uint32 oldnod;
16032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					SNPRINTF(dname, len, "%s%lu", name, i);
16042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					oldnod = find_dir(fs, nod, dname);
16052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					if(oldnod)
16062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						chmod_fs(fs, oldnod, mode, uid, gid);
16072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					else
16082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						mknod_fs(fs, nod, dname, mode, uid, gid, major, minor + (i * increment - start), ctime, mtime);
16092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				}
16102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				free(dname);
16112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
16122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			else
16132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
16142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				uint32 oldnod = find_dir(fs, nod, name);
16152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				if(oldnod)
16162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					chmod_fs(fs, oldnod, mode, uid, gid);
16172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				else
16182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					mknod_fs(fs, nod, name, mode, uid, gid, major, minor, ctime, mtime);
16192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
16202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
16212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
16222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (line)
16232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		free(line);
16242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (path)
16252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		free(path);
16262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (path2)
16272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		free(path2);
16282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
16292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
16302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
16312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectprep_stat(const char *root_path)
16322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
16332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int len = strlen(root_path);
16342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
16352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if((len >= 4) && (!strcmp(root_path + len - 4, "data"))) {
16362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		source_path_len = len - 4;
16372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	} else if((len >= 7) && (!strcmp(root_path + len - 6, "system"))) {
16382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		source_path_len = len - 6;
16392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	} else {
16402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("Fixstats (-a) option requested but "
16412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				  "filesystem is not data or android!");
16422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
16432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
16442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
16452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
16462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectfix_stat(const char *path, struct stat *s)
16472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
1648e3be79ff7978674e280fec2f6e77c450a4b95e81Nick Kralevich	uint64_t capabilities;
16492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	path += source_path_len;
1650e3be79ff7978674e280fec2f6e77c450a4b95e81Nick Kralevich	fs_config(path, S_ISDIR(s->st_mode), &s->st_uid, &s->st_gid, &s->st_mode, &capabilities);
16512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
16522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
16532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// adds a tree of entries to the filesystem from current dir
16542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
16552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectadd2fs_from_dir(filesystem *fs, const char *path, uint32 this_nod, int squash_uids, int squash_perms, int fixstats, uint32 fs_timestamp, struct stats *stats)
16562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
16572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 nod;
16582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 uid, gid, mode, ctime, mtime;
16592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	const char *name;
16602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	FILE *fh;
16612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	DIR *dh;
16622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	struct dirent *dent;
16632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	struct stat st;
16642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char *lnk;
16652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 save_nod;
16662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char full_name[2048];
16672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
16682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!(dh = opendir(".")))
16692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perror_msg_and_die(".");
16702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	while((dent = readdir(dh)))
16712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
16722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if((!strcmp(dent->d_name, ".")) || (!strcmp(dent->d_name, "..")))
16732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			continue;
16742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
16752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		lstat(dent->d_name, &st);
16762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
16772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(fixstats) {
16782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			int tmp = snprintf(full_name, sizeof(full_name),
16792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			                   "%s/%s", path, dent->d_name);
16802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if(tmp >= (int)sizeof(full_name))
16812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				error_msg_and_die("Path too long!");
16822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			fix_stat(full_name, &st);
16832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		} else
16842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			full_name[0] = '\0';
16852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		uid = st.st_uid;
16862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		gid = st.st_gid;
16872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		ctime = fs_timestamp;
16882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mtime = st.st_mtime;
16892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		name = dent->d_name;
16902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		mode = get_mode(&st);
16912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(squash_uids)
16922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			uid = gid = 0;
16932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(squash_perms)
16942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			mode &= ~(FM_IRWXG | FM_IRWXO);
16952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(stats)
16962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			switch(st.st_mode & S_IFMT)
16972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
16982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFLNK:
16992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFREG:
17002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					if((st.st_mode & S_IFMT) == S_IFREG || st.st_size > 4 * (EXT2_TIND_BLOCK+1))
17012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						stats->nblocks += (st.st_size + BLOCKSIZE - 1) / BLOCKSIZE;
17022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFCHR:
17032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFBLK:
17042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFIFO:
17052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFSOCK:
17062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					stats->ninodes++;
17072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					break;
17082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFDIR:
17092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					stats->ninodes++;
17102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					if(chdir(dent->d_name) < 0)
17112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						perror_msg_and_die(dent->d_name);
17122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					add2fs_from_dir(fs, full_name, this_nod, squash_uids, squash_perms, fixstats, fs_timestamp, stats);
17132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					chdir("..");
17142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					break;
17152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				default:
17162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					break;
17172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
17182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		else
17192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
17202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if((nod = find_dir(fs, this_nod, name)))
17212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
17222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				error_msg("ignoring duplicate entry %s", name);
17232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				if(S_ISDIR(st.st_mode)) {
17242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					if(chdir(dent->d_name) < 0)
17252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						perror_msg_and_die(name);
17262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					add2fs_from_dir(fs, full_name, nod, squash_uids, squash_perms, fixstats, fs_timestamp, stats);
17272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					chdir("..");
17282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				}
17292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				continue;
17302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
17312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			save_nod = 0;
17322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			/* Check for hardlinks */
17332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if (!S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode) && st.st_nlink > 1) {
17342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				int32 hdlink = is_hardlink(st.st_ino);
17352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				if (hdlink >= 0) {
17362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					add2dir(fs, this_nod, hdlinks.hdl[hdlink].dst_nod, name);
17372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					continue;
17382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				} else {
17392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					save_nod = 1;
17402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				}
17412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
17422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			switch(st.st_mode & S_IFMT)
17432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
17442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_STRUCT_STAT_ST_RDEV
17452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFCHR:
17462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					nod = mknod_fs(fs, this_nod, name, mode|FM_IFCHR, uid, gid, major(st.st_rdev), minor(st.st_rdev), ctime, mtime);
17472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					break;
17482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFBLK:
17492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					nod = mknod_fs(fs, this_nod, name, mode|FM_IFBLK, uid, gid, major(st.st_rdev), minor(st.st_rdev), ctime, mtime);
17502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					break;
17512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif
17522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFIFO:
17532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					nod = mknod_fs(fs, this_nod, name, mode|FM_IFIFO, uid, gid, 0, 0, ctime, mtime);
17542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					break;
17552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFSOCK:
17562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					nod = mknod_fs(fs, this_nod, name, mode|FM_IFSOCK, uid, gid, 0, 0, ctime, mtime);
17572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					break;
17582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFLNK:
17592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					lnk = xreadlink(dent->d_name);
17602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					mklink_fs(fs, this_nod, name, st.st_size, (uint8*)lnk, uid, gid, ctime, mtime);
17612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					free(lnk);
17622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					break;
17632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFREG:
17642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					fh = xfopen(dent->d_name, "rb");
17652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					nod = mkfile_fs(fs, this_nod, name, mode, st.st_size, fh, uid, gid, ctime, mtime);
17662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					fclose(fh);
17672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					break;
17682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				case S_IFDIR:
17692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					nod = mkdir_fs(fs, this_nod, name, mode, uid, gid, ctime, mtime);
17702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					if(chdir(dent->d_name) < 0)
17712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						perror_msg_and_die(name);
17722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					add2fs_from_dir(fs, full_name, nod, squash_uids, squash_perms, fixstats, fs_timestamp, stats);
17732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					chdir("..");
17742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					break;
17752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				default:
17762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					error_msg("ignoring entry %s", name);
17772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
17782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if (save_nod) {
17792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				if (hdlinks.count == hdlink_cnt) {
17802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					if ((hdlinks.hdl =
17812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						 realloc (hdlinks.hdl, (hdlink_cnt + HDLINK_CNT) *
17822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project								  sizeof (struct hdlink_s))) == NULL) {
17832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						error_msg_and_die("Not enough memory");
17842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					}
17852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					hdlink_cnt += HDLINK_CNT;
17862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				}
17872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				hdlinks.hdl[hdlinks.count].src_inode = st.st_ino;
17882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				hdlinks.hdl[hdlinks.count].dst_nod = nod;
17892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				hdlinks.count++;
17902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
17912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
17922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
17932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	closedir(dh);
17942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
17952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
17962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// endianness swap of x-indirect blocks
17972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
17982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectswap_goodblocks(filesystem *fs, inode *nod)
17992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
18002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 i,j;
18012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int done=0;
18022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 *b,*b2;
18032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
18042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 nblk = nod->i_blocks / INOBLK;
18052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if((nod->i_size && !nblk) || ((nod->i_mode & FM_IFBLK) == FM_IFBLK) || ((nod->i_mode & FM_IFCHR) == FM_IFCHR))
18062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(i = 0; i <= EXT2_TIND_BLOCK; i++)
18072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			nod->i_block[i] = swab32(nod->i_block[i]);
18082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(nblk <= EXT2_IND_BLOCK)
18092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		return;
18102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	swap_block(get_blk(fs, nod->i_block[EXT2_IND_BLOCK]));
18112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(nblk <= EXT2_DIND_BLOCK + BLOCKSIZE/4)
18122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		return;
18132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* Currently this will fail b'cos the number of blocks as stored
18142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   in i_blocks also includes the indirection blocks (see
18152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   walk_bw). But this function assumes that i_blocks only
18162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   stores the count of data blocks ( Actually according to
18172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   "Understanding the Linux Kernel" (Table 17-3 p502 1st Ed)
18182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   i_blocks IS supposed to store the count of data blocks). so
18192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   with a file of size 268K nblk would be 269.The above check
18202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   will be false even though double indirection hasn't been
18212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   started.This is benign as 0 means block 0 which has been
18222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	   zeroed out and therefore points back to itself from any offset
18232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	 */
18242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// FIXME: I have fixed that, but I have the feeling the rest of
18252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// ths function needs to be fixed for the same reasons - Xav
18262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	assert(nod->i_block[EXT2_DIND_BLOCK] != 0);
18272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i = 0; i < BLOCKSIZE/4; i++)
18282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(nblk > EXT2_IND_BLOCK + BLOCKSIZE/4 + (BLOCKSIZE/4)*i )
18292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			swap_block(get_blk(fs, ((uint32*)get_blk(fs, nod->i_block[EXT2_DIND_BLOCK]))[i]));
18302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	swap_block(get_blk(fs, nod->i_block[EXT2_DIND_BLOCK]));
18312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(nblk <= EXT2_IND_BLOCK + BLOCKSIZE/4 + BLOCKSIZE/4 * BLOCKSIZE/4)
18322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		return;
18332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* Adding support for triple indirection */
18342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	b = (uint32*)get_blk(fs,nod->i_block[EXT2_TIND_BLOCK]);
18352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i=0;i < BLOCKSIZE/4 && !done ; i++) {
18362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b2 = (uint32*)get_blk(fs,b[i]);
18372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(j=0; j<BLOCKSIZE/4;j++) {
18382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if (nblk > ( EXT2_IND_BLOCK + BLOCKSIZE/4 +
18392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				     (BLOCKSIZE/4)*(BLOCKSIZE/4) +
18402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				     i*(BLOCKSIZE/4)*(BLOCKSIZE/4) +
18412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				     j*(BLOCKSIZE/4)) )
18422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			  swap_block(get_blk(fs,b2[j]));
18432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			else {
18442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			  done = 1;
18452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			  break;
18462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
18472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
18482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		swap_block((uint8 *)b2);
18492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
18502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	swap_block((uint8 *)b);
18512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return;
18522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
18532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
18542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
18552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectswap_badblocks(filesystem *fs, inode *nod)
18562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
18572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 i,j;
18582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int done=0;
18592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 *b,*b2;
18602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
18612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 nblk = nod->i_blocks / INOBLK;
18622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if((nod->i_size && !nblk) || ((nod->i_mode & FM_IFBLK) == FM_IFBLK) || ((nod->i_mode & FM_IFCHR) == FM_IFCHR))
18632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(i = 0; i <= EXT2_TIND_BLOCK; i++)
18642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			nod->i_block[i] = swab32(nod->i_block[i]);
18652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(nblk <= EXT2_IND_BLOCK)
18662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		return;
18672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	swap_block(get_blk(fs, nod->i_block[EXT2_IND_BLOCK]));
18682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(nblk <= EXT2_DIND_BLOCK + BLOCKSIZE/4)
18692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		return;
18702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* See comment in swap_goodblocks */
18712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	assert(nod->i_block[EXT2_DIND_BLOCK] != 0);
18722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	swap_block(get_blk(fs, nod->i_block[EXT2_DIND_BLOCK]));
18732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i = 0; i < BLOCKSIZE/4; i++)
18742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(nblk > EXT2_IND_BLOCK + BLOCKSIZE/4 + (BLOCKSIZE/4)*i )
18752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			swap_block(get_blk(fs, ((uint32*)get_blk(fs, nod->i_block[EXT2_DIND_BLOCK]))[i]));
18762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(nblk <= EXT2_IND_BLOCK + BLOCKSIZE/4 + BLOCKSIZE/4 * BLOCKSIZE/4)
18772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		return;
18782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* Adding support for triple indirection */
18792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	b = (uint32*)get_blk(fs,nod->i_block[EXT2_TIND_BLOCK]);
18802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	swap_block((uint8 *)b);
18812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i=0;i < BLOCKSIZE/4 && !done ; i++) {
18822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b2 = (uint32*)get_blk(fs,b[i]);
18832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		swap_block((uint8 *)b2);
18842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(j=0; j<BLOCKSIZE/4;j++) {
18852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if (nblk > ( EXT2_IND_BLOCK + BLOCKSIZE/4 +
18862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				     (BLOCKSIZE/4)*(BLOCKSIZE/4) +
18872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				     i*(BLOCKSIZE/4)*(BLOCKSIZE/4) +
18882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				     j*(BLOCKSIZE/4)) )
18892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			  swap_block(get_blk(fs,b2[j]));
18902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			else {
18912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			  done = 1;
18922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			  break;
18932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
18942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
18952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
18962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return;
18972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
18982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
18992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// endianness swap of the whole filesystem
19002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
19012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectswap_goodfs(filesystem *fs)
19022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
19032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 i;
19042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i = 1; i < fs->sb.s_inodes_count; i++)
19052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
19062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		inode *nod = get_nod(fs, i);
19072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(nod->i_mode & FM_IFDIR)
19082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
19092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			blockwalker bw;
19102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			uint32 bk;
19112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			init_bw(&bw);
19122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			while((bk = walk_bw(fs, i, &bw, 0, 0)) != WALK_END)
19132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
19142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				directory *d;
19152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				uint8 *b;
19162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				b = get_blk(fs, bk);
19172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + swab16(d->d_rec_len)))
19182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					swap_dir(d);
19192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
19202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
19212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		swap_goodblocks(fs, nod);
19222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		swap_nod(nod);
19232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
19242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i=0;i<GRP_NBGROUPS(fs);i++)
19252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		swap_gd(&(fs->gd[i]));
19262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	swap_sb(&fs->sb);
19272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
19282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
19292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
19302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectswap_badfs(filesystem *fs)
19312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
19322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 i;
19332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	swap_sb(&fs->sb);
19342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i=0;i<GRP_NBGROUPS(fs);i++)
19352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		swap_gd(&(fs->gd[i]));
19362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i = 1; i < fs->sb.s_inodes_count; i++)
19372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
19382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		inode *nod = get_nod(fs, i);
19392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		swap_nod(nod);
19402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		swap_badblocks(fs, nod);
19412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(nod->i_mode & FM_IFDIR)
19422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
19432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			blockwalker bw;
19442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			uint32 bk;
19452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			init_bw(&bw);
19462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			while((bk = walk_bw(fs, i, &bw, 0, 0)) != WALK_END)
19472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
19482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				directory *d;
19492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				uint8 *b;
19502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				b = get_blk(fs, bk);
19512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))
19522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					swap_dir(d);
19532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
19542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
19552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
19562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
19572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
19582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// initialize an empty filesystem
19592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic filesystem *
19602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectinit_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp)
19612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
19622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 i;
19632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	filesystem *fs;
19642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	directory *d;
19652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint8 * b;
19662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 nod, first_block;
19672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 nbgroups,nbinodes_per_group,overhead_per_group,free_blocks,
19682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		free_blocks_per_group,nbblocks_per_group,min_nbgroups;
19692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 gdsz,itblsz,bbmpos,ibmpos,itblpos;
19702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 j;
19712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint8 *bbm,*ibm;
19722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	inode *itab0;
19732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
19742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(nbresrvd < 0)
19752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("reserved blocks value is invalid. Note: options have changed, see --help or the man page.");
19762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(nbinodes < EXT2_FIRST_INO - 1 + (nbresrvd ? 1 : 0))
19772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("too few inodes. Note: options have changed, see --help or the man page.");
19782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(nbblocks < 8)
19792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("too few blocks. Note: options have changed, see --help or the man page.");
19802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
19812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* nbinodes is the total number of inodes in the system.
19822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	 * a block group can have no more than 8192 inodes.
19832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	 */
19842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	min_nbgroups = (nbinodes + INODES_PER_GROUP - 1) / INODES_PER_GROUP;
19852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
19862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* nbblocks is the total number of blocks in the filesystem.
19872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	 * a block group can have no more than 8192 blocks.
19882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	 */
19892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	first_block = (BLOCKSIZE == 1024);
19902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	nbgroups = (nbblocks - first_block + BLOCKS_PER_GROUP - 1) / BLOCKS_PER_GROUP;
19912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(nbgroups < min_nbgroups) nbgroups = min_nbgroups;
19922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	nbblocks_per_group = rndup((nbblocks - first_block + nbgroups - 1)/nbgroups, 8);
19932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	nbinodes_per_group = rndup((nbinodes + nbgroups - 1)/nbgroups,
19942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project						(BLOCKSIZE/sizeof(inode)));
19952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (nbinodes_per_group < 16)
19962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		nbinodes_per_group = 16; //minimum number b'cos the first 10 are reserved
19972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
19982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	gdsz = rndup(nbgroups*sizeof(groupdescriptor),BLOCKSIZE)/BLOCKSIZE;
19992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	itblsz = nbinodes_per_group * sizeof(inode)/BLOCKSIZE;
20002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	overhead_per_group = 3 /*sb,bbm,ibm*/ + gdsz + itblsz;
20012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if((uint32)nbblocks - 1 < overhead_per_group * nbgroups)
20022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("too much overhead, try fewer inodes or more blocks. Note: options have changed, see --help or the man page.");
20032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	free_blocks = nbblocks - overhead_per_group*nbgroups - 1 /*boot block*/;
20042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	free_blocks_per_group = nbblocks_per_group - overhead_per_group;
20052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
20062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!(fs = (filesystem*)calloc(nbblocks, BLOCKSIZE)))
20072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("not enough memory for filesystem");
20082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
20092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// create the superblock for an empty filesystem
20102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_inodes_count = nbinodes_per_group * nbgroups;
20112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_blocks_count = nbblocks;
20122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_r_blocks_count = nbresrvd;
20132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_free_blocks_count = free_blocks;
20142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_free_inodes_count = fs->sb.s_inodes_count - EXT2_FIRST_INO + 1;
20152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_first_data_block = first_block;
20162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_log_block_size = BLOCKSIZE >> 11;
20172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_log_frag_size = BLOCKSIZE >> 11;
20182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_blocks_per_group = nbblocks_per_group;
20192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_frags_per_group = nbblocks_per_group;
20202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_inodes_per_group = nbinodes_per_group;
20212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_wtime = fs_timestamp;
20222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_magic = EXT2_MAGIC_NUMBER;
20232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_lastcheck = fs_timestamp;
20242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
20252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// set up groupdescriptors
20262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i=0, bbmpos=gdsz+2, ibmpos=bbmpos+1, itblpos=ibmpos+1;
20272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		i<nbgroups;
20282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		i++, bbmpos+=nbblocks_per_group, ibmpos+=nbblocks_per_group, itblpos+=nbblocks_per_group)
20292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
20302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(free_blocks > free_blocks_per_group) {
20312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			fs->gd[i].bg_free_blocks_count = free_blocks_per_group;
20322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blocks -= free_blocks_per_group;
20332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		} else {
20342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			fs->gd[i].bg_free_blocks_count = free_blocks;
20352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			free_blocks = 0; // this is the last block group
20362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
20372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(i)
20382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			fs->gd[i].bg_free_inodes_count = nbinodes_per_group;
20392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		else
20402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			fs->gd[i].bg_free_inodes_count = nbinodes_per_group -
20412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project							EXT2_FIRST_INO + 2;
20422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		fs->gd[i].bg_used_dirs_count = 0;
20432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		fs->gd[i].bg_block_bitmap = bbmpos;
20442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		fs->gd[i].bg_inode_bitmap = ibmpos;
20452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		fs->gd[i].bg_inode_table = itblpos;
20462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
20472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
20482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* Mark non-filesystem blocks and inodes as allocated */
20492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* Mark system blocks and inodes as allocated         */
20502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i = 0; i<nbgroups;i++) {
20512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
20522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		/* Block bitmap */
20532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		bbm = get_blk(fs,fs->gd[i].bg_block_bitmap);
20542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		//non-filesystem blocks
20552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(j = fs->gd[i].bg_free_blocks_count
20562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		        + overhead_per_group + 1; j <= BLOCKSIZE * 8; j++)
20572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			allocate(bbm, j);
20582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		//system blocks
20592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(j = 1; j <= overhead_per_group; j++)
20602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			allocate(bbm, j);
20612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
20622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		/* Inode bitmap */
20632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		ibm = get_blk(fs,fs->gd[i].bg_inode_bitmap);
20642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		//non-filesystem inodes
20652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(j = fs->sb.s_inodes_per_group+1; j <= BLOCKSIZE * 8; j++)
20662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			allocate(ibm, j);
20672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
20682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		//system inodes
20692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(i == 0)
20702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			for(j = 1; j < EXT2_FIRST_INO; j++)
20712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				allocate(ibm, j);
20722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
20732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
20742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// make root inode and directory
20752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* We have groups now. Add the root filesystem in group 0 */
20762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	/* Also increment the directory count for group 0 */
20772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->gd[0].bg_free_inodes_count--;
20782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->gd[0].bg_used_dirs_count = 1;
20792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	itab0 = (inode *)get_blk(fs,fs->gd[0].bg_inode_table);
20802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	itab0[EXT2_ROOT_INO-1].i_mode = FM_IFDIR | FM_IRWXU | FM_IRGRP | FM_IROTH | FM_IXGRP | FM_IXOTH;
20812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	itab0[EXT2_ROOT_INO-1].i_ctime = fs_timestamp;
20822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	itab0[EXT2_ROOT_INO-1].i_mtime = fs_timestamp;
20832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	itab0[EXT2_ROOT_INO-1].i_atime = fs_timestamp;
20842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	itab0[EXT2_ROOT_INO-1].i_size = BLOCKSIZE;
20852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	itab0[EXT2_ROOT_INO-1].i_links_count = 2;
20862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
20872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!(b = get_workblk()))
20882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("get_workblk() failed.");
20892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	d = (directory*)b;
20902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	d->d_inode = EXT2_ROOT_INO;
20912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	d->d_rec_len = sizeof(directory)+4;
20922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	d->d_name_len = 1;
20932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	strcpy(d->d_name, ".");
20942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	d = (directory*)(b + d->d_rec_len);
20952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	d->d_inode = EXT2_ROOT_INO;
20962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	d->d_rec_len = BLOCKSIZE - (sizeof(directory)+4);
20972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	d->d_name_len = 2;
20982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	strcpy(d->d_name, "..");
20992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	extend_blk(fs, EXT2_ROOT_INO, b, 1);
21002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
21012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// make lost+found directory and reserve blocks
21022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(fs->sb.s_r_blocks_count)
21032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
21042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		nod = mkdir_fs(fs, EXT2_ROOT_INO, "lost+found", FM_IRWXU, 0, 0, fs_timestamp, fs_timestamp);
21052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		memset(b, 0, BLOCKSIZE);
21062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		((directory*)b)->d_rec_len = BLOCKSIZE;
21072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		/* We run into problems with e2fsck if directory lost+found grows
21082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		 * bigger than this. Need to find out why this happens - sundar
21092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		 */
21102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if (fs->sb.s_r_blocks_count > fs->sb.s_blocks_count * MAX_RESERVED_BLOCKS )
21112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			fs->sb.s_r_blocks_count = fs->sb.s_blocks_count * MAX_RESERVED_BLOCKS;
21122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(i = 1; i < fs->sb.s_r_blocks_count; i++)
21132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			extend_blk(fs, nod, b, 1);
21142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		get_nod(fs, nod)->i_size = fs->sb.s_r_blocks_count * BLOCKSIZE;
21152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
21162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	free_workblk(b);
21172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
21182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// administrative info
21192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_state = 1;
21202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_max_mnt_count = 20;
21212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
21222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	// options for me
21232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(holes)
21242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		fs->sb.s_reserved[200] |= OP_HOLES;
21252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
21262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return fs;
21272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
21282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
21292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// loads a filesystem from disk
21302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic filesystem *
21312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectload_fs(FILE * fh, int swapit)
21322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
21332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	size_t fssize;
21342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	filesystem *fs;
21352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if((fseek(fh, 0, SEEK_END) < 0) || ((ssize_t)(fssize = ftell(fh)) == -1))
21362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perror_msg_and_die("input filesystem image");
21372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	rewind(fh);
21382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fssize = (fssize + BLOCKSIZE - 1) / BLOCKSIZE;
21392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(fssize < 16) // totally arbitrary
21402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("too small filesystem");
21412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!(fs = (filesystem*)calloc(fssize, BLOCKSIZE)))
21422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("not enough memory for filesystem");
21432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(fread(fs, BLOCKSIZE, fssize, fh) != fssize)
21442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perror_msg_and_die("input filesystem image");
21452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(swapit)
21462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		swap_badfs(fs);
21472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(fs->sb.s_rev_level || (fs->sb.s_magic != EXT2_MAGIC_NUMBER))
21482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("not a suitable ext2 filesystem");
21492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return fs;
21502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
21512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
21522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
21532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectfree_fs(filesystem *fs)
21542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
21552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	free(fs);
21562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
21572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
21582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// just walk through blocks list
21592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
21602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectflist_blocks(filesystem *fs, uint32 nod, FILE *fh)
21612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
21622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	blockwalker bw;
21632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bk;
21642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	init_bw(&bw);
21652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
21662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		fprintf(fh, " %d", bk);
21672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fprintf(fh, "\n");
21682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
21692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
21702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// walk through blocks list
21712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
21722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectlist_blocks(filesystem *fs, uint32 nod)
21732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
21742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int bn = 0;
21752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	blockwalker bw;
21762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bk;
21772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	init_bw(&bw);
21782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("blocks in inode %d:", nod);
21792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
21802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		printf(" %d", bk), bn++;
21812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("\n%d blocks (%d bytes)\n", bn, bn * BLOCKSIZE);
21822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
21832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
21842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// saves blocks to FILE*
21852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
21862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectwrite_blocks(filesystem *fs, uint32 nod, FILE* f)
21872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
21882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	blockwalker bw;
21892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bk;
21902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int32 fsize = get_nod(fs, nod)->i_size;
21912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	init_bw(&bw);
21922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
21932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
21942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(fsize <= 0)
21952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			error_msg_and_die("wrong size while saving inode %d", nod);
21962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(fwrite(get_blk(fs, bk), (fsize > BLOCKSIZE) ? BLOCKSIZE : fsize, 1, f) != 1)
21972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			error_msg_and_die("error while saving inode %d", nod);
21982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		fsize -= BLOCKSIZE;
21992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
22002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
22012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
22022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
22032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// print block/char device minor and major
22042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
22052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectprint_dev(filesystem *fs, uint32 nod)
22062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
22072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int minor, major;
22082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	minor = ((uint8*)get_nod(fs, nod)->i_block)[0];
22092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	major = ((uint8*)get_nod(fs, nod)->i_block)[1];
22102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("major: %d, minor: %d\n", major, minor);
22112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
22122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
22132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// print an inode as a directory
22142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
22152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectprint_dir(filesystem *fs, uint32 nod)
22162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
22172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	blockwalker bw;
22182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 bk;
22192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	init_bw(&bw);
22202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("directory for inode %d:\n", nod);
22212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
22222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
22232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		directory *d;
22242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		uint8 *b;
22252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		b = get_blk(fs, bk);
22262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))
22272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if(d->d_inode)
22282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
22292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				int i;
22302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				printf("entry '");
22312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				for(i = 0; i < d->d_name_len; i++)
22322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					putchar(d->d_name[i]);
22332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				printf("' (inode %d): rec_len: %d (name_len: %d)\n", d->d_inode, d->d_rec_len, d->d_name_len);
22342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
22352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
22362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
22372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
22382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// print a symbolic link
22392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
22402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectprint_link(filesystem *fs, uint32 nod)
22412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
22422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!get_nod(fs, nod)->i_blocks)
22432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		printf("links to '%s'\n", (char*)get_nod(fs, nod)->i_block);
22442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else
22452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
22462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		printf("links to '");
22472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		write_blocks(fs, nod, stdout);
22482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		printf("'\n");
22492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
22502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
22512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
22522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// make a ls-like printout of permissions
22532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
22542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectmake_perms(uint32 mode, char perms[11])
22552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
22562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	strcpy(perms, "----------");
22572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(mode & FM_IRUSR)
22582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perms[1] = 'r';
22592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(mode & FM_IWUSR)
22602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perms[2] = 'w';
22612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(mode & FM_IXUSR)
22622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perms[3] = 'x';
22632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(mode & FM_IRGRP)
22642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perms[4] = 'r';
22652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(mode & FM_IWGRP)
22662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perms[5] = 'w';
22672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(mode & FM_IXGRP)
22682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perms[6] = 'x';
22692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(mode & FM_IROTH)
22702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perms[7] = 'r';
22712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(mode & FM_IWOTH)
22722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perms[8] = 'w';
22732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(mode & FM_IXOTH)
22742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perms[9] = 'x';
22752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(mode & FM_ISUID)
22762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perms[3] = 's';
22772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(mode & FM_ISGID)
22782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perms[6] = 's';
22792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(mode & FM_ISVTX)
22802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perms[9] = 't';
22812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	switch(mode & FM_IFMT)
22822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
22832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case 0:
22842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*perms = '0';
22852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
22862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFSOCK:
22872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*perms = 's';
22882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
22892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFLNK:
22902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*perms = 'l';
22912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
22922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFREG:
22932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*perms = '-';
22942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
22952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFBLK:
22962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*perms = 'b';
22972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
22982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFDIR:
22992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*perms = 'd';
23002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFCHR:
23022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*perms = 'c';
23032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFIFO:
23052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*perms = 'p';
23062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		default:
23082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*perms = '?';
23092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
23102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
23112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
23122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// print an inode
23132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
23142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectprint_inode(filesystem *fs, uint32 nod)
23152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
23162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char *s;
23172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char perms[11];
23182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!get_nod(fs, nod)->i_mode)
23192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		return;
23202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	switch(nod)
23212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
23222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case EXT2_BAD_INO:
23232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			s = "bad blocks";
23242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case EXT2_ROOT_INO:
23262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			s = "root";
23272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case EXT2_ACL_IDX_INO:
23292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case EXT2_ACL_DATA_INO:
23302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			s = "ACL";
23312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case EXT2_BOOT_LOADER_INO:
23332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			s = "boot loader";
23342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case EXT2_UNDEL_DIR_INO:
23362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			s = "undelete directory";
23372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		default:
23392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			s = (nod >= EXT2_FIRST_INO) ? "normal" : "unknown reserved";
23402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
23412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("inode %d (%s, %d links): ", nod, s, get_nod(fs, nod)->i_links_count);
23422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(!allocated(GRP_GET_INODE_BITMAP(fs,nod), GRP_IBM_OFFSET(fs,nod)))
23432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
23442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		printf("unallocated\n");
23452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		return;
23462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
23472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	make_perms(get_nod(fs, nod)->i_mode, perms);
23482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("%s,  size: %d byte%s (%d block%s)\n", perms, plural(get_nod(fs, nod)->i_size), plural(get_nod(fs, nod)->i_blocks / INOBLK));
23492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	switch(get_nod(fs, nod)->i_mode & FM_IFMT)
23502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
23512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFSOCK:
23522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			list_blocks(fs, nod);
23532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFLNK:
23552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			print_link(fs, nod);
23562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFREG:
23582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			list_blocks(fs, nod);
23592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFBLK:
23612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			print_dev(fs, nod);
23622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFDIR:
23642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			list_blocks(fs, nod);
23652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			print_dir(fs, nod);
23662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFCHR:
23682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			print_dev(fs, nod);
23692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		case FM_IFIFO:
23712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			list_blocks(fs, nod);
23722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			break;
23732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		default:
23742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			list_blocks(fs, nod);
23752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
23762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("Done with inode %d\n",nod);
23772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
23782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
23792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project// describes various fields in a filesystem
23802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
23812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectprint_fs(filesystem *fs)
23822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
23832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 i;
23842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint8 *ibm;
23852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
23862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("%d blocks (%d free, %d reserved), first data block: %d\n",
23872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	       fs->sb.s_blocks_count, fs->sb.s_free_blocks_count,
23882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	       fs->sb.s_r_blocks_count, fs->sb.s_first_data_block);
23892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("%d inodes (%d free)\n", fs->sb.s_inodes_count,
23902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	       fs->sb.s_free_inodes_count);
23912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("block size = %d, frag size = %d\n",
23922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	       fs->sb.s_log_block_size ? (fs->sb.s_log_block_size << 11) : 1024,
23932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	       fs->sb.s_log_frag_size ? (fs->sb.s_log_frag_size << 11) : 1024);
23942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("number of groups: %d\n",GRP_NBGROUPS(fs));
23952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("%d blocks per group,%d frags per group,%d inodes per group\n",
23962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	     fs->sb.s_blocks_per_group, fs->sb.s_frags_per_group,
23972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	     fs->sb.s_inodes_per_group);
23982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("Size of inode table: %d blocks\n",
23992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		(int)(fs->sb.s_inodes_per_group * sizeof(inode) / BLOCKSIZE));
24002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for (i = 0; i < GRP_NBGROUPS(fs); i++) {
24012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		printf("Group No: %d\n", i+1);
24022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		printf("block bitmap: block %d,inode bitmap: block %d, inode table: block %d\n",
24032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		     fs->gd[i].bg_block_bitmap, fs->gd[i].bg_inode_bitmap,
24042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		     fs->gd[i].bg_inode_table);
24052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		printf("block bitmap allocation:\n");
24062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		print_bm(GRP_GET_GROUP_BBM(fs, i),fs->sb.s_blocks_per_group);
24072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		printf("inode bitmap allocation:\n");
24082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		ibm = GRP_GET_GROUP_IBM(fs, i);
24092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		print_bm(ibm, fs->sb.s_inodes_per_group);
24102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for (i = 1; i <= fs->sb.s_inodes_per_group; i++)
24112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if (allocated(ibm, i))
24122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				print_inode(fs, i);
24132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
24142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
24152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
24162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
24172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectdump_fs(filesystem *fs, FILE * fh, int swapit)
24182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
24192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint32 nbblocks = fs->sb.s_blocks_count;
24202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fs->sb.s_reserved[200] = 0;
24212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(swapit)
24222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		swap_goodfs(fs);
24232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(fwrite(fs, BLOCKSIZE, nbblocks, fh) < nbblocks)
24242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		perror_msg_and_die("output filesystem image");
24252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(swapit)
24262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		swap_badfs(fs);
24272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
24282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
24292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
24302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectpopulate_fs(filesystem *fs, char **dopt, int didx, int squash_uids, int squash_perms, int fixstats, uint32 fs_timestamp, struct stats *stats)
24312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
24322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int i;
24332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i = 0; i < didx; i++)
24342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
24352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		struct stat st;
24362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		FILE *fh;
24372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		int pdir;
24382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		char *pdest;
24392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		uint32 nod = EXT2_ROOT_INO;
24402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(fs)
24412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if((pdest = strchr(dopt[i], ':')))
24422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
24432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				*(pdest++) = 0;
24442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				if(!(nod = find_path(fs, EXT2_ROOT_INO, pdest)))
24452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					error_msg_and_die("path %s not found in filesystem", pdest);
24462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
24472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		stat(dopt[i], &st);
24482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		switch(st.st_mode & S_IFMT)
24492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
24502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case S_IFREG:
24512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				fh = xfopen(dopt[i], "rb");
24522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				add2fs_from_file(fs, nod, fh, fs_timestamp, stats);
24532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				fclose(fh);
24542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
24552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case S_IFDIR:
24562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				if((pdir = open(".", O_RDONLY)) < 0)
24572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					perror_msg_and_die(".");
24582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				if(chdir(dopt[i]) < 0)
24592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					perror_msg_and_die(dopt[i]);
24602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				if (fixstats)
24612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					prep_stat(dopt[i]);
24622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				add2fs_from_dir(fs, dopt[i], nod, squash_uids, squash_perms, fixstats, fs_timestamp, stats);
24632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				if(fchdir(pdir) < 0)
24642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					perror_msg_and_die("fchdir");
24652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				if(close(pdir) < 0)
24662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project					perror_msg_and_die("close");
24672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
24682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			default:
24692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				error_msg_and_die("%s is neither a file nor a directory", dopt[i]);
24702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
24712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
24722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
24732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
24742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
24752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectshowversion(void)
24762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
24772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	printf("genext2fs " VERSION "\n");
24782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
24792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
24802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectstatic void
24812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectshowhelp(void)
24822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
24832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fprintf(stderr, "Usage: %s [options] image\n"
24842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"Create an ext2 filesystem image from directories/files\n\n"
24852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -x, --starting-image <image>\n"
24862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -d, --root <directory>\n"
24872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -D, --devtable <file>\n"
24882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -b, --size-in-blocks <blocks>\n"
24892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -i, --bytes-per-inode <bytes per inode>\n"
24902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -N, --number-of-inodes <number of inodes>\n"
24912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -m, --reserved-percentage <percentage of blocks to reserve>\n"
24922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -g, --block-map <path>     Generate a block map file for this path.\n"
24932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -e, --fill-value <value>   Fill unallocated blocks with value.\n"
24942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -z, --allow-holes          Allow files with holes.\n"
24952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -f, --faketime             Set filesystem timestamps to 0 (for testing).\n"
24962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -q, --squash               Same as \"-U -P\".\n"
24972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -U, --squash-uids          Squash owners making all files be owned by root.\n"
24982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -P, --squash-perms         Squash permissions on all files.\n"
24992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -a, --fix-android-stats    Fix-up file stats (user, perms, ...)\n"
25002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -h, --help\n"
25012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -V, --version\n"
25022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"  -v, --verbose\n\n"
25032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	"Report bugs to genext2fs-devel@lists.sourceforge.net\n", app_name);
25042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
25052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
25062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define MAX_DOPT 128
25072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define MAX_GOPT 128
25082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
25092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#define MAX_FILENAME 255
25102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
25112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectextern char* optarg;
25122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectextern int optind, opterr, optopt;
25132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
25142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectint
25152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Projectmain(int argc, char **argv)
25162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project{
25172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int nbblocks = -1;
25182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int nbinodes = -1;
25192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int nbresrvd = -1;
25202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	float bytes_per_inode = -1;
25212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	float reserved_frac = -1;
25222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int fs_timestamp = -1;
25232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char * fsout = "-";
25242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char * fsin = 0;
25252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char * dopt[MAX_DOPT];
25262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int didx = 0;
25272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	char * gopt[MAX_GOPT];
25282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int gidx = 0;
25292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int verbose = 0;
25302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int holes = 0;
25312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int emptyval = 0;
25322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int squash_uids = 0;
25332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int squash_perms = 0;
25342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int fix_android_stats = 0;
25352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	uint16 endian = 1;
25362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int bigendian = !*(char*)&endian;
25372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	filesystem *fs;
25382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int i;
25392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	int c;
25402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	struct stats stats;
25412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
25422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#if HAVE_GETOPT_LONG
25432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	struct option longopts[] = {
25442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "starting-image",	required_argument,	NULL, 'x' },
25452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "root",		required_argument,	NULL, 'd' },
25462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "devtable",		required_argument,	NULL, 'D' },
25472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "size-in-blocks",	required_argument,	NULL, 'b' },
25482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "bytes-per-inode",	required_argument,	NULL, 'i' },
25492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "number-of-inodes",	required_argument,	NULL, 'N' },
25502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "reserved-percentage", required_argument,	NULL, 'm' },
25512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "block-map",	required_argument,	NULL, 'g' },
25522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "fill-value",	required_argument,	NULL, 'e' },
25532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "allow-holes",	no_argument, 		NULL, 'z' },
25542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "faketime",		no_argument,		NULL, 'f' },
25552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "squash",		no_argument,		NULL, 'q' },
25562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "squash-uids",	no_argument,		NULL, 'U' },
25572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "squash-perms",	no_argument,		NULL, 'P' },
25582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "fix-android-stats",no_argument,		NULL, 'a' },
25592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "help",		no_argument,		NULL, 'h' },
25602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "version",		no_argument,		NULL, 'V' },
25612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { "verbose",		no_argument,		NULL, 'v' },
25622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	  { 0, 0, 0, 0}
25632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	} ;
25642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
25652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	app_name = argv[0];
25662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
25672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	while((c = getopt_long(argc, argv, "x:d:D:b:i:N:m:g:e:zfqUPahVv", longopts, NULL)) != EOF) {
25682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#else
25692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	app_name = argv[0];
25702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
25712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	while((c = getopt(argc, argv,      "x:d:D:b:i:N:m:g:e:zfqUPahVv")) != EOF) {
25722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project#endif /* HAVE_GETOPT_LONG */
25732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		switch(c)
25742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
25752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'x':
25762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				fsin = optarg;
25772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
25782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'd':
25792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'D':
25802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				dopt[didx++] = optarg;
25812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
25822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'b':
25832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				nbblocks = SI_atof(optarg);
25842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
25852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'i':
25862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				bytes_per_inode = SI_atof(optarg);
25872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
25882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'N':
25892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				nbinodes = SI_atof(optarg);
25902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
25912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'm':
25922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				reserved_frac = SI_atof(optarg) / 100;
25932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
25942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'g':
25952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				gopt[gidx++] = optarg;
25962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
25972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'e':
25982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				emptyval = atoi(optarg);
25992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
26002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'z':
26012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				holes = 1;
26022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
26032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'f':
26042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				fs_timestamp = 0;
26052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
26062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'q':
26072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				squash_uids = 1;
26082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				squash_perms = 1;
26092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
26102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'U':
26112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				squash_uids = 1;
26122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
26132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'P':
26142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				squash_perms = 1;
26152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
26162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'a':
26172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				fix_android_stats = 1;
26182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
26192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'h':
26202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				showhelp();
26212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				exit(0);
26222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'V':
26232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				showversion();
26242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				exit(0);
26252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			case 'v':
26262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				verbose = 1;
26272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				showversion();
26282068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				break;
26292068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			default:
26302068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				error_msg_and_die("Note: options have changed, see --help or the man page.");
26312068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
26322068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
26332068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
26342068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(optind < (argc - 1))
26352068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("Too many arguments. Try --help or else see the man page.");
26362068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(optind > (argc - 1))
26372068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("Not enough arguments. Try --help or else see the man page.");
26382068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
26392068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(fix_android_stats && (squash_uids || squash_perms))
26402068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("Cannot squash uid/perms and fix them up for Android at the same time.");
26412068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
26422068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	fsout = argv[optind];
26432068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
26442068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	hdlinks.hdl = (struct hdlink_s *)malloc(hdlink_cnt * sizeof(struct hdlink_s));
26452068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if (!hdlinks.hdl)
26462068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		error_msg_and_die("Not enough memory");
26472068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	hdlinks.count = 0 ;
26482068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
26492068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(fsin)
26502068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
26512068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(strcmp(fsin, "-"))
26522068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		{
26532068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			FILE * fh = xfopen(fsin, "rb");
26542068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			fs = load_fs(fh, bigendian);
26552068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			fclose(fh);
26562068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
26572068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		else
26582068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			fs = load_fs(stdin, bigendian);
26592068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
26602068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else
26612068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
26622068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(reserved_frac == -1)
26632068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			nbresrvd = nbblocks * RESERVED_BLOCKS;
26642068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		else
26652068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			nbresrvd = nbblocks * reserved_frac;
26662068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
26672068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		stats.ninodes = EXT2_FIRST_INO - 1 + (nbresrvd ? 1 : 0);
26682068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		stats.nblocks = 0;
26692068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
26702068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		populate_fs(NULL, dopt, didx, squash_uids, squash_perms, 0, fs_timestamp, &stats);
26712068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
26722068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(nbinodes == -1)
26732068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			nbinodes = stats.ninodes;
26742068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		else
26752068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if(stats.ninodes > (unsigned long)nbinodes)
26762068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			{
26772068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				fprintf(stderr, "number of inodes too low, increasing to %ld\n", stats.ninodes);
26782068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				nbinodes = stats.ninodes;
26792068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			}
26802068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
26812068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(bytes_per_inode != -1) {
26822068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			int tmp_nbinodes = nbblocks * BLOCKSIZE / bytes_per_inode;
26832068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if(tmp_nbinodes > nbinodes)
26842068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				nbinodes = tmp_nbinodes;
26852068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		}
26862068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(fs_timestamp == -1)
26872068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			fs_timestamp = time(NULL);
26882068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		fs = init_fs(nbblocks, nbinodes, nbresrvd, holes, fs_timestamp);
26892068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
26902068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
26912068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	populate_fs(fs, dopt, didx, squash_uids, squash_perms, fix_android_stats, fs_timestamp, NULL);
26922068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project
26932068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(emptyval) {
26942068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		uint32 b;
26952068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		for(b = 1; b < fs->sb.s_blocks_count; b++)
26962068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			if(!allocated(GRP_GET_BLOCK_BITMAP(fs,b),GRP_BBM_OFFSET(fs,b)))
26972068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project				memset(get_blk(fs, b), emptyval, BLOCKSIZE);
26982068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
26992068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(verbose)
27002068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		print_fs(fs);
27012068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	for(i = 0; i < gidx; i++)
27022068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
27032068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		uint32 nod;
27042068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		char fname[MAX_FILENAME];
27052068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		char *p;
27062068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		FILE *fh;
27072068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		if(!(nod = find_path(fs, EXT2_ROOT_INO, gopt[i])))
27082068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			error_msg_and_die("path %s not found in filesystem", gopt[i]);
27092068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		while((p = strchr(gopt[i], '/')))
27102068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project			*p = '_';
27112068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		SNPRINTF(fname, MAX_FILENAME-1, "%s.blk", gopt[i]);
27122068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		fh = xfopen(fname, "wb");
27132068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		fprintf(fh, "%d:", get_nod(fs, nod)->i_size);
27142068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		flist_blocks(fs, nod, fh);
27152068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		fclose(fh);
27162068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
27172068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	if(strcmp(fsout, "-"))
27182068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	{
27192068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		FILE * fh = xfopen(fsout, "wb");
27202068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		dump_fs(fs, fh, bigendian);
27212068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		fclose(fh);
27222068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	}
27232068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	else
27242068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project		dump_fs(fs, stdout, bigendian);
27252068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	free_fs(fs);
27262068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project	return 0;
27272068259fff846977bdd4262fa27ea6cb81d35a78The Android Open Source Project}
2728