3
0

mke2fs.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464
  1. /*
  2. * mke2fs.c - Make a ext2fs filesystem.
  3. *
  4. * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
  5. * 2003, 2004, 2005 by Theodore Ts'o.
  6. *
  7. * %Begin-Header%
  8. * This file may be redistributed under the terms of the GNU Public
  9. * License.
  10. * %End-Header%
  11. */
  12. /* Usage: mke2fs [options] device
  13. *
  14. * The device may be a block device or a image of one, but this isn't
  15. * enforced (but it's not much fun on a character device :-).
  16. */
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <fcntl.h>
  20. #include <ctype.h>
  21. #include <time.h>
  22. #include <getopt.h>
  23. #include <unistd.h>
  24. #include <stdlib.h>
  25. #include <errno.h>
  26. #include <mntent.h>
  27. #include <sys/ioctl.h>
  28. #include <sys/types.h>
  29. #include "e2fsbb.h"
  30. #include "ext2fs/ext2_fs.h"
  31. #include "uuid/uuid.h"
  32. #include "e2p/e2p.h"
  33. #include "ext2fs/ext2fs.h"
  34. #include "util.h"
  35. #define STRIDE_LENGTH 8
  36. #ifndef __sparc__
  37. #define ZAP_BOOTBLOCK
  38. #endif
  39. static const char * device_name /* = NULL */;
  40. /* Command line options */
  41. static int cflag;
  42. static int quiet;
  43. static int super_only;
  44. static int force;
  45. static int noaction;
  46. static int journal_size;
  47. static int journal_flags;
  48. static char *bad_blocks_filename;
  49. static __u32 fs_stride;
  50. static struct ext2_super_block param;
  51. static char *creator_os;
  52. static char *volume_label;
  53. static char *mount_dir;
  54. static char *journal_device;
  55. static int sync_kludge; /* Set using the MKE2FS_SYNC env. option */
  56. static int sys_page_size = 4096;
  57. static int linux_version_code = 0;
  58. static int int_log2(int arg)
  59. {
  60. int l = 0;
  61. arg >>= 1;
  62. while (arg) {
  63. l++;
  64. arg >>= 1;
  65. }
  66. return l;
  67. }
  68. static int int_log10(unsigned int arg)
  69. {
  70. int l;
  71. for (l=0; arg ; l++)
  72. arg = arg / 10;
  73. return l;
  74. }
  75. static int parse_version_number(const char *s)
  76. {
  77. int major, minor, rev;
  78. char *endptr;
  79. const char *cp = s;
  80. if (!s)
  81. return 0;
  82. major = strtol(cp, &endptr, 10);
  83. if (cp == endptr || *endptr != '.')
  84. return 0;
  85. cp = endptr + 1;
  86. minor = strtol(cp, &endptr, 10);
  87. if (cp == endptr || *endptr != '.')
  88. return 0;
  89. cp = endptr + 1;
  90. rev = strtol(cp, &endptr, 10);
  91. if (cp == endptr)
  92. return 0;
  93. return ((((major * 256) + minor) * 256) + rev);
  94. }
  95. /*
  96. * This function sets the default parameters for a filesystem
  97. *
  98. * The type is specified by the user. The size is the maximum size
  99. * (in megabytes) for which a set of parameters applies, with a size
  100. * of zero meaning that it is the default parameter for the type.
  101. * Note that order is important in the table below.
  102. */
  103. #define DEF_MAX_BLOCKSIZE -1
  104. static char default_str[] = "default";
  105. struct mke2fs_defaults {
  106. const char *type;
  107. int size;
  108. int blocksize;
  109. int inode_ratio;
  110. } settings[] = {
  111. { default_str, 0, 4096, 8192 },
  112. { default_str, 512, 1024, 4096 },
  113. { default_str, 3, 1024, 8192 },
  114. { "journal", 0, 4096, 8192 },
  115. { "news", 0, 4096, 4096 },
  116. { "largefile", 0, 4096, 1024 * 1024 },
  117. { "largefile4", 0, 4096, 4096 * 1024 },
  118. { 0, 0, 0, 0},
  119. };
  120. static void set_fs_defaults(const char *fs_type,
  121. struct ext2_super_block *super,
  122. int blocksize, int sector_size,
  123. int *inode_ratio)
  124. {
  125. int megs;
  126. int ratio = 0;
  127. struct mke2fs_defaults *p;
  128. int use_bsize = 1024;
  129. megs = super->s_blocks_count * (EXT2_BLOCK_SIZE(super) / 1024) / 1024;
  130. if (inode_ratio)
  131. ratio = *inode_ratio;
  132. if (!fs_type)
  133. fs_type = default_str;
  134. for (p = settings; p->type; p++) {
  135. if ((strcmp(p->type, fs_type) != 0) &&
  136. (strcmp(p->type, default_str) != 0))
  137. continue;
  138. if ((p->size != 0) && (megs > p->size))
  139. continue;
  140. if (ratio == 0)
  141. *inode_ratio = p->inode_ratio < blocksize ?
  142. blocksize : p->inode_ratio;
  143. use_bsize = p->blocksize;
  144. }
  145. if (blocksize <= 0) {
  146. if (use_bsize == DEF_MAX_BLOCKSIZE) {
  147. use_bsize = sys_page_size;
  148. if ((linux_version_code < (2*65536 + 6*256)) &&
  149. (use_bsize > 4096))
  150. use_bsize = 4096;
  151. }
  152. if (sector_size && use_bsize < sector_size)
  153. use_bsize = sector_size;
  154. if ((blocksize < 0) && (use_bsize < (-blocksize)))
  155. use_bsize = -blocksize;
  156. blocksize = use_bsize;
  157. super->s_blocks_count /= blocksize / 1024;
  158. }
  159. super->s_log_frag_size = super->s_log_block_size =
  160. int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
  161. }
  162. /*
  163. * Helper function for read_bb_file and test_disk
  164. */
  165. static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk)
  166. {
  167. bb_error_msg("Bad block %u out of range; ignored", blk);
  168. return;
  169. }
  170. /*
  171. * Reads the bad blocks list from a file
  172. */
  173. static void read_bb_file(ext2_filsys fs, badblocks_list *bb_list,
  174. const char *bad_blocks_file)
  175. {
  176. FILE *f;
  177. errcode_t retval;
  178. f = fopen(bad_blocks_file, "r");
  179. if (!f) {
  180. bb_perror_msg_and_die("Could not read bad blocks file %s", bad_blocks_file);
  181. }
  182. retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
  183. fclose (f);
  184. if (retval) {
  185. bb_error_msg_and_die("Could not read bad blocks list");
  186. }
  187. }
  188. /*
  189. * Runs the badblocks program to test the disk
  190. */
  191. static void test_disk(ext2_filsys fs, badblocks_list *bb_list)
  192. {
  193. FILE *f;
  194. errcode_t retval;
  195. char buf[1024];
  196. sprintf(buf, "badblocks -b %d %s%s%s %d", fs->blocksize,
  197. quiet ? "" : "-s ", (cflag > 1) ? "-w " : "",
  198. fs->device_name, fs->super->s_blocks_count);
  199. if (!quiet)
  200. printf(_("Running command: %s\n"), buf);
  201. f = popen(buf, "r");
  202. if (!f) {
  203. bb_perror_msg_and_die("Could not run '%s'", buf);
  204. }
  205. retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
  206. pclose(f);
  207. if (retval) {
  208. bb_error_msg_and_die(
  209. "Could not get list of bad blocks from program");
  210. }
  211. }
  212. static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list)
  213. {
  214. dgrp_t i;
  215. blk_t j;
  216. unsigned must_be_good;
  217. blk_t blk;
  218. badblocks_iterate bb_iter;
  219. errcode_t retval;
  220. blk_t group_block;
  221. int group;
  222. int group_bad;
  223. if (!bb_list)
  224. return;
  225. /*
  226. * The primary superblock and group descriptors *must* be
  227. * good; if not, abort.
  228. */
  229. must_be_good = fs->super->s_first_data_block + 1 + fs->desc_blocks;
  230. for (i = fs->super->s_first_data_block; i <= must_be_good; i++) {
  231. if (ext2fs_badblocks_list_test(bb_list, i)) {
  232. bb_error_msg_and_die(
  233. "Block %d in primary superblock/group descriptor area bad\n"
  234. "Blocks %d through %d must be good in order to build a filesystem\n"
  235. "Aborting ...", i, fs->super->s_first_data_block, must_be_good);
  236. }
  237. }
  238. /*
  239. * See if any of the bad blocks are showing up in the backup
  240. * superblocks and/or group descriptors. If so, issue a
  241. * warning and adjust the block counts appropriately.
  242. */
  243. group_block = fs->super->s_first_data_block +
  244. fs->super->s_blocks_per_group;
  245. for (i = 1; i < fs->group_desc_count; i++) {
  246. group_bad = 0;
  247. for (j=0; j < fs->desc_blocks+1; j++) {
  248. if (ext2fs_badblocks_list_test(bb_list,
  249. group_block + j)) {
  250. if (!group_bad)
  251. bb_error_msg(
  252. "Warning: the backup superblock/group descriptors at block %d contain\n"
  253. " bad blocks\n", group_block);
  254. group_bad++;
  255. group = ext2fs_group_of_blk(fs, group_block+j);
  256. fs->group_desc[group].bg_free_blocks_count++;
  257. fs->super->s_free_blocks_count++;
  258. }
  259. }
  260. group_block += fs->super->s_blocks_per_group;
  261. }
  262. /*
  263. * Mark all the bad blocks as used...
  264. */
  265. retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
  266. if (retval) {
  267. bb_error_msg_and_die("while marking bad blocks as used");
  268. }
  269. while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
  270. ext2fs_mark_block_bitmap(fs->block_map, blk);
  271. ext2fs_badblocks_list_iterate_end(bb_iter);
  272. }
  273. /*
  274. * These functions implement a generalized progress meter.
  275. */
  276. struct progress_struct {
  277. char format[20];
  278. char backup[80];
  279. __u32 max;
  280. int skip_progress;
  281. };
  282. static void progress_init(struct progress_struct *progress,
  283. const char *label,__u32 max)
  284. {
  285. int i;
  286. memset(progress, 0, sizeof(struct progress_struct));
  287. if (quiet)
  288. return;
  289. /*
  290. * Figure out how many digits we need
  291. */
  292. i = int_log10(max);
  293. sprintf(progress->format, "%%%dd/%%%dld", i, i);
  294. memset(progress->backup, '\b', sizeof(progress->backup)-1);
  295. progress->backup[sizeof(progress->backup)-1] = 0;
  296. if ((2*i)+1 < (int) sizeof(progress->backup))
  297. progress->backup[(2*i)+1] = 0;
  298. progress->max = max;
  299. progress->skip_progress = 0;
  300. if (getenv("MKE2FS_SKIP_PROGRESS"))
  301. progress->skip_progress++;
  302. fputs(label, stdout);
  303. fflush(stdout);
  304. }
  305. static void progress_update(struct progress_struct *progress, __u32 val)
  306. {
  307. if ((progress->format[0] == 0) || progress->skip_progress)
  308. return;
  309. printf(progress->format, val, progress->max);
  310. fputs(progress->backup, stdout);
  311. }
  312. static void progress_close(struct progress_struct *progress)
  313. {
  314. if (progress->format[0] == 0)
  315. return;
  316. fputs(_("done \n"), stdout);
  317. }
  318. /*
  319. * Helper function which zeros out _num_ blocks starting at _blk_. In
  320. * case of an error, the details of the error is returned via _ret_blk_
  321. * and _ret_count_ if they are non-NULL pointers. Returns 0 on
  322. * success, and an error code on an error.
  323. *
  324. * As a special case, if the first argument is NULL, then it will
  325. * attempt to free the static zeroizing buffer. (This is to keep
  326. * programs that check for memory leaks happy.)
  327. */
  328. static errcode_t zero_blocks(ext2_filsys fs, blk_t blk, int num,
  329. struct progress_struct *progress,
  330. blk_t *ret_blk, int *ret_count)
  331. {
  332. int j, count, next_update, next_update_incr;
  333. static char *buf;
  334. errcode_t retval;
  335. /* If fs is null, clean up the static buffer and return */
  336. if (!fs) {
  337. if (buf) {
  338. free(buf);
  339. buf = 0;
  340. }
  341. return 0;
  342. }
  343. /* Allocate the zeroizing buffer if necessary */
  344. if (!buf) {
  345. buf = xmalloc(fs->blocksize * STRIDE_LENGTH);
  346. memset(buf, 0, fs->blocksize * STRIDE_LENGTH);
  347. }
  348. /* OK, do the write loop */
  349. next_update = 0;
  350. next_update_incr = num / 100;
  351. if (next_update_incr < 1)
  352. next_update_incr = 1;
  353. for (j=0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
  354. count = num - j;
  355. if (count > STRIDE_LENGTH)
  356. count = STRIDE_LENGTH;
  357. retval = io_channel_write_blk(fs->io, blk, count, buf);
  358. if (retval) {
  359. if (ret_count)
  360. *ret_count = count;
  361. if (ret_blk)
  362. *ret_blk = blk;
  363. return retval;
  364. }
  365. if (progress && j > next_update) {
  366. next_update += num / 100;
  367. progress_update(progress, blk);
  368. }
  369. }
  370. return 0;
  371. }
  372. static void write_inode_tables(ext2_filsys fs)
  373. {
  374. errcode_t retval;
  375. blk_t blk;
  376. dgrp_t i;
  377. int num;
  378. struct progress_struct progress;
  379. if (quiet)
  380. memset(&progress, 0, sizeof(progress));
  381. else
  382. progress_init(&progress, _("Writing inode tables: "),
  383. fs->group_desc_count);
  384. for (i = 0; i < fs->group_desc_count; i++) {
  385. progress_update(&progress, i);
  386. blk = fs->group_desc[i].bg_inode_table;
  387. num = fs->inode_blocks_per_group;
  388. retval = zero_blocks(fs, blk, num, 0, &blk, &num);
  389. if (retval) {
  390. bb_error_msg_and_die(
  391. "\nCould not write %d blocks "
  392. "in inode table starting at %d.",
  393. num, blk);
  394. }
  395. if (sync_kludge) {
  396. if (sync_kludge == 1)
  397. sync();
  398. else if ((i % sync_kludge) == 0)
  399. sync();
  400. }
  401. }
  402. zero_blocks(0, 0, 0, 0, 0, 0);
  403. progress_close(&progress);
  404. }
  405. static void create_root_dir(ext2_filsys fs)
  406. {
  407. errcode_t retval;
  408. struct ext2_inode inode;
  409. retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0);
  410. if (retval) {
  411. bb_error_msg_and_die("Could not create root dir");
  412. }
  413. if (geteuid()) {
  414. retval = ext2fs_read_inode(fs, EXT2_ROOT_INO, &inode);
  415. if (retval) {
  416. bb_error_msg_and_die("Could not read root inode");
  417. }
  418. inode.i_uid = getuid();
  419. if (inode.i_uid)
  420. inode.i_gid = getgid();
  421. retval = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
  422. if (retval) {
  423. bb_error_msg_and_die("Could not set root inode ownership");
  424. }
  425. }
  426. }
  427. static void create_lost_and_found(ext2_filsys fs)
  428. {
  429. errcode_t retval;
  430. ext2_ino_t ino;
  431. const char *name = "lost+found";
  432. int i;
  433. int lpf_size = 0;
  434. fs->umask = 077;
  435. retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, 0, name);
  436. if (retval) {
  437. bb_error_msg_and_die("Could not create lost+found");
  438. }
  439. retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, strlen(name), 0, &ino);
  440. if (retval) {
  441. bb_error_msg_and_die("Could not look up lost+found");
  442. }
  443. for (i=1; i < EXT2_NDIR_BLOCKS; i++) {
  444. if ((lpf_size += fs->blocksize) >= 16*1024)
  445. break;
  446. retval = ext2fs_expand_dir(fs, ino);
  447. if (retval) {
  448. bb_error_msg_and_die("Could not expand lost+found");
  449. }
  450. }
  451. }
  452. static void create_bad_block_inode(ext2_filsys fs, badblocks_list bb_list)
  453. {
  454. errcode_t retval;
  455. ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_BAD_INO);
  456. fs->group_desc[0].bg_free_inodes_count--;
  457. fs->super->s_free_inodes_count--;
  458. retval = ext2fs_update_bb_inode(fs, bb_list);
  459. if (retval) {
  460. bb_error_msg_and_die("Could not set bad block inode");
  461. }
  462. }
  463. static void reserve_inodes(ext2_filsys fs)
  464. {
  465. ext2_ino_t i;
  466. int group;
  467. for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->super); i++) {
  468. ext2fs_mark_inode_bitmap(fs->inode_map, i);
  469. group = ext2fs_group_of_ino(fs, i);
  470. fs->group_desc[group].bg_free_inodes_count--;
  471. fs->super->s_free_inodes_count--;
  472. }
  473. ext2fs_mark_ib_dirty(fs);
  474. }
  475. #define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */
  476. #define BSD_MAGICDISK (0x57455682UL) /* The disk magic number reversed */
  477. #define BSD_LABEL_OFFSET 64
  478. static void zap_sector(ext2_filsys fs, int sect, int nsect)
  479. {
  480. char *buf;
  481. int retval;
  482. unsigned int *magic;
  483. buf = xmalloc(512*nsect);
  484. if (sect == 0) {
  485. /* Check for a BSD disklabel, and don't erase it if so */
  486. retval = io_channel_read_blk(fs->io, 0, -512, buf);
  487. if (retval)
  488. bb_error_msg("Warning: could not read block 0");
  489. else {
  490. magic = (unsigned int *) (buf + BSD_LABEL_OFFSET);
  491. if ((*magic == BSD_DISKMAGIC) ||
  492. (*magic == BSD_MAGICDISK))
  493. return;
  494. }
  495. }
  496. memset(buf, 0, 512*nsect);
  497. io_channel_set_blksize(fs->io, 512);
  498. retval = io_channel_write_blk(fs->io, sect, -512*nsect, buf);
  499. io_channel_set_blksize(fs->io, fs->blocksize);
  500. free(buf);
  501. if (retval)
  502. bb_error_msg("Warning: could not erase sector %d", sect);
  503. }
  504. static void create_journal_dev(ext2_filsys fs)
  505. {
  506. struct progress_struct progress;
  507. errcode_t retval;
  508. char *buf;
  509. blk_t blk;
  510. int count;
  511. retval = ext2fs_create_journal_superblock(fs,
  512. fs->super->s_blocks_count, 0, &buf);
  513. if (retval) {
  514. bb_error_msg_and_die("Could not init journal superblock");
  515. }
  516. if (quiet)
  517. memset(&progress, 0, sizeof(progress));
  518. else
  519. progress_init(&progress, _("Zeroing journal device: "),
  520. fs->super->s_blocks_count);
  521. retval = zero_blocks(fs, 0, fs->super->s_blocks_count,
  522. &progress, &blk, &count);
  523. if (retval) {
  524. bb_error_msg_and_die("Could not zero journal device (block %u, count %d)",
  525. blk, count);
  526. }
  527. zero_blocks(0, 0, 0, 0, 0, 0);
  528. retval = io_channel_write_blk(fs->io,
  529. fs->super->s_first_data_block+1,
  530. 1, buf);
  531. if (retval) {
  532. bb_error_msg_and_die("Could not write journal superblock");
  533. }
  534. progress_close(&progress);
  535. }
  536. static void show_stats(ext2_filsys fs)
  537. {
  538. struct ext2_super_block *s = fs->super;
  539. char buf[80];
  540. char *os;
  541. blk_t group_block;
  542. dgrp_t i;
  543. int need, col_left;
  544. if (param.s_blocks_count != s->s_blocks_count)
  545. bb_error_msg("warning: %d blocks unused\n",
  546. param.s_blocks_count - s->s_blocks_count);
  547. memset(buf, 0, sizeof(buf));
  548. strncpy(buf, s->s_volume_name, sizeof(s->s_volume_name));
  549. printf("Filesystem label=%s\n", buf);
  550. fputs(_("OS type: "), stdout);
  551. os = e2p_os2string(fs->super->s_creator_os);
  552. fputs(os, stdout);
  553. free(os);
  554. printf("\n");
  555. printf(_("Block size=%u (log=%u)\n"), fs->blocksize,
  556. s->s_log_block_size);
  557. printf(_("Fragment size=%u (log=%u)\n"), fs->fragsize,
  558. s->s_log_frag_size);
  559. printf(_("%u inodes, %u blocks\n"), s->s_inodes_count,
  560. s->s_blocks_count);
  561. printf(_("%u blocks (%2.2f%%) reserved for the super user\n"),
  562. s->s_r_blocks_count,
  563. 100.0 * s->s_r_blocks_count / s->s_blocks_count);
  564. printf(_("First data block=%u\n"), s->s_first_data_block);
  565. if (s->s_reserved_gdt_blocks)
  566. printf(_("Maximum filesystem blocks=%lu\n"),
  567. (s->s_reserved_gdt_blocks + fs->desc_blocks) *
  568. (fs->blocksize / sizeof(struct ext2_group_desc)) *
  569. s->s_blocks_per_group);
  570. if (fs->group_desc_count > 1)
  571. printf(_("%u block groups\n"), fs->group_desc_count);
  572. else
  573. printf(_("%u block group\n"), fs->group_desc_count);
  574. printf(_("%u blocks per group, %u fragments per group\n"),
  575. s->s_blocks_per_group, s->s_frags_per_group);
  576. printf(_("%u inodes per group\n"), s->s_inodes_per_group);
  577. if (fs->group_desc_count == 1) {
  578. printf("\n");
  579. return;
  580. }
  581. printf(_("Superblock backups stored on blocks: "));
  582. group_block = s->s_first_data_block;
  583. col_left = 0;
  584. for (i = 1; i < fs->group_desc_count; i++) {
  585. group_block += s->s_blocks_per_group;
  586. if (!ext2fs_bg_has_super(fs, i))
  587. continue;
  588. if (i != 1)
  589. printf(", ");
  590. need = int_log10(group_block) + 2;
  591. if (need > col_left) {
  592. printf("\n\t");
  593. col_left = 72;
  594. }
  595. col_left -= need;
  596. printf("%u", group_block);
  597. }
  598. printf("\n\n");
  599. }
  600. /*
  601. * Set the S_CREATOR_OS field. Return true if OS is known,
  602. * otherwise, 0.
  603. */
  604. static int set_os(struct ext2_super_block *sb, char *os)
  605. {
  606. if (isdigit (*os))
  607. sb->s_creator_os = atoi (os);
  608. else if (strcasecmp(os, "linux") == 0)
  609. sb->s_creator_os = EXT2_OS_LINUX;
  610. else if (strcasecmp(os, "GNU") == 0 || strcasecmp(os, "hurd") == 0)
  611. sb->s_creator_os = EXT2_OS_HURD;
  612. else if (strcasecmp(os, "masix") == 0)
  613. sb->s_creator_os = EXT2_OS_MASIX;
  614. else if (strcasecmp(os, "freebsd") == 0)
  615. sb->s_creator_os = EXT2_OS_FREEBSD;
  616. else if (strcasecmp(os, "lites") == 0)
  617. sb->s_creator_os = EXT2_OS_LITES;
  618. else
  619. return 0;
  620. return 1;
  621. }
  622. #define PATH_SET "PATH=/sbin"
  623. static void parse_extended_opts(struct ext2_super_block *sb_param,
  624. const char *opts)
  625. {
  626. char *buf, *token, *next, *p, *arg;
  627. int len;
  628. int r_usage = 0;
  629. len = strlen(opts);
  630. buf = xmalloc(len+1);
  631. strcpy(buf, opts);
  632. for (token = buf; token && *token; token = next) {
  633. p = strchr(token, ',');
  634. next = 0;
  635. if (p) {
  636. *p = 0;
  637. next = p+1;
  638. }
  639. arg = strchr(token, '=');
  640. if (arg) {
  641. *arg = 0;
  642. arg++;
  643. }
  644. if (strcmp(token, "stride") == 0) {
  645. if (!arg) {
  646. r_usage++;
  647. continue;
  648. }
  649. fs_stride = strtoul(arg, &p, 0);
  650. if (*p || (fs_stride == 0)) {
  651. bb_error_msg("Invalid stride parameter");
  652. r_usage++;
  653. continue;
  654. }
  655. } else if (!strcmp(token, "resize")) {
  656. unsigned long resize, bpg, rsv_groups;
  657. unsigned long group_desc_count, desc_blocks;
  658. unsigned int gdpb, blocksize;
  659. int rsv_gdb;
  660. if (!arg) {
  661. r_usage++;
  662. continue;
  663. }
  664. resize = parse_num_blocks(arg,
  665. sb_param->s_log_block_size);
  666. if (resize == 0) {
  667. bb_error_msg("Invalid resize parameter: %s", arg);
  668. r_usage++;
  669. continue;
  670. }
  671. if (resize <= sb_param->s_blocks_count) {
  672. bb_error_msg("The resize maximum must be greater than the filesystem size");
  673. r_usage++;
  674. continue;
  675. }
  676. blocksize = EXT2_BLOCK_SIZE(sb_param);
  677. bpg = sb_param->s_blocks_per_group;
  678. if (!bpg)
  679. bpg = blocksize * 8;
  680. gdpb = blocksize / sizeof(struct ext2_group_desc);
  681. group_desc_count = (sb_param->s_blocks_count +
  682. bpg - 1) / bpg;
  683. desc_blocks = (group_desc_count +
  684. gdpb - 1) / gdpb;
  685. rsv_groups = (resize + bpg - 1) / bpg;
  686. rsv_gdb = (rsv_groups + gdpb - 1) / gdpb -
  687. desc_blocks;
  688. if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb_param))
  689. rsv_gdb = EXT2_ADDR_PER_BLOCK(sb_param);
  690. if (rsv_gdb > 0) {
  691. sb_param->s_feature_compat |=
  692. EXT2_FEATURE_COMPAT_RESIZE_INODE;
  693. sb_param->s_reserved_gdt_blocks = rsv_gdb;
  694. }
  695. } else
  696. r_usage++;
  697. }
  698. if (r_usage) {
  699. bb_error_msg_and_die(
  700. "\nBad options specified.\n\n"
  701. "Options are separated by commas, "
  702. "and may take an argument which\n"
  703. "\tis set off by an equals ('=') sign.\n\n"
  704. "Valid raid options are:\n"
  705. "\tstride=<stride length in blocks>\n"
  706. "\tresize=<resize maximum size in blocks>\n");
  707. }
  708. }
  709. static __u32 ok_features[3] = {
  710. EXT3_FEATURE_COMPAT_HAS_JOURNAL |
  711. EXT2_FEATURE_COMPAT_RESIZE_INODE |
  712. EXT2_FEATURE_COMPAT_DIR_INDEX, /* Compat */
  713. EXT2_FEATURE_INCOMPAT_FILETYPE| /* Incompat */
  714. EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|
  715. EXT2_FEATURE_INCOMPAT_META_BG,
  716. EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */
  717. };
  718. static void PRS(int argc, char *argv[])
  719. {
  720. int b, c;
  721. int size;
  722. char * tmp;
  723. int blocksize = 0;
  724. int inode_ratio = 0;
  725. int inode_size = 0;
  726. int reserved_ratio = 5;
  727. int sector_size = 0;
  728. int show_version_only = 0;
  729. ext2_ino_t num_inodes = 0;
  730. errcode_t retval;
  731. char * oldpath = getenv("PATH");
  732. char * extended_opts = 0;
  733. const char * fs_type = 0;
  734. blk_t dev_size;
  735. long sysval;
  736. /* Update our PATH to include /sbin */
  737. if (oldpath) {
  738. char *newpath;
  739. newpath = xmalloc(sizeof (PATH_SET) + 1 + strlen (oldpath));
  740. strcpy (newpath, PATH_SET);
  741. strcat (newpath, ":");
  742. strcat (newpath, oldpath);
  743. putenv (newpath);
  744. } else
  745. putenv (PATH_SET);
  746. tmp = getenv("MKE2FS_SYNC");
  747. if (tmp)
  748. sync_kludge = atoi(tmp);
  749. /* Determine the system page size if possible */
  750. #if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
  751. #define _SC_PAGESIZE _SC_PAGE_SIZE
  752. #endif
  753. #ifdef _SC_PAGESIZE
  754. sysval = sysconf(_SC_PAGESIZE);
  755. if (sysval > 0)
  756. sys_page_size = sysval;
  757. #endif /* _SC_PAGESIZE */
  758. setbuf(stdout, NULL);
  759. setbuf(stderr, NULL);
  760. memset(&param, 0, sizeof(struct ext2_super_block));
  761. param.s_rev_level = 1; /* Create revision 1 filesystems now */
  762. param.s_feature_incompat |= EXT2_FEATURE_INCOMPAT_FILETYPE;
  763. param.s_feature_ro_compat |= EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
  764. #if 0
  765. param.s_feature_compat |= EXT2_FEATURE_COMPAT_DIR_INDEX;
  766. #endif
  767. #ifdef __linux__
  768. linux_version_code = get_kernel_revision();
  769. if (linux_version_code && linux_version_code < (2*65536 + 2*256)) {
  770. param.s_rev_level = 0;
  771. param.s_feature_incompat = 0;
  772. param.s_feature_compat = 0;
  773. param.s_feature_ro_compat = 0;
  774. }
  775. #endif
  776. if (argc && *argv) {
  777. /* If called as mkfs.ext3, create a journal inode */
  778. if (!strcmp(*argv + strlen(*argv) - 9, "mkfs.ext3"))
  779. journal_size = -1;
  780. }
  781. while ((c = getopt (argc, argv,
  782. "b:cE:f:g:i:jl:m:no:qr:R:s:tvI:J:ST:FL:M:N:O:V")) != EOF) {
  783. switch (c) {
  784. case 'b':
  785. blocksize = strtol(optarg, &tmp, 0);
  786. b = (blocksize > 0) ? blocksize : -blocksize;
  787. if (b < EXT2_MIN_BLOCK_SIZE ||
  788. b > EXT2_MAX_BLOCK_SIZE || *tmp) {
  789. bb_error_msg_and_die("bad block size - %s", optarg);
  790. }
  791. if (blocksize > 4096)
  792. bb_error_msg(
  793. "Warning: blocksize %d not usable on most systems",
  794. blocksize);
  795. if (blocksize > 0)
  796. param.s_log_block_size =
  797. int_log2(blocksize >>
  798. EXT2_MIN_BLOCK_LOG_SIZE);
  799. break;
  800. case 'c': /* Check for bad blocks */
  801. case 't': /* deprecated */
  802. cflag++;
  803. break;
  804. case 'f':
  805. size = strtoul(optarg, &tmp, 0);
  806. if (size < EXT2_MIN_BLOCK_SIZE ||
  807. size > EXT2_MAX_BLOCK_SIZE || *tmp) {
  808. bb_error_msg_and_die("bad fragment size - %s", optarg);
  809. }
  810. param.s_log_frag_size =
  811. int_log2(size >> EXT2_MIN_BLOCK_LOG_SIZE);
  812. bb_error_msg(
  813. "Warning: fragments not supported. "
  814. "Ignoring -f option");
  815. break;
  816. case 'g':
  817. param.s_blocks_per_group = strtoul(optarg, &tmp, 0);
  818. if (*tmp) {
  819. bb_error_msg_and_die("Illegal number for blocks per group");
  820. }
  821. if ((param.s_blocks_per_group % 8) != 0) {
  822. bb_error_msg_and_die("blocks per group must be multiple of 8");
  823. }
  824. break;
  825. case 'i':
  826. inode_ratio = strtoul(optarg, &tmp, 0);
  827. if (inode_ratio < EXT2_MIN_BLOCK_SIZE ||
  828. inode_ratio > EXT2_MAX_BLOCK_SIZE * 1024 ||
  829. *tmp) {
  830. bb_error_msg_and_die("bad inode ratio %s (min %d/max %d",
  831. optarg, EXT2_MIN_BLOCK_SIZE,
  832. EXT2_MAX_BLOCK_SIZE);
  833. }
  834. break;
  835. case 'J':
  836. parse_journal_opts(&journal_device, &journal_flags, &journal_size, optarg);
  837. break;
  838. case 'j':
  839. param.s_feature_compat |=
  840. EXT3_FEATURE_COMPAT_HAS_JOURNAL;
  841. if (!journal_size)
  842. journal_size = -1;
  843. break;
  844. case 'l':
  845. bad_blocks_filename = xmalloc(strlen(optarg)+1);
  846. strcpy(bad_blocks_filename, optarg);
  847. break;
  848. case 'm':
  849. reserved_ratio = strtoul(optarg, &tmp, 0);
  850. if (reserved_ratio > 50 || *tmp) {
  851. bb_error_msg_and_die("bad reserved blocks percent - %s", optarg);
  852. }
  853. break;
  854. case 'n':
  855. noaction++;
  856. break;
  857. case 'o':
  858. creator_os = optarg;
  859. break;
  860. case 'r':
  861. param.s_rev_level = atoi(optarg);
  862. if (param.s_rev_level == EXT2_GOOD_OLD_REV) {
  863. param.s_feature_incompat = 0;
  864. param.s_feature_compat = 0;
  865. param.s_feature_ro_compat = 0;
  866. }
  867. break;
  868. case 's': /* deprecated */
  869. if (atoi(optarg))
  870. param.s_feature_ro_compat |=
  871. EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
  872. else
  873. param.s_feature_ro_compat &=
  874. ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
  875. break;
  876. #ifdef EXT2_DYNAMIC_REV
  877. case 'I':
  878. inode_size = strtoul(optarg, &tmp, 0);
  879. if (*tmp) {
  880. bb_error_msg_and_die("bad inode size - %s", optarg);
  881. }
  882. break;
  883. #endif
  884. case 'N':
  885. num_inodes = atoi(optarg);
  886. break;
  887. case 'v':
  888. quiet = 0;
  889. break;
  890. case 'q':
  891. quiet = 1;
  892. break;
  893. case 'F':
  894. force = 1;
  895. break;
  896. case 'L':
  897. volume_label = optarg;
  898. break;
  899. case 'M':
  900. mount_dir = optarg;
  901. break;
  902. case 'O':
  903. if (!strcmp(optarg, "none")) {
  904. param.s_feature_compat = 0;
  905. param.s_feature_incompat = 0;
  906. param.s_feature_ro_compat = 0;
  907. break;
  908. }
  909. if (e2p_edit_feature(optarg,
  910. &param.s_feature_compat,
  911. ok_features)) {
  912. bb_error_msg_and_die("Invalid filesystem option set: %s", optarg);
  913. }
  914. break;
  915. case 'E':
  916. case 'R':
  917. extended_opts = optarg;
  918. break;
  919. case 'S':
  920. super_only = 1;
  921. break;
  922. case 'T':
  923. fs_type = optarg;
  924. break;
  925. case 'V':
  926. /* Print version number and exit */
  927. show_version_only++;
  928. break;
  929. default:
  930. bb_show_usage();
  931. }
  932. }
  933. if ((optind == argc) && !show_version_only)
  934. bb_show_usage();
  935. device_name = argv[optind++];
  936. if (!quiet || show_version_only)
  937. bb_error_msg("mke2fs %s (%s)", E2FSPROGS_VERSION,
  938. E2FSPROGS_DATE);
  939. if (show_version_only) {
  940. exit(0);
  941. }
  942. /*
  943. * If there's no blocksize specified and there is a journal
  944. * device, use it to figure out the blocksize
  945. */
  946. if (blocksize <= 0 && journal_device) {
  947. ext2_filsys jfs;
  948. io_manager io_ptr;
  949. #ifdef CONFIG_TESTIO_DEBUG
  950. io_ptr = test_io_manager;
  951. test_io_backing_manager = unix_io_manager;
  952. #else
  953. io_ptr = unix_io_manager;
  954. #endif
  955. retval = ext2fs_open(journal_device,
  956. EXT2_FLAG_JOURNAL_DEV_OK, 0,
  957. 0, io_ptr, &jfs);
  958. if (retval) {
  959. bb_error_msg_and_die("Could not open journal device %s", journal_device);
  960. }
  961. if ((blocksize < 0) && (jfs->blocksize < (unsigned) (-blocksize))) {
  962. bb_error_msg_and_die(
  963. "Journal dev blocksize (%d) smaller than "
  964. "minimum blocksize %d\n", jfs->blocksize,
  965. -blocksize);
  966. }
  967. blocksize = jfs->blocksize;
  968. param.s_log_block_size =
  969. int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
  970. ext2fs_close(jfs);
  971. }
  972. if (blocksize > sys_page_size) {
  973. if (!force) {
  974. bb_error_msg("%d-byte blocks too big for system (max %d)",
  975. blocksize, sys_page_size);
  976. proceed_question();
  977. }
  978. bb_error_msg(
  979. "Warning: %d-byte blocks too big for system "
  980. "(max %d), forced to continue",
  981. blocksize, sys_page_size);
  982. }
  983. if ((blocksize > 4096) &&
  984. (param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
  985. bb_error_msg(
  986. "\nWarning: some 2.4 kernels do not support "
  987. "blocksizes greater than 4096 \n\tusing ext3."
  988. " Use -b 4096 if this is an issue for you\n");
  989. if (optind < argc) {
  990. param.s_blocks_count = parse_num_blocks(argv[optind++],
  991. param.s_log_block_size);
  992. if (!param.s_blocks_count) {
  993. bb_error_msg_and_die("bad blocks count - %s", argv[optind - 1]);
  994. }
  995. }
  996. if (optind < argc)
  997. bb_show_usage();
  998. if (param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
  999. if (!fs_type)
  1000. fs_type = "journal";
  1001. reserved_ratio = 0;
  1002. param.s_feature_incompat = EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
  1003. param.s_feature_compat = 0;
  1004. param.s_feature_ro_compat = 0;
  1005. }
  1006. if (param.s_rev_level == EXT2_GOOD_OLD_REV &&
  1007. (param.s_feature_compat || param.s_feature_ro_compat ||
  1008. param.s_feature_incompat))
  1009. param.s_rev_level = 1; /* Create a revision 1 filesystem */
  1010. if (!force)
  1011. check_plausibility(device_name);
  1012. check_mount(device_name, force, _("filesystem"));
  1013. param.s_log_frag_size = param.s_log_block_size;
  1014. if (noaction && param.s_blocks_count) {
  1015. dev_size = param.s_blocks_count;
  1016. retval = 0;
  1017. } else {
  1018. retry:
  1019. retval = ext2fs_get_device_size(device_name,
  1020. EXT2_BLOCK_SIZE(&param),
  1021. &dev_size);
  1022. if ((retval == EFBIG) &&
  1023. (blocksize == 0) &&
  1024. (param.s_log_block_size == 0)) {
  1025. param.s_log_block_size = 2;
  1026. blocksize = 4096;
  1027. goto retry;
  1028. }
  1029. }
  1030. if (retval && (retval != EXT2_ET_UNIMPLEMENTED)) {
  1031. bb_error_msg_and_die("Could not determine filesystem size");
  1032. }
  1033. if (!param.s_blocks_count) {
  1034. if (retval == EXT2_ET_UNIMPLEMENTED) {
  1035. bb_error_msg_and_die(
  1036. "Couldn't determine device size; you "
  1037. "must specify\nthe size of the "
  1038. "filesystem");
  1039. } else {
  1040. if (dev_size == 0) {
  1041. bb_error_msg_and_die(
  1042. "Device size reported to be zero. "
  1043. "Invalid partition specified, or\n\t"
  1044. "partition table wasn't reread "
  1045. "after running fdisk, due to\n\t"
  1046. "a modified partition being busy "
  1047. "and in use. You may need to reboot\n\t"
  1048. "to re-read your partition table.\n"
  1049. );
  1050. }
  1051. param.s_blocks_count = dev_size;
  1052. if (sys_page_size > EXT2_BLOCK_SIZE(&param))
  1053. param.s_blocks_count &= ~((sys_page_size /
  1054. EXT2_BLOCK_SIZE(&param))-1);
  1055. }
  1056. } else if (!force && (param.s_blocks_count > dev_size)) {
  1057. bb_error_msg("Filesystem larger than apparent device size");
  1058. proceed_question();
  1059. }
  1060. /*
  1061. * If the user asked for HAS_JOURNAL, then make sure a journal
  1062. * gets created.
  1063. */
  1064. if ((param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
  1065. !journal_size)
  1066. journal_size = -1;
  1067. /* Set first meta blockgroup via an environment variable */
  1068. /* (this is mostly for debugging purposes) */
  1069. if ((param.s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) &&
  1070. ((tmp = getenv("MKE2FS_FIRST_META_BG"))))
  1071. param.s_first_meta_bg = atoi(tmp);
  1072. /* Get the hardware sector size, if available */
  1073. retval = ext2fs_get_device_sectsize(device_name, &sector_size);
  1074. if (retval) {
  1075. bb_error_msg_and_die("Could not determine hardware sector size");
  1076. }
  1077. if ((tmp = getenv("MKE2FS_DEVICE_SECTSIZE")) != NULL)
  1078. sector_size = atoi(tmp);
  1079. set_fs_defaults(fs_type, &param, blocksize, sector_size, &inode_ratio);
  1080. blocksize = EXT2_BLOCK_SIZE(&param);
  1081. if (extended_opts)
  1082. parse_extended_opts(&param, extended_opts);
  1083. /* Since sparse_super is the default, we would only have a problem
  1084. * here if it was explicitly disabled.
  1085. */
  1086. if ((param.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE) &&
  1087. !(param.s_feature_ro_compat&EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
  1088. bb_error_msg_and_die("reserved online resize blocks not supported "
  1089. "on non-sparse filesystem");
  1090. }
  1091. if (param.s_blocks_per_group) {
  1092. if (param.s_blocks_per_group < 256 ||
  1093. param.s_blocks_per_group > 8 * (unsigned) blocksize) {
  1094. bb_error_msg_and_die("blocks per group count out of range");
  1095. }
  1096. }
  1097. if (inode_size) {
  1098. if (inode_size < EXT2_GOOD_OLD_INODE_SIZE ||
  1099. inode_size > EXT2_BLOCK_SIZE(&param) ||
  1100. inode_size & (inode_size - 1)) {
  1101. bb_error_msg_and_die("bad inode size %d (min %d/max %d)",
  1102. inode_size, EXT2_GOOD_OLD_INODE_SIZE,
  1103. blocksize);
  1104. }
  1105. if (inode_size != EXT2_GOOD_OLD_INODE_SIZE)
  1106. bb_error_msg(
  1107. "Warning: %d-byte inodes not usable on most systems",
  1108. inode_size);
  1109. param.s_inode_size = inode_size;
  1110. }
  1111. /*
  1112. * Calculate number of inodes based on the inode ratio
  1113. */
  1114. param.s_inodes_count = num_inodes ? num_inodes :
  1115. ((__u64) param.s_blocks_count * blocksize)
  1116. / inode_ratio;
  1117. /*
  1118. * Calculate number of blocks to reserve
  1119. */
  1120. param.s_r_blocks_count = (param.s_blocks_count * reserved_ratio) / 100;
  1121. }
  1122. int mke2fs_main (int argc, char *argv[])
  1123. {
  1124. errcode_t retval = 0;
  1125. ext2_filsys fs;
  1126. badblocks_list bb_list = 0;
  1127. int journal_blocks;
  1128. unsigned int i;
  1129. int val;
  1130. io_manager io_ptr;
  1131. #ifdef ENABLE_NLS
  1132. setlocale(LC_MESSAGES, "");
  1133. setlocale(LC_CTYPE, "");
  1134. bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
  1135. textdomain(NLS_CAT_NAME);
  1136. #endif
  1137. PRS(argc, argv);
  1138. #ifdef CONFIG_TESTIO_DEBUG
  1139. io_ptr = test_io_manager;
  1140. test_io_backing_manager = unix_io_manager;
  1141. #else
  1142. io_ptr = unix_io_manager;
  1143. #endif
  1144. /*
  1145. * Initialize the superblock....
  1146. */
  1147. retval = ext2fs_initialize(device_name, 0, &param,
  1148. io_ptr, &fs);
  1149. if (retval) {
  1150. bb_error_msg_and_die("Could not set up superblock");
  1151. }
  1152. /*
  1153. * Wipe out the old on-disk superblock
  1154. */
  1155. if (!noaction)
  1156. zap_sector(fs, 2, 6);
  1157. /*
  1158. * Generate a UUID for it...
  1159. */
  1160. uuid_generate(fs->super->s_uuid);
  1161. /*
  1162. * Initialize the directory index variables
  1163. */
  1164. fs->super->s_def_hash_version = EXT2_HASH_TEA;
  1165. uuid_generate((unsigned char *) fs->super->s_hash_seed);
  1166. /*
  1167. * Add "jitter" to the superblock's check interval so that we
  1168. * don't check all the filesystems at the same time. We use a
  1169. * kludgy hack of using the UUID to derive a random jitter value.
  1170. */
  1171. for (i = 0, val = 0 ; i < sizeof(fs->super->s_uuid); i++)
  1172. val += fs->super->s_uuid[i];
  1173. fs->super->s_max_mnt_count += val % EXT2_DFL_MAX_MNT_COUNT;
  1174. /*
  1175. * Override the creator OS, if applicable
  1176. */
  1177. if (creator_os && !set_os(fs->super, creator_os)) {
  1178. bb_error_msg_and_die("unknown os - %s", creator_os);
  1179. }
  1180. /*
  1181. * For the Hurd, we will turn off filetype since it doesn't
  1182. * support it.
  1183. */
  1184. if (fs->super->s_creator_os == EXT2_OS_HURD)
  1185. fs->super->s_feature_incompat &=
  1186. ~EXT2_FEATURE_INCOMPAT_FILETYPE;
  1187. /*
  1188. * Set the volume label...
  1189. */
  1190. if (volume_label) {
  1191. memset(fs->super->s_volume_name, 0,
  1192. sizeof(fs->super->s_volume_name));
  1193. strncpy(fs->super->s_volume_name, volume_label,
  1194. sizeof(fs->super->s_volume_name));
  1195. }
  1196. /*
  1197. * Set the last mount directory
  1198. */
  1199. if (mount_dir) {
  1200. memset(fs->super->s_last_mounted, 0,
  1201. sizeof(fs->super->s_last_mounted));
  1202. strncpy(fs->super->s_last_mounted, mount_dir,
  1203. sizeof(fs->super->s_last_mounted));
  1204. }
  1205. if (!quiet || noaction)
  1206. show_stats(fs);
  1207. if (noaction)
  1208. exit(0);
  1209. if (fs->super->s_feature_incompat &
  1210. EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
  1211. create_journal_dev(fs);
  1212. exit(ext2fs_close(fs) ? 1 : 0);
  1213. }
  1214. if (bad_blocks_filename)
  1215. read_bb_file(fs, &bb_list, bad_blocks_filename);
  1216. if (cflag)
  1217. test_disk(fs, &bb_list);
  1218. handle_bad_blocks(fs, bb_list);
  1219. fs->stride = fs_stride;
  1220. retval = ext2fs_allocate_tables(fs);
  1221. if (retval) {
  1222. bb_error_msg_and_die("Could not allocate filesystem tables");
  1223. }
  1224. if (super_only) {
  1225. fs->super->s_state |= EXT2_ERROR_FS;
  1226. fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY);
  1227. } else {
  1228. /* rsv must be a power of two (64kB is MD RAID sb alignment) */
  1229. unsigned int rsv = 65536 / fs->blocksize;
  1230. unsigned long blocks = fs->super->s_blocks_count;
  1231. unsigned long start;
  1232. blk_t ret_blk;
  1233. #ifdef ZAP_BOOTBLOCK
  1234. zap_sector(fs, 0, 2);
  1235. #endif
  1236. /*
  1237. * Wipe out any old MD RAID (or other) metadata at the end
  1238. * of the device. This will also verify that the device is
  1239. * as large as we think. Be careful with very small devices.
  1240. */
  1241. start = (blocks & ~(rsv - 1));
  1242. if (start > rsv)
  1243. start -= rsv;
  1244. if (start > 0)
  1245. retval = zero_blocks(fs, start, blocks - start,
  1246. NULL, &ret_blk, NULL);
  1247. if (retval) {
  1248. bb_error_msg("Could not zero block %u at end of filesystem", ret_blk);
  1249. }
  1250. write_inode_tables(fs);
  1251. create_root_dir(fs);
  1252. create_lost_and_found(fs);
  1253. reserve_inodes(fs);
  1254. create_bad_block_inode(fs, bb_list);
  1255. if (fs->super->s_feature_compat &
  1256. EXT2_FEATURE_COMPAT_RESIZE_INODE) {
  1257. retval = ext2fs_create_resize_inode(fs);
  1258. if (retval) {
  1259. bb_error_msg_and_die("Could not reserve blocks for online resize");
  1260. }
  1261. }
  1262. }
  1263. if (journal_device) {
  1264. ext2_filsys jfs;
  1265. if (!force)
  1266. check_plausibility(journal_device);
  1267. check_mount(journal_device, force, _("journal"));
  1268. retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
  1269. EXT2_FLAG_JOURNAL_DEV_OK, 0,
  1270. fs->blocksize, unix_io_manager, &jfs);
  1271. if (retval) {
  1272. bb_error_msg_and_die("Could not open journal device %s", journal_device);
  1273. }
  1274. if (!quiet) {
  1275. printf("Adding journal to device %s: ", journal_device);
  1276. fflush(stdout);
  1277. }
  1278. retval = ext2fs_add_journal_device(fs, jfs);
  1279. if(retval) {
  1280. bb_error_msg_and_die("Could not add journal to device %s", journal_device);
  1281. }
  1282. if (!quiet)
  1283. printf("done\n");
  1284. ext2fs_close(jfs);
  1285. free(journal_device);
  1286. } else if (journal_size) {
  1287. journal_blocks = figure_journal_size(journal_size, fs);
  1288. if (!journal_blocks) {
  1289. fs->super->s_feature_compat &=
  1290. ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
  1291. goto no_journal;
  1292. }
  1293. if (!quiet) {
  1294. printf("Creating journal (%d blocks): ",
  1295. journal_blocks);
  1296. fflush(stdout);
  1297. }
  1298. retval = ext2fs_add_journal_inode(fs, journal_blocks,
  1299. journal_flags);
  1300. if (retval) {
  1301. bb_error_msg_and_die("Could not create journal");
  1302. }
  1303. if (!quiet)
  1304. printf("done\n");
  1305. }
  1306. no_journal:
  1307. if (!quiet)
  1308. printf("Writing superblocks and "
  1309. "filesystem accounting information: ");
  1310. retval = ext2fs_flush(fs);
  1311. if (retval) {
  1312. bb_error_msg("\nWarning, had trouble writing out superblocks");
  1313. }
  1314. if (!quiet) {
  1315. printf("done\n\n");
  1316. if (!getenv("MKE2FS_SKIP_CHECK_MSG"))
  1317. print_check_message(fs);
  1318. }
  1319. val = ext2fs_close(fs);
  1320. return (retval || val) ? 1 : 0;
  1321. }