3
0

mke2fs.c 35 KB

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