7191a5f5587f9e2ad0b55565d89357a735ef5a4b
[oweals/busybox.git] / util-linux / mkfs_ext2.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * mkfs_ext2: utility to create EXT2 filesystem
4  * inspired by genext2fs
5  *
6  * Busybox'ed (2009) by Vladimir Dronnikov <dronnikov@gmail.com>
7  *
8  * Licensed under GPLv2, see file LICENSE in this tarball for details.
9  */
10 #include "libbb.h"
11 #include <linux/fs.h>
12 #include <linux/ext2_fs.h>
13 #include <sys/user.h> /* PAGE_SIZE */
14 #ifndef PAGE_SIZE
15 # define PAGE_SIZE 4096
16 #endif
17 #include "volume_id/volume_id_internal.h"
18
19 #define ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT 0
20 #define ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX 1
21
22 // from e2fsprogs
23 #define s_reserved_gdt_blocks s_padding1
24 #define s_mkfs_time           s_reserved[0]
25 #define s_flags               s_reserved[22]
26 #define EXT2_HASH_HALF_MD4     1
27 #define EXT2_FLAGS_SIGNED_HASH 0x0001
28
29 // whiteout: for writable overlays
30 //#define LINUX_S_IFWHT                  0160000
31 //#define EXT2_FEATURE_INCOMPAT_WHITEOUT 0x0020
32
33 // storage helpers
34 char BUG_wrong_field_size(void);
35 #define STORE_LE(field, value) \
36 do { \
37         if (sizeof(field) == 4) \
38                 field = cpu_to_le32(value); \
39         else if (sizeof(field) == 2) \
40                 field = cpu_to_le16(value); \
41         else if (sizeof(field) == 1) \
42                 field = (value); \
43         else \
44                 BUG_wrong_field_size(); \
45 } while (0)
46
47 #define FETCH_LE32(field) \
48         (sizeof(field) == 4 ? cpu_to_le32(field) : BUG_wrong_field_size())
49
50 // All fields are little-endian
51 struct ext2_dir {
52         uint32_t inode1;
53         uint16_t rec_len1;
54         uint8_t  name_len1;
55         uint8_t  file_type1;
56         char     name1[4];
57         uint32_t inode2;
58         uint16_t rec_len2;
59         uint8_t  name_len2;
60         uint8_t  file_type2;
61         char     name2[4];
62         uint32_t inode3;
63         uint16_t rec_len3;
64         uint8_t  name_len3;
65         uint8_t  file_type3;
66         char     name3[12];
67 };
68
69 static unsigned int_log2(unsigned arg)
70 {
71         unsigned r = 0;
72         while ((arg >>= 1) != 0)
73                 r++;
74         return r;
75 }
76
77 // taken from mkfs_minix.c. libbb candidate?
78 // "uint32_t size", since we never use it for anything >32 bits
79 static uint32_t div_roundup(uint32_t size, uint32_t n)
80 {
81         // Overflow-resistant
82         uint32_t res = size / n;
83         if (res * n != size)
84                 res++;
85         return res;
86 }
87
88 static void allocate(uint8_t *bitmap, uint32_t blocksize, uint32_t start, uint32_t end)
89 {
90         uint32_t i;
91
92 //bb_info_msg("ALLOC: [%u][%u][%u]: [%u-%u]:=[%x],[%x]", blocksize, start, end, start/8, blocksize - end/8 - 1, (1 << (start & 7)) - 1, (uint8_t)(0xFF00 >> (end & 7)));
93         memset(bitmap, 0, blocksize);
94         i = start / 8;
95         memset(bitmap, 0xFF, i);
96         bitmap[i] = (1 << (start & 7)) - 1; //0..7 => 00000000..01111111
97         i = end / 8;
98         bitmap[blocksize - i - 1] |= 0x7F00 >> (end & 7); //0..7 => 00000000..11111110
99         memset(bitmap + blocksize - i, 0xFF, i); // N.B. no overflow here!
100 }
101
102 static uint32_t has_super(uint32_t x)
103 {
104         // 0, 1 and powers of 3, 5, 7 up to 2^32 limit
105         static const uint32_t supers[] = {
106                 0, 1, 3, 5, 7, 9, 25, 27, 49, 81, 125, 243, 343, 625, 729,
107                 2187, 2401, 3125, 6561, 15625, 16807, 19683, 59049, 78125,
108                 117649, 177147, 390625, 531441, 823543, 1594323, 1953125,
109                 4782969, 5764801, 9765625, 14348907, 40353607, 43046721,
110                 48828125, 129140163, 244140625, 282475249, 387420489,
111                 1162261467, 1220703125, 1977326743, 3486784401/* >2^31 */,
112         };
113         const uint32_t *sp = supers + ARRAY_SIZE(supers);
114         while (1) {
115                 sp--;
116                 if (x == *sp)
117                         return 1;
118                 if (x > *sp)
119                         return 0;
120         }
121 }
122
123 #define fd 3    /* predefined output descriptor */
124
125 static void PUT(uint64_t off, void *buf, uint32_t size)
126 {
127 //      bb_info_msg("PUT[%llu]:[%u]", off, size);
128         xlseek(fd, off, SEEK_SET);
129         xwrite(fd, buf, size);
130 }
131
132 // 128 and 256-byte inodes:
133 // 128-byte inode is described by struct ext2_inode.
134 // 256-byte one just has these fields appended:
135 //      __u16   i_extra_isize;
136 //      __u16   i_pad1;
137 //      __u32   i_ctime_extra;  /* extra Change time (nsec << 2 | epoch) */
138 //      __u32   i_mtime_extra;  /* extra Modification time (nsec << 2 | epoch) */
139 //      __u32   i_atime_extra;  /* extra Access time (nsec << 2 | epoch) */
140 //      __u32   i_crtime;       /* File creation time */
141 //      __u32   i_crtime_extra; /* extra File creation time (nsec << 2 | epoch)*/
142 //      __u32   i_version_hi;   /* high 32 bits for 64-bit version */
143 // the rest is padding.
144 //
145 // linux/ext2_fs.h has "#define i_size_high i_dir_acl" which suggests that even
146 // 128-byte inode is capable of describing large files (i_dir_acl is meaningful
147 // only for directories, which never need i_size_high).
148 //
149 // Standard mke2fs creates a filesystem with 256-byte inodes if it is
150 // bigger than 0.5GB. So far, we do not do this.
151
152 // Standard mke2fs 1.41.9:
153 // Usage: mke2fs [-c|-l filename] [-b block-size] [-f fragment-size]
154 //      [-i bytes-per-inode] [-I inode-size] [-J journal-options]
155 //      [-G meta group size] [-N number-of-inodes]
156 //      [-m reserved-blocks-percentage] [-o creator-os]
157 //      [-g blocks-per-group] [-L volume-label] [-M last-mounted-directory]
158 //      [-O feature[,...]] [-r fs-revision] [-E extended-option[,...]]
159 //      [-T fs-type] [-U UUID] [-jnqvFSV] device [blocks-count]
160 //
161 // Options not commented below are taken but silently ignored:
162 enum {
163         OPT_c = 1 << 0,
164         OPT_l = 1 << 1,
165         OPT_b = 1 << 2,         // block size, in bytes
166         OPT_f = 1 << 3,
167         OPT_i = 1 << 4,         // bytes per inode
168         OPT_I = 1 << 5,
169         OPT_J = 1 << 6,
170         OPT_G = 1 << 7,
171         OPT_N = 1 << 8,
172         OPT_m = 1 << 9,         // percentage of blocks reserved for superuser
173         OPT_o = 1 << 10,
174         OPT_g = 1 << 11,
175         OPT_L = 1 << 12,        // label
176         OPT_M = 1 << 13,
177         OPT_O = 1 << 14,
178         OPT_r = 1 << 15,
179         OPT_E = 1 << 16,
180         OPT_T = 1 << 17,
181         OPT_U = 1 << 18,
182         OPT_j = 1 << 19,
183         OPT_n = 1 << 20,        // dry run: do not write anything
184         OPT_q = 1 << 21,
185         OPT_v = 1 << 22,
186         OPT_F = 1 << 23,
187         OPT_S = 1 << 24,
188         //OPT_V = 1 << 25,      // -V version. bbox applets don't support that
189 };
190
191 int mkfs_ext2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
192 int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
193 {
194         unsigned i, pos, n;
195         unsigned bs, bpi;
196         unsigned blocksize, blocksize_log2;
197         unsigned reserved_percent = 5;
198         unsigned long long kilobytes;
199         uint32_t nblocks, nblocks_full;
200         uint32_t nreserved;
201         uint32_t ngroups;
202         uint32_t bytes_per_inode;
203         uint32_t first_block;
204         uint32_t inodes_per_group;
205         uint32_t group_desc_blocks;
206         uint32_t inode_table_blocks;
207         uint32_t lost_and_found_blocks;
208         time_t timestamp;
209         unsigned opts;
210         const char *label = "";
211         struct stat st;
212         struct ext2_super_block *sb; // superblock
213         struct ext2_group_desc *gd; // group descriptors
214         struct ext2_inode *inode;
215         struct ext2_dir *dir;
216         uint8_t *buf;
217
218         opt_complementary = "-1:b+:m+:i+";
219         opts = getopt32(argv, "cl:b:f:i:I:J:G:N:m:o:g:L:M:O:r:E:T:U:jnqvFS",
220                 NULL, &bs, NULL, &bpi, NULL, NULL, NULL, NULL,
221                 &reserved_percent, NULL, NULL, &label, NULL, NULL, NULL, NULL, NULL, NULL);
222         argv += optind; // argv[0] -- device
223
224         // check the device is a block device
225         xmove_fd(xopen(argv[0], O_WRONLY), fd);
226         fstat(fd, &st);
227         if (!S_ISBLK(st.st_mode) && !(opts & OPT_F))
228                 bb_error_msg_and_die("not a block device");
229
230         // check if it is mounted
231         // N.B. what if we format a file? find_mount_point will return false negative since
232         // it is loop block device which mounted!
233         if (find_mount_point(argv[0], 0))
234                 bb_error_msg_and_die("can't format mounted filesystem");
235
236         // open the device, get size in kbytes
237         if (argv[1]) {
238                 kilobytes = xatoull(argv[1]);
239                 // seek past end fails on block devices but works on files
240                 if (lseek(fd, kilobytes * 1024 - 1, SEEK_SET) != (off_t)-1) {
241                         xwrite(fd, "", 1); // file grows if needed
242                 }
243                 //else {
244                 //      bb_error_msg("warning, block device is smaller");
245                 //}
246         } else {
247                 kilobytes = (uoff_t)xlseek(fd, 0, SEEK_END) / 1024;
248         }
249
250         bytes_per_inode = 16384;
251         if (kilobytes < 512*1024)
252                 bytes_per_inode = 4096;
253         if (kilobytes < 3*1024)
254                 bytes_per_inode = 8192;
255         if (opts & OPT_i)
256                 bytes_per_inode = bpi;
257
258         // Determine block size
259         // block size is a multiple of 1024
260         blocksize = 1024;
261         if (kilobytes >= 512*1024) // mke2fs 1.41.9 compat
262                 blocksize = 4096;
263         if (EXT2_MAX_BLOCK_SIZE > 4096) {
264                 // kilobytes >> 22 == size in 4gigabyte chunks.
265                 // if size >= 16k gigs, blocksize must be increased.
266                 // Try "mke2fs -F image $((16 * 1024*1024*1024))"
267                 while ((kilobytes >> 22) >= blocksize)
268                         blocksize *= 2;
269         }
270         if (opts & OPT_b)
271                 blocksize = bs;
272         if (blocksize < EXT2_MIN_BLOCK_SIZE
273          || blocksize > EXT2_MAX_BLOCK_SIZE
274          || (blocksize & (blocksize - 1)) // not power of 2
275         ) {
276                 bb_error_msg_and_die("blocksize %u is bad", blocksize);
277         }
278         if ((int32_t)bytes_per_inode < blocksize)
279                 bb_error_msg_and_die("-%c is bad", 'i');
280         // number of bits in one block, i.e. 8*blocksize
281 #define blocks_per_group (8 * blocksize)
282         first_block = (EXT2_MIN_BLOCK_SIZE == blocksize);
283         blocksize_log2 = int_log2(blocksize);
284
285         // Determine number of blocks
286         kilobytes >>= (blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE);
287         nblocks = kilobytes;
288         if (nblocks != kilobytes)
289                 bb_error_msg_and_die("block count doesn't fit in 32 bits");
290 #define kilobytes kilobytes_unused_after_this
291 //compat problem
292 //      if (blocksize < PAGE_SIZE)
293 //              nblocks &= ~((PAGE_SIZE >> blocksize_log2)-1);
294         // Experimentally, standard mke2fs won't work on images smaller than 60k
295         if (nblocks < 60)
296                 bb_error_msg_and_die("need >= 60 blocks");
297
298         // How many reserved blocks?
299         if (reserved_percent > 50)
300                 bb_error_msg_and_die("-%c is bad", 'm');
301         nreserved = (uint64_t)nblocks * reserved_percent / 100;
302
303         // N.B. killing e2fsprogs feature! Unused blocks don't account in calculations
304         nblocks_full = nblocks;
305
306         // If last block group is too small, nblocks may be decreased in order
307         // to discard it, and control returns here to recalculate some
308         // parameters.
309         // Note: blocksize and bytes_per_inode are never recalculated.
310  retry:
311         // N.B. a block group can have no more than blocks_per_group blocks
312         ngroups = div_roundup(nblocks - first_block, blocks_per_group);
313
314         group_desc_blocks = div_roundup(ngroups, blocksize / sizeof(*gd));
315         // TODO: reserved blocks must be marked as such in the bitmaps,
316         // or resulting filesystem is corrupt
317         if (ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT) {
318                 /*
319                  * From e2fsprogs: Calculate the number of GDT blocks to reserve for online
320                  * filesystem growth.
321                  * The absolute maximum number of GDT blocks we can reserve is determined by
322                  * the number of block pointers that can fit into a single block.
323                  * We set it at 1024x the current filesystem size, or
324                  * the upper block count limit (2^32), whichever is lower.
325                  */
326                 uint32_t reserved_group_desc_blocks = 0xFFFFFFFF; // maximum block number
327                 if (nblocks < reserved_group_desc_blocks / 1024)
328                         reserved_group_desc_blocks = nblocks * 1024;
329                 reserved_group_desc_blocks = div_roundup(reserved_group_desc_blocks - first_block, blocks_per_group);
330                 reserved_group_desc_blocks = div_roundup(reserved_group_desc_blocks, blocksize / sizeof(*gd)) - group_desc_blocks;
331                 if (reserved_group_desc_blocks > blocksize / sizeof(uint32_t))
332                         reserved_group_desc_blocks = blocksize / sizeof(uint32_t);
333                 //TODO: STORE_LE(sb->s_reserved_gdt_blocks, reserved_group_desc_blocks);
334                 group_desc_blocks += reserved_group_desc_blocks;
335         }
336
337         {
338                 // N.B. e2fsprogs does as follows!
339                 uint32_t overhead, remainder;
340                 // ninodes is the max number of inodes in this filesystem
341                 uint32_t ninodes = ((uint64_t) nblocks_full * blocksize) / bytes_per_inode;
342                 if (ninodes < EXT2_GOOD_OLD_FIRST_INO+1)
343                         ninodes = EXT2_GOOD_OLD_FIRST_INO+1;
344                 inodes_per_group = div_roundup(ninodes, ngroups);
345                 // minimum number because the first EXT2_GOOD_OLD_FIRST_INO-1 are reserved
346                 if (inodes_per_group < 16)
347                         inodes_per_group = 16;
348                 // a block group can't have more inodes than blocks
349                 if (inodes_per_group > blocks_per_group)
350                         inodes_per_group = blocks_per_group;
351                 // adjust inodes per group so they completely fill the inode table blocks in the descriptor
352 //incompatibility on images >= 0.5GB:
353 //difference in sizeof(*inode) sometimes
354 //results in slightly bigger inodes_per_group here
355 //compared to standard mke2fs:
356                 inodes_per_group = (div_roundup(inodes_per_group * sizeof(*inode), blocksize) * blocksize) / sizeof(*inode);
357                 // make sure the number of inodes per group is a multiple of 8
358                 inodes_per_group &= ~7;
359                 inode_table_blocks = div_roundup(inodes_per_group * sizeof(*inode), blocksize);
360
361                 // to be useful, lost+found should occupy at least 2 blocks (but not exceeding 16*1024 bytes),
362                 // and at most EXT2_NDIR_BLOCKS. So reserve these blocks right now
363                 /* Or e2fsprogs comment verbatim (what does it mean?):
364                  * Ensure that lost+found is at least 2 blocks, so we always
365                  * test large empty blocks for big-block filesystems. */
366                 lost_and_found_blocks = MIN(EXT2_NDIR_BLOCKS, 16 >> (blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE));
367
368                 // the last group needs more attention: isn't it too small for possible overhead?
369                 overhead = (has_super(ngroups - 1) ? (1/*sb*/ + group_desc_blocks) : 0) + 1/*bbmp*/ + 1/*ibmp*/ + inode_table_blocks;
370                 remainder = (nblocks - first_block) % blocks_per_group;
371                 ////can't happen, nblocks >= 60 guarantees this
372                 ////if ((1 == ngroups)
373                 //// && remainder
374                 //// && (remainder < overhead + 1/* "/" */ + lost_and_found_blocks)
375                 ////) {
376                 ////    bb_error_msg_and_die("way small device");
377                 ////}
378
379                 // Standard mke2fs uses 50. Looks like a bug in our calculation
380                 // of "remainder" or "overhead" - we don't match standard mke2fs
381                 // when we transition from one group to two groups
382                 // (a bit after 8M image size), but it works for two->three groups
383                 // transition (at 16M).
384                 if (remainder && (remainder < overhead + 50)) {
385 //bb_info_msg("CHOP[%u]", remainder);
386                         nblocks -= remainder;
387                         goto retry;
388                 }
389         }
390
391         if (nblocks_full - nblocks)
392                 printf("warning: %u blocks unused\n\n", nblocks_full - nblocks);
393         printf(
394                 "Filesystem label=%s\n"
395                 "OS type: Linux\n"
396                 "Block size=%u (log=%u)\n"
397                 "Fragment size=%u (log=%u)\n"
398                 "%u inodes, %u blocks\n"
399                 "%u blocks (%u%%) reserved for the super user\n"
400                 "First data block=%u\n"
401                 "Maximum filesystem blocks=%u\n"
402                 "%u block groups\n"
403                 "%u blocks per group, %u fragments per group\n"
404                 "%u inodes per group"
405                 , label
406                 , blocksize, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE
407                 , blocksize, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE
408                 , inodes_per_group * ngroups, nblocks
409                 , nreserved, reserved_percent
410                 , first_block
411                 , group_desc_blocks * (blocksize / sizeof(*gd)) * blocks_per_group
412                 , ngroups
413                 , blocks_per_group, blocks_per_group
414                 , inodes_per_group
415         );
416         {
417                 const char *fmt = "\nSuperblock backups stored on blocks:\n"
418                         "\t%u";
419                 pos = first_block;
420                 for (i = 1; i < ngroups; i++) {
421                         pos += blocks_per_group;
422                         if (has_super(i)) {
423                                 printf(fmt, (unsigned)pos);
424                                 fmt = ", %u";
425                         }
426                 }
427         }
428         bb_putchar('\n');
429
430         if (opts & OPT_n) {
431                 if (ENABLE_FEATURE_CLEAN_UP)
432                         close(fd);
433                 return EXIT_SUCCESS;
434         }
435
436         // TODO: 3/5 refuse if mounted
437         // TODO: 4/5 compat options
438         // TODO: 1/5 sanity checks
439         // TODO: 0/5 more verbose error messages
440         // TODO: 4/5 bigendianness: recheck, wait for ARM reporters
441         // TODO: 2/5 reserved GDT: how to mark but not allocate?
442         // TODO: 3/5 dir_index?
443
444         // fill the superblock
445         sb = xzalloc(1024);
446         STORE_LE(sb->s_rev_level, 1); // revision 1 filesystem
447         STORE_LE(sb->s_magic, EXT2_SUPER_MAGIC);
448 //incompatibility:
449 //on images > 0.5GB, standard mke2fs uses 256 byte inodes.
450 //we always use 128 byte ones:
451         STORE_LE(sb->s_inode_size, sizeof(*inode));
452         STORE_LE(sb->s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
453         STORE_LE(sb->s_log_block_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE);
454         STORE_LE(sb->s_log_frag_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE);
455         // first 1024 bytes of the device are for boot record. If block size is 1024 bytes, then
456         // the first block is 1, otherwise 0
457         STORE_LE(sb->s_first_data_block, first_block);
458         // block and inode bitmaps occupy no more than one block, so maximum number of blocks is
459         STORE_LE(sb->s_blocks_per_group, blocks_per_group);
460         STORE_LE(sb->s_frags_per_group, blocks_per_group);
461         // blocks
462         STORE_LE(sb->s_blocks_count, nblocks);
463         // reserve blocks for superuser
464         STORE_LE(sb->s_r_blocks_count, nreserved);
465         // ninodes
466         STORE_LE(sb->s_inodes_per_group, inodes_per_group);
467         STORE_LE(sb->s_inodes_count, inodes_per_group * ngroups);
468         STORE_LE(sb->s_free_inodes_count, inodes_per_group * ngroups - EXT2_GOOD_OLD_FIRST_INO);
469         // timestamps
470         timestamp = time(NULL);
471         STORE_LE(sb->s_mkfs_time, timestamp);
472         STORE_LE(sb->s_wtime, timestamp);
473         STORE_LE(sb->s_lastcheck, timestamp);
474         // misc
475         STORE_LE(sb->s_state, 1); // TODO: what's 1?
476         STORE_LE(sb->s_creator_os, EXT2_OS_LINUX);
477         STORE_LE(sb->s_checkinterval, 24*60*60 * 180); // 180 days
478         STORE_LE(sb->s_errors, EXT2_ERRORS_DEFAULT);
479         STORE_LE(sb->s_feature_compat, EXT2_FEATURE_COMPAT_SUPP
480                 | (EXT2_FEATURE_COMPAT_RESIZE_INO * ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT)
481                 | (EXT2_FEATURE_COMPAT_DIR_INDEX * ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX)
482         );
483         // e2fsck from 1.41.9 doesn't like EXT2_FEATURE_INCOMPAT_WHITEOUT
484         STORE_LE(sb->s_feature_incompat, EXT2_FEATURE_INCOMPAT_FILETYPE);// | EXT2_FEATURE_INCOMPAT_WHITEOUT;
485         STORE_LE(sb->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER);
486         STORE_LE(sb->s_flags, EXT2_FLAGS_SIGNED_HASH * ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX);
487         generate_uuid(sb->s_uuid);
488         if (ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX) {
489                 STORE_LE(sb->s_def_hash_version, EXT2_HASH_HALF_MD4);
490                 generate_uuid((uint8_t *)sb->s_hash_seed);
491         }
492         /*
493          * From e2fsprogs: add "jitter" to the superblock's check interval so that we
494          * don't check all the filesystems at the same time.  We use a
495          * kludgy hack of using the UUID to derive a random jitter value.
496          */
497         STORE_LE(sb->s_max_mnt_count,
498                 EXT2_DFL_MAX_MNT_COUNT
499                 + (sb->s_uuid[ARRAY_SIZE(sb->s_uuid)-1] % EXT2_DFL_MAX_MNT_COUNT));
500
501         // write the label
502         safe_strncpy((char *)sb->s_volume_name, label, sizeof(sb->s_volume_name));
503
504         // calculate filesystem skeleton structures
505         gd = xzalloc(group_desc_blocks * blocksize);
506         buf = xmalloc(blocksize);
507         sb->s_free_blocks_count = 0;
508         for (i = 0, pos = first_block, n = nblocks - first_block;
509                 i < ngroups;
510                 i++, pos += blocks_per_group, n -= blocks_per_group
511         ) {
512                 uint32_t overhead = pos + (has_super(i) ? (1/*sb*/ + group_desc_blocks) : 0);
513                 uint32_t free_blocks;
514                 // fill group descriptors
515                 STORE_LE(gd[i].bg_block_bitmap, overhead + 0);
516                 STORE_LE(gd[i].bg_inode_bitmap, overhead + 1);
517                 STORE_LE(gd[i].bg_inode_table, overhead + 2);
518                 overhead = overhead - pos + 1/*bbmp*/ + 1/*ibmp*/ + inode_table_blocks;
519                 gd[i].bg_free_inodes_count = inodes_per_group;
520                 //STORE_LE(gd[i].bg_used_dirs_count, 0);
521                 // N.B. both "/" and "/lost+found" are within the first block group
522                 // "/" occupies 1 block, "/lost+found" occupies lost_and_found_blocks...
523                 if (0 == i) {
524                         // ... thus increased overhead for the first block group ...
525                         overhead += 1 + lost_and_found_blocks;
526                         // ... and 2 used directories
527                         STORE_LE(gd[i].bg_used_dirs_count, 2);
528                         // well known reserved inodes belong to the first block too
529                         gd[i].bg_free_inodes_count -= EXT2_GOOD_OLD_FIRST_INO;
530                 }
531
532                 // cache free block count of the group
533                 free_blocks = (n < blocks_per_group ? n : blocks_per_group) - overhead;
534
535                 // mark preallocated blocks as allocated
536 //bb_info_msg("ALLOC: [%u][%u][%u]", blocksize, overhead, blocks_per_group - (free_blocks + overhead));
537                 allocate(buf, blocksize,
538                         // reserve "overhead" blocks
539                         overhead,
540                         // mark unused trailing blocks
541                         blocks_per_group - (free_blocks + overhead)
542                 );
543                 // dump block bitmap
544                 PUT((uint64_t)(FETCH_LE32(gd[i].bg_block_bitmap)) * blocksize, buf, blocksize);
545                 STORE_LE(gd[i].bg_free_blocks_count, free_blocks);
546
547                 // mark preallocated inodes as allocated
548                 allocate(buf, blocksize,
549                         // mark reserved inodes
550                         inodes_per_group - gd[i].bg_free_inodes_count,
551                         // mark unused trailing inodes
552                         blocks_per_group - inodes_per_group
553                 );
554                 // dump inode bitmap
555                 //PUT((uint64_t)(FETCH_LE32(gd[i].bg_block_bitmap)) * blocksize, buf, blocksize);
556                 //but it's right after block bitmap, so we can just:
557                 xwrite(fd, buf, blocksize);
558                 STORE_LE(gd[i].bg_free_inodes_count, gd[i].bg_free_inodes_count);
559
560                 // count overall free blocks
561                 sb->s_free_blocks_count += free_blocks;
562         }
563         STORE_LE(sb->s_free_blocks_count, sb->s_free_blocks_count);
564
565         // dump filesystem skeleton structures
566 //      printf("Writing superblocks and filesystem accounting information: ");
567         for (i = 0, pos = first_block; i < ngroups; i++, pos += blocks_per_group) {
568                 // dump superblock and group descriptors and their backups
569                 if (has_super(i)) {
570                         // N.B. 1024 byte blocks are special
571                         PUT(((uint64_t)pos * blocksize) + ((0 == i && 1024 != blocksize) ? 1024 : 0),
572                                         sb, 1024);
573                         PUT(((uint64_t)pos * blocksize) + blocksize,
574                                         gd, group_desc_blocks * blocksize);
575                 }
576         }
577
578         // zero boot sectors
579         memset(buf, 0, blocksize);
580         PUT(0, buf, 1024); // N.B. 1024 <= blocksize, so buf[0..1023] contains zeros
581         // zero inode tables
582         for (i = 0; i < ngroups; ++i)
583                 for (n = 0; n < inode_table_blocks; ++n)
584                         PUT((uint64_t)(FETCH_LE32(gd[i].bg_inode_table) + n) * blocksize,
585                                 buf, blocksize);
586
587         // prepare directory inode
588         inode = (struct ext2_inode *)buf;
589         STORE_LE(inode->i_mode, S_IFDIR | S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH);
590         STORE_LE(inode->i_mtime, timestamp);
591         STORE_LE(inode->i_atime, timestamp);
592         STORE_LE(inode->i_ctime, timestamp);
593         STORE_LE(inode->i_size, blocksize);
594         // inode->i_blocks stores the number of 512 byte data blocks
595         // (512, because it goes directly to struct stat without scaling)
596         STORE_LE(inode->i_blocks, blocksize / 512);
597
598         // dump root dir inode
599         STORE_LE(inode->i_links_count, 3); // "/.", "/..", "/lost+found/.." point to this inode
600         STORE_LE(inode->i_block[0], FETCH_LE32(gd[0].bg_inode_table) + inode_table_blocks);
601         PUT(((uint64_t)FETCH_LE32(gd[0].bg_inode_table) * blocksize) + (EXT2_ROOT_INO-1) * sizeof(*inode),
602                                 buf, sizeof(*inode));
603
604         // dump lost+found dir inode
605         STORE_LE(inode->i_links_count, 2); // both "/lost+found" and "/lost+found/." point to this inode
606         STORE_LE(inode->i_size, lost_and_found_blocks * blocksize);
607         STORE_LE(inode->i_blocks, (lost_and_found_blocks * blocksize) / 512);
608         n = FETCH_LE32(inode->i_block[0]) + 1;
609         for (i = 0; i < lost_and_found_blocks; ++i)
610                 STORE_LE(inode->i_block[i], i + n); // use next block
611 //bb_info_msg("LAST BLOCK USED[%u]", i + n);
612         PUT(((uint64_t)FETCH_LE32(gd[0].bg_inode_table) * blocksize) + (EXT2_GOOD_OLD_FIRST_INO-1) * sizeof(*inode),
613                                 buf, sizeof(*inode));
614
615         // dump directories
616         memset(buf, 0, blocksize);
617         dir = (struct ext2_dir *)buf;
618
619         // dump 2nd+ blocks of "/lost+found"
620         STORE_LE(dir->rec_len1, blocksize); // e2fsck 1.41.4 compat (1.41.9 does not need this)
621         for (i = 1; i < lost_and_found_blocks; ++i)
622                 PUT((uint64_t)(FETCH_LE32(gd[0].bg_inode_table) + inode_table_blocks + 1+i) * blocksize,
623                                 buf, blocksize);
624
625         // dump 1st block of "/lost+found"
626         STORE_LE(dir->inode1, EXT2_GOOD_OLD_FIRST_INO);
627         STORE_LE(dir->rec_len1, 12);
628         STORE_LE(dir->name_len1, 1);
629         STORE_LE(dir->file_type1, EXT2_FT_DIR);
630         dir->name1[0] = '.';
631         STORE_LE(dir->inode2, EXT2_ROOT_INO);
632         STORE_LE(dir->rec_len2, blocksize - 12);
633         STORE_LE(dir->name_len2, 2);
634         STORE_LE(dir->file_type2, EXT2_FT_DIR);
635         dir->name2[0] = '.'; dir->name2[1] = '.';
636         PUT((uint64_t)(FETCH_LE32(gd[0].bg_inode_table) + inode_table_blocks + 1) * blocksize, buf, blocksize);
637
638         // dump root dir block
639         STORE_LE(dir->inode1, EXT2_ROOT_INO);
640         STORE_LE(dir->rec_len2, 12);
641         STORE_LE(dir->inode3, EXT2_GOOD_OLD_FIRST_INO);
642         STORE_LE(dir->rec_len3, blocksize - 12 - 12);
643         STORE_LE(dir->name_len3, 10);
644         STORE_LE(dir->file_type3, EXT2_FT_DIR);
645         strcpy(dir->name3, "lost+found");
646         PUT((uint64_t)(FETCH_LE32(gd[0].bg_inode_table) + inode_table_blocks + 0) * blocksize, buf, blocksize);
647
648         // cleanup
649         if (ENABLE_FEATURE_CLEAN_UP) {
650                 free(buf);
651                 free(gd);
652                 free(sb);
653         }
654
655         xclose(fd);
656         return EXIT_SUCCESS;
657 }