fsck.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * fsck --- A generic, parallelizing front-end for the fsck program.
  4. * It will automatically try to run fsck programs in parallel if the
  5. * devices are on separate spindles. It is based on the same ideas as
  6. * the generic front end for fsck by David Engel and Fred van Kempen,
  7. * but it has been completely rewritten from scratch to support
  8. * parallel execution.
  9. *
  10. * Written by Theodore Ts'o, <tytso@mit.edu>
  11. *
  12. * Miquel van Smoorenburg (miquels@drinkel.ow.org) 20-Oct-1994:
  13. * o Changed -t fstype to behave like with mount when -A (all file
  14. * systems) or -M (like mount) is specified.
  15. * o fsck looks if it can find the fsck.type program to decide
  16. * if it should ignore the fs type. This way more fsck programs
  17. * can be added without changing this front-end.
  18. * o -R flag skip root file system.
  19. *
  20. * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
  21. * 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o.
  22. *
  23. * Licensed under GPLv2, see file LICENSE in this source tree.
  24. */
  25. /* All filesystem specific hooks have been removed.
  26. * If filesystem cannot be determined, we will execute
  27. * "fsck.auto". Currently this also happens if you specify
  28. * UUID=xxx or LABEL=xxx as an object to check.
  29. * Detection code for that is also probably has to be in fsck.auto.
  30. *
  31. * In other words, this is _really_ is just a driver program which
  32. * spawns actual fsck.something for each filesystem to check.
  33. * It doesn't guess filesystem types from on-disk format.
  34. */
  35. //usage:#define fsck_trivial_usage
  36. //usage: "[-ANPRTV] [-C FD] [-t FSTYPE] [FS_OPTS] [BLOCKDEV]..."
  37. //usage:#define fsck_full_usage "\n\n"
  38. //usage: "Check and repair filesystems\n"
  39. //usage: "\n -A Walk /etc/fstab and check all filesystems"
  40. //usage: "\n -N Don't execute, just show what would be done"
  41. //usage: "\n -P With -A, check filesystems in parallel"
  42. //usage: "\n -R With -A, skip the root filesystem"
  43. //usage: "\n -T Don't show title on startup"
  44. //usage: "\n -V Verbose"
  45. //usage: "\n -C n Write status information to specified filedescriptor"
  46. //usage: "\n -t TYPE List of filesystem types to check"
  47. #include "libbb.h"
  48. /* "progress indicator" code is somewhat buggy and ext[23] specific.
  49. * We should be filesystem agnostic. IOW: there should be a well-defined
  50. * API for fsck.something, NOT ad-hoc hacks in generic fsck. */
  51. #define DO_PROGRESS_INDICATOR 0
  52. /* fsck 1.41.4 (27-Jan-2009) manpage says:
  53. * 0 - No errors
  54. * 1 - File system errors corrected
  55. * 2 - System should be rebooted
  56. * 4 - File system errors left uncorrected
  57. * 8 - Operational error
  58. * 16 - Usage or syntax error
  59. * 32 - Fsck canceled by user request
  60. * 128 - Shared library error
  61. */
  62. #define EXIT_OK 0
  63. #define EXIT_NONDESTRUCT 1
  64. #define EXIT_DESTRUCT 2
  65. #define EXIT_UNCORRECTED 4
  66. #define EXIT_ERROR 8
  67. #define EXIT_USAGE 16
  68. #define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
  69. /*
  70. * Internal structure for mount table entries.
  71. */
  72. struct fs_info {
  73. struct fs_info *next;
  74. char *device;
  75. char *mountpt;
  76. char *type;
  77. char *opts;
  78. int passno;
  79. int flags;
  80. };
  81. #define FLAG_DONE 1
  82. #define FLAG_PROGRESS 2
  83. /*
  84. * Structure to allow exit codes to be stored
  85. */
  86. struct fsck_instance {
  87. struct fsck_instance *next;
  88. int pid;
  89. int flags;
  90. #if DO_PROGRESS_INDICATOR
  91. time_t start_time;
  92. #endif
  93. char *prog;
  94. char *device;
  95. char *base_device; /* /dev/hda for /dev/hdaN etc */
  96. };
  97. static const char ignored_types[] ALIGN1 =
  98. "ignore\0"
  99. "iso9660\0"
  100. "nfs\0"
  101. "proc\0"
  102. "sw\0"
  103. "swap\0"
  104. "tmpfs\0"
  105. "devpts\0";
  106. #if 0
  107. static const char really_wanted[] ALIGN1 =
  108. "minix\0"
  109. "ext2\0"
  110. "ext3\0"
  111. "jfs\0"
  112. "reiserfs\0"
  113. "xiafs\0"
  114. "xfs\0";
  115. #endif
  116. #define BASE_MD "/dev/md"
  117. static char **args;
  118. static int num_args;
  119. static int verbose;
  120. #define FS_TYPE_FLAG_NORMAL 0
  121. #define FS_TYPE_FLAG_OPT 1
  122. #define FS_TYPE_FLAG_NEGOPT 2
  123. static char **fs_type_list;
  124. static uint8_t *fs_type_flag;
  125. static smallint fs_type_negated;
  126. static smallint noexecute;
  127. static smallint serialize;
  128. static smallint skip_root;
  129. /* static smallint like_mount; */
  130. static smallint parallel_root;
  131. static smallint force_all_parallel;
  132. #if DO_PROGRESS_INDICATOR
  133. static smallint progress;
  134. static int progress_fd;
  135. #endif
  136. static int num_running;
  137. static int max_running;
  138. static char *fstype;
  139. static struct fs_info *filesys_info;
  140. static struct fs_info *filesys_last;
  141. static struct fsck_instance *instance_list;
  142. /*
  143. * Return the "base device" given a particular device; this is used to
  144. * assure that we only fsck one partition on a particular drive at any
  145. * one time. Otherwise, the disk heads will be seeking all over the
  146. * place. If the base device cannot be determined, return NULL.
  147. *
  148. * The base_device() function returns an allocated string which must
  149. * be freed.
  150. */
  151. #if ENABLE_FEATURE_DEVFS
  152. /*
  153. * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3
  154. * pathames.
  155. */
  156. static const char *const devfs_hier[] = {
  157. "host", "bus", "target", "lun", NULL
  158. };
  159. #endif
  160. static char *base_device(const char *device)
  161. {
  162. char *str, *cp;
  163. #if ENABLE_FEATURE_DEVFS
  164. const char *const *hier;
  165. const char *disk;
  166. int len;
  167. #endif
  168. str = xstrdup(device);
  169. /* Skip over "/dev/"; if it's not present, give up */
  170. cp = skip_dev_pfx(str);
  171. if (cp == str)
  172. goto errout;
  173. /*
  174. * For md devices, we treat them all as if they were all
  175. * on one disk, since we don't know how to parallelize them.
  176. */
  177. if (cp[0] == 'm' && cp[1] == 'd') {
  178. cp[2] = 0;
  179. return str;
  180. }
  181. /* Handle DAC 960 devices */
  182. if (is_prefixed_with(cp, "rd/")) {
  183. cp += 3;
  184. if (cp[0] != 'c' || !isdigit(cp[1])
  185. || cp[2] != 'd' || !isdigit(cp[3]))
  186. goto errout;
  187. cp[4] = 0;
  188. return str;
  189. }
  190. /* Now let's handle /dev/hd* and /dev/sd* devices.... */
  191. if ((cp[0] == 'h' || cp[0] == 's') && cp[1] == 'd') {
  192. cp += 2;
  193. /* If there's a single number after /dev/hd, skip it */
  194. if (isdigit(*cp))
  195. cp++;
  196. /* What follows must be an alpha char, or give up */
  197. if (!isalpha(*cp))
  198. goto errout;
  199. cp[1] = 0;
  200. return str;
  201. }
  202. #if ENABLE_FEATURE_DEVFS
  203. /* Now let's handle devfs (ugh) names */
  204. len = 0;
  205. if (is_prefixed_with(cp, "ide/"))
  206. len = 4;
  207. if (is_prefixed_with(cp, "scsi/"))
  208. len = 5;
  209. if (len) {
  210. cp += len;
  211. /*
  212. * Now we proceed down the expected devfs hierarchy.
  213. * i.e., .../host1/bus2/target3/lun4/...
  214. * If we don't find the expected token, followed by
  215. * some number of digits at each level, abort.
  216. */
  217. for (hier = devfs_hier; *hier; hier++) {
  218. cp = is_prefixed_with(cp, *hier);
  219. if (!cp)
  220. goto errout;
  221. while (*cp != '/' && *cp != '\0') {
  222. if (!isdigit(*cp))
  223. goto errout;
  224. cp++;
  225. }
  226. //FIXME: what if *cp = '\0' now? cp++ moves past it!!!
  227. cp++;
  228. }
  229. cp[-1] = '\0';
  230. return str;
  231. }
  232. /* Now handle devfs /dev/disc or /dev/disk names */
  233. disk = NULL;
  234. if (is_prefixed_with(cp, "discs/"))
  235. disk = "disc";
  236. else if (is_prefixed_with(cp, "disks/"))
  237. disk = "disk";
  238. if (disk) {
  239. cp += 6;
  240. cp = is_prefixed_with(cp, disk);
  241. if (!cp)
  242. goto errout;
  243. while (*cp != '/' && *cp != '\0') {
  244. if (!isdigit(*cp))
  245. goto errout;
  246. cp++;
  247. }
  248. *cp = '\0';
  249. return str;
  250. }
  251. #endif
  252. errout:
  253. free(str);
  254. return NULL;
  255. }
  256. static void free_instance(struct fsck_instance *p)
  257. {
  258. free(p->prog);
  259. free(p->device);
  260. free(p->base_device);
  261. free(p);
  262. }
  263. static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
  264. const char *type, const char *opts,
  265. int passno)
  266. {
  267. struct fs_info *fs;
  268. fs = xzalloc(sizeof(*fs));
  269. fs->device = xstrdup(device);
  270. fs->mountpt = xstrdup(mntpnt);
  271. if (strchr(type, ','))
  272. type = (char *)"auto";
  273. fs->type = xstrdup(type);
  274. fs->opts = xstrdup(opts ? opts : "");
  275. fs->passno = passno < 0 ? 1 : passno;
  276. /*fs->flags = 0; */
  277. /*fs->next = NULL; */
  278. if (!filesys_info)
  279. filesys_info = fs;
  280. else
  281. filesys_last->next = fs;
  282. filesys_last = fs;
  283. return fs;
  284. }
  285. /* Load the filesystem database from /etc/fstab */
  286. static void load_fs_info(const char *filename)
  287. {
  288. FILE *fstab;
  289. struct mntent mte;
  290. fstab = setmntent(filename, "r");
  291. if (!fstab) {
  292. bb_perror_msg("can't read '%s'", filename);
  293. return;
  294. }
  295. // Loop through entries
  296. while (getmntent_r(fstab, &mte, bb_common_bufsiz1, COMMON_BUFSIZE)) {
  297. //bb_info_msg("CREATE[%s][%s][%s][%s][%d]", mte.mnt_fsname, mte.mnt_dir,
  298. // mte.mnt_type, mte.mnt_opts,
  299. // mte.mnt_passno);
  300. create_fs_device(mte.mnt_fsname, mte.mnt_dir,
  301. mte.mnt_type, mte.mnt_opts,
  302. mte.mnt_passno);
  303. }
  304. endmntent(fstab);
  305. }
  306. /* Lookup filesys in /etc/fstab and return the corresponding entry. */
  307. static struct fs_info *lookup(char *filesys)
  308. {
  309. struct fs_info *fs;
  310. for (fs = filesys_info; fs; fs = fs->next) {
  311. if (strcmp(filesys, fs->device) == 0
  312. || (fs->mountpt && strcmp(filesys, fs->mountpt) == 0)
  313. )
  314. break;
  315. }
  316. return fs;
  317. }
  318. #if DO_PROGRESS_INDICATOR
  319. static int progress_active(void)
  320. {
  321. struct fsck_instance *inst;
  322. for (inst = instance_list; inst; inst = inst->next) {
  323. if (inst->flags & FLAG_DONE)
  324. continue;
  325. if (inst->flags & FLAG_PROGRESS)
  326. return 1;
  327. }
  328. return 0;
  329. }
  330. #endif
  331. /*
  332. * Send a signal to all outstanding fsck child processes
  333. */
  334. static void kill_all_if_got_signal(void)
  335. {
  336. static smallint kill_sent;
  337. struct fsck_instance *inst;
  338. if (!bb_got_signal || kill_sent)
  339. return;
  340. for (inst = instance_list; inst; inst = inst->next) {
  341. if (inst->flags & FLAG_DONE)
  342. continue;
  343. kill(inst->pid, SIGTERM);
  344. }
  345. kill_sent = 1;
  346. }
  347. /*
  348. * Wait for one child process to exit; when it does, unlink it from
  349. * the list of executing child processes, free, and return its exit status.
  350. * If there is no exited child, return -1.
  351. */
  352. static int wait_one(int flags)
  353. {
  354. int status;
  355. int sig;
  356. struct fsck_instance *inst, *prev;
  357. pid_t pid;
  358. if (!instance_list)
  359. return -1;
  360. /* if (noexecute) { already returned -1; } */
  361. while (1) {
  362. pid = waitpid(-1, &status, flags);
  363. kill_all_if_got_signal();
  364. if (pid == 0) /* flags == WNOHANG and no children exited */
  365. return -1;
  366. if (pid < 0) {
  367. if (errno == EINTR)
  368. continue;
  369. if (errno == ECHILD) { /* paranoia */
  370. bb_error_msg("wait: no more children");
  371. return -1;
  372. }
  373. bb_perror_msg("wait");
  374. continue;
  375. }
  376. prev = NULL;
  377. inst = instance_list;
  378. do {
  379. if (inst->pid == pid)
  380. goto child_died;
  381. prev = inst;
  382. inst = inst->next;
  383. } while (inst);
  384. }
  385. child_died:
  386. if (WIFEXITED(status))
  387. status = WEXITSTATUS(status);
  388. else if (WIFSIGNALED(status)) {
  389. sig = WTERMSIG(status);
  390. status = EXIT_UNCORRECTED;
  391. if (sig != SIGINT) {
  392. printf("Warning: %s %s terminated "
  393. "by signal %d\n",
  394. inst->prog, inst->device, sig);
  395. status = EXIT_ERROR;
  396. }
  397. } else {
  398. printf("%s %s: status is %x, should never happen\n",
  399. inst->prog, inst->device, status);
  400. status = EXIT_ERROR;
  401. }
  402. #if DO_PROGRESS_INDICATOR
  403. if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) {
  404. struct fsck_instance *inst2;
  405. for (inst2 = instance_list; inst2; inst2 = inst2->next) {
  406. if (inst2->flags & FLAG_DONE)
  407. continue;
  408. if (strcmp(inst2->type, "ext2") != 0
  409. && strcmp(inst2->type, "ext3") != 0
  410. ) {
  411. continue;
  412. }
  413. /* ext[23], we will send USR1
  414. * (request to start displaying progress bar)
  415. *
  416. * If we've just started the fsck, wait a tiny
  417. * bit before sending the kill, to give it
  418. * time to set up the signal handler
  419. */
  420. if (inst2->start_time >= time(NULL) - 1)
  421. sleep(1);
  422. kill(inst2->pid, SIGUSR1);
  423. inst2->flags |= FLAG_PROGRESS;
  424. break;
  425. }
  426. }
  427. #endif
  428. if (prev)
  429. prev->next = inst->next;
  430. else
  431. instance_list = inst->next;
  432. if (verbose > 1)
  433. printf("Finished with %s (exit status %d)\n",
  434. inst->device, status);
  435. num_running--;
  436. free_instance(inst);
  437. return status;
  438. }
  439. /*
  440. * Wait until all executing child processes have exited; return the
  441. * logical OR of all of their exit code values.
  442. */
  443. #define FLAG_WAIT_ALL 0
  444. #define FLAG_WAIT_ATLEAST_ONE WNOHANG
  445. static int wait_many(int flags)
  446. {
  447. int exit_status;
  448. int global_status = 0;
  449. int wait_flags = 0;
  450. while ((exit_status = wait_one(wait_flags)) != -1) {
  451. global_status |= exit_status;
  452. wait_flags |= flags;
  453. }
  454. return global_status;
  455. }
  456. /*
  457. * Execute a particular fsck program, and link it into the list of
  458. * child processes we are waiting for.
  459. */
  460. static void execute(const char *type, const char *device,
  461. const char *mntpt /*, int interactive */)
  462. {
  463. int i;
  464. struct fsck_instance *inst;
  465. pid_t pid;
  466. args[0] = xasprintf("fsck.%s", type);
  467. #if DO_PROGRESS_INDICATOR
  468. if (progress && !progress_active()) {
  469. if (strcmp(type, "ext2") == 0
  470. || strcmp(type, "ext3") == 0
  471. ) {
  472. args[XXX] = xasprintf("-C%d", progress_fd); /* 1 */
  473. inst->flags |= FLAG_PROGRESS;
  474. }
  475. }
  476. #endif
  477. args[num_args - 2] = (char*)device;
  478. /* args[num_args - 1] = NULL; - already is */
  479. if (verbose || noexecute) {
  480. printf("[%s (%d) -- %s]", args[0], num_running,
  481. mntpt ? mntpt : device);
  482. for (i = 0; args[i]; i++)
  483. printf(" %s", args[i]);
  484. bb_putchar('\n');
  485. }
  486. /* Fork and execute the correct program. */
  487. pid = -1;
  488. if (!noexecute) {
  489. pid = spawn(args);
  490. if (pid < 0)
  491. bb_simple_perror_msg(args[0]);
  492. }
  493. #if DO_PROGRESS_INDICATOR
  494. free(args[XXX]);
  495. #endif
  496. /* No child, so don't record an instance */
  497. if (pid <= 0) {
  498. free(args[0]);
  499. return;
  500. }
  501. inst = xzalloc(sizeof(*inst));
  502. inst->pid = pid;
  503. inst->prog = args[0];
  504. inst->device = xstrdup(device);
  505. inst->base_device = base_device(device);
  506. #if DO_PROGRESS_INDICATOR
  507. inst->start_time = time(NULL);
  508. #endif
  509. /* Add to the list of running fsck's.
  510. * (was adding to the end, but adding to the front is simpler...) */
  511. inst->next = instance_list;
  512. instance_list = inst;
  513. }
  514. /*
  515. * Run the fsck program on a particular device
  516. *
  517. * If the type is specified using -t, and it isn't prefixed with "no"
  518. * (as in "noext2") and only one filesystem type is specified, then
  519. * use that type regardless of what is specified in /etc/fstab.
  520. *
  521. * If the type isn't specified by the user, then use either the type
  522. * specified in /etc/fstab, or "auto".
  523. */
  524. static void fsck_device(struct fs_info *fs /*, int interactive */)
  525. {
  526. const char *type;
  527. if (strcmp(fs->type, "auto") != 0) {
  528. type = fs->type;
  529. if (verbose > 2)
  530. bb_info_msg("using filesystem type '%s' %s",
  531. type, "from fstab");
  532. } else if (fstype
  533. && (fstype[0] != 'n' || fstype[1] != 'o') /* != "no" */
  534. && !is_prefixed_with(fstype, "opts=")
  535. && !is_prefixed_with(fstype, "loop")
  536. && !strchr(fstype, ',')
  537. ) {
  538. type = fstype;
  539. if (verbose > 2)
  540. bb_info_msg("using filesystem type '%s' %s",
  541. type, "from -t");
  542. } else {
  543. type = "auto";
  544. if (verbose > 2)
  545. bb_info_msg("using filesystem type '%s' %s",
  546. type, "(default)");
  547. }
  548. num_running++;
  549. execute(type, fs->device, fs->mountpt /*, interactive */);
  550. }
  551. /*
  552. * Returns TRUE if a partition on the same disk is already being
  553. * checked.
  554. */
  555. static int device_already_active(char *device)
  556. {
  557. struct fsck_instance *inst;
  558. char *base;
  559. if (force_all_parallel)
  560. return 0;
  561. #ifdef BASE_MD
  562. /* Don't check a soft raid disk with any other disk */
  563. if (instance_list
  564. && (is_prefixed_with(instance_list->device, BASE_MD)
  565. || is_prefixed_with(device, BASE_MD))
  566. ) {
  567. return 1;
  568. }
  569. #endif
  570. base = base_device(device);
  571. /*
  572. * If we don't know the base device, assume that the device is
  573. * already active if there are any fsck instances running.
  574. */
  575. if (!base)
  576. return (instance_list != NULL);
  577. for (inst = instance_list; inst; inst = inst->next) {
  578. if (!inst->base_device || !strcmp(base, inst->base_device)) {
  579. free(base);
  580. return 1;
  581. }
  582. }
  583. free(base);
  584. return 0;
  585. }
  586. /*
  587. * This function returns true if a particular option appears in a
  588. * comma-delimited options list
  589. */
  590. static int opt_in_list(char *opt, char *optlist)
  591. {
  592. char *s;
  593. int len;
  594. if (!optlist)
  595. return 0;
  596. len = strlen(opt);
  597. s = optlist - 1;
  598. while (1) {
  599. s = strstr(s + 1, opt);
  600. if (!s)
  601. return 0;
  602. /* neither "opt.." nor "xxx,opt.."? */
  603. if (s != optlist && s[-1] != ',')
  604. continue;
  605. /* neither "..opt" nor "..opt,xxx"? */
  606. if (s[len] != '\0' && s[len] != ',')
  607. continue;
  608. return 1;
  609. }
  610. }
  611. /* See if the filesystem matches the criteria given by the -t option */
  612. static int fs_match(struct fs_info *fs)
  613. {
  614. int n, ret, checked_type;
  615. char *cp;
  616. if (!fs_type_list)
  617. return 1;
  618. ret = 0;
  619. checked_type = 0;
  620. n = 0;
  621. while (1) {
  622. cp = fs_type_list[n];
  623. if (!cp)
  624. break;
  625. switch (fs_type_flag[n]) {
  626. case FS_TYPE_FLAG_NORMAL:
  627. checked_type++;
  628. if (strcmp(cp, fs->type) == 0)
  629. ret = 1;
  630. break;
  631. case FS_TYPE_FLAG_NEGOPT:
  632. if (opt_in_list(cp, fs->opts))
  633. return 0;
  634. break;
  635. case FS_TYPE_FLAG_OPT:
  636. if (!opt_in_list(cp, fs->opts))
  637. return 0;
  638. break;
  639. }
  640. n++;
  641. }
  642. if (checked_type == 0)
  643. return 1;
  644. return (fs_type_negated ? !ret : ret);
  645. }
  646. /* Check if we should ignore this filesystem. */
  647. static int ignore(struct fs_info *fs)
  648. {
  649. /*
  650. * If the pass number is 0, ignore it.
  651. */
  652. if (fs->passno == 0)
  653. return 1;
  654. /*
  655. * If a specific fstype is specified, and it doesn't match,
  656. * ignore it.
  657. */
  658. if (!fs_match(fs))
  659. return 1;
  660. /* Are we ignoring this type? */
  661. if (index_in_strings(ignored_types, fs->type) >= 0)
  662. return 1;
  663. /* We can and want to check this file system type. */
  664. return 0;
  665. }
  666. /* Check all file systems, using the /etc/fstab table. */
  667. static int check_all(void)
  668. {
  669. struct fs_info *fs;
  670. int status = EXIT_OK;
  671. smallint not_done_yet;
  672. smallint pass_done;
  673. int passno;
  674. if (verbose)
  675. puts("Checking all filesystems");
  676. /*
  677. * Do an initial scan over the filesystem; mark filesystems
  678. * which should be ignored as done, and resolve any "auto"
  679. * filesystem types (done as a side-effect of calling ignore()).
  680. */
  681. for (fs = filesys_info; fs; fs = fs->next)
  682. if (ignore(fs))
  683. fs->flags |= FLAG_DONE;
  684. /*
  685. * Find and check the root filesystem.
  686. */
  687. if (!parallel_root) {
  688. for (fs = filesys_info; fs; fs = fs->next) {
  689. if (LONE_CHAR(fs->mountpt, '/')) {
  690. if (!skip_root && !ignore(fs)) {
  691. fsck_device(fs /*, 1*/);
  692. status |= wait_many(FLAG_WAIT_ALL);
  693. if (status > EXIT_NONDESTRUCT)
  694. return status;
  695. }
  696. fs->flags |= FLAG_DONE;
  697. break;
  698. }
  699. }
  700. }
  701. /*
  702. * This is for the bone-headed user who has root
  703. * filesystem listed twice.
  704. * "Skip root" will skip _all_ root entries.
  705. */
  706. if (skip_root)
  707. for (fs = filesys_info; fs; fs = fs->next)
  708. if (LONE_CHAR(fs->mountpt, '/'))
  709. fs->flags |= FLAG_DONE;
  710. not_done_yet = 1;
  711. passno = 1;
  712. while (not_done_yet) {
  713. not_done_yet = 0;
  714. pass_done = 1;
  715. for (fs = filesys_info; fs; fs = fs->next) {
  716. if (bb_got_signal)
  717. break;
  718. if (fs->flags & FLAG_DONE)
  719. continue;
  720. /*
  721. * If the filesystem's pass number is higher
  722. * than the current pass number, then we didn't
  723. * do it yet.
  724. */
  725. if (fs->passno > passno) {
  726. not_done_yet = 1;
  727. continue;
  728. }
  729. /*
  730. * If a filesystem on a particular device has
  731. * already been spawned, then we need to defer
  732. * this to another pass.
  733. */
  734. if (device_already_active(fs->device)) {
  735. pass_done = 0;
  736. continue;
  737. }
  738. /*
  739. * Spawn off the fsck process
  740. */
  741. fsck_device(fs /*, serialize*/);
  742. fs->flags |= FLAG_DONE;
  743. /*
  744. * Only do one filesystem at a time, or if we
  745. * have a limit on the number of fsck's extant
  746. * at one time, apply that limit.
  747. */
  748. if (serialize
  749. || (max_running && (num_running >= max_running))
  750. ) {
  751. pass_done = 0;
  752. break;
  753. }
  754. }
  755. if (bb_got_signal)
  756. break;
  757. if (verbose > 1)
  758. printf("--waiting-- (pass %d)\n", passno);
  759. status |= wait_many(pass_done ? FLAG_WAIT_ALL :
  760. FLAG_WAIT_ATLEAST_ONE);
  761. if (pass_done) {
  762. if (verbose > 1)
  763. puts("----------------------------------");
  764. passno++;
  765. } else
  766. not_done_yet = 1;
  767. }
  768. kill_all_if_got_signal();
  769. status |= wait_many(FLAG_WAIT_ATLEAST_ONE);
  770. return status;
  771. }
  772. /*
  773. * Deal with the fsck -t argument.
  774. * Huh, for mount "-t novfat,nfs" means "neither vfat nor nfs"!
  775. * Why here we require "-t novfat,nonfs" ??
  776. */
  777. static void compile_fs_type(char *fs_type)
  778. {
  779. char *s;
  780. int num = 2;
  781. smallint negate;
  782. s = fs_type;
  783. while ((s = strchr(s, ','))) {
  784. num++;
  785. s++;
  786. }
  787. fs_type_list = xzalloc(num * sizeof(fs_type_list[0]));
  788. fs_type_flag = xzalloc(num * sizeof(fs_type_flag[0]));
  789. fs_type_negated = -1; /* not yet known is it negated or not */
  790. num = 0;
  791. s = fs_type;
  792. while (1) {
  793. char *comma;
  794. negate = 0;
  795. if (s[0] == 'n' && s[1] == 'o') { /* "no.." */
  796. s += 2;
  797. negate = 1;
  798. } else if (s[0] == '!') {
  799. s++;
  800. negate = 1;
  801. }
  802. if (strcmp(s, "loop") == 0)
  803. /* loop is really short-hand for opts=loop */
  804. goto loop_special_case;
  805. if (is_prefixed_with(s, "opts=")) {
  806. s += 5;
  807. loop_special_case:
  808. fs_type_flag[num] = negate ? FS_TYPE_FLAG_NEGOPT : FS_TYPE_FLAG_OPT;
  809. } else {
  810. if (fs_type_negated == -1)
  811. fs_type_negated = negate;
  812. if (fs_type_negated != negate)
  813. bb_error_msg_and_die(
  814. "either all or none of the filesystem types passed to -t must be prefixed "
  815. "with 'no' or '!'");
  816. }
  817. comma = strchr(s, ',');
  818. fs_type_list[num++] = comma ? xstrndup(s, comma-s) : xstrdup(s);
  819. if (!comma)
  820. break;
  821. s = comma + 1;
  822. }
  823. }
  824. static char **new_args(void)
  825. {
  826. args = xrealloc_vector(args, 2, num_args);
  827. return &args[num_args++];
  828. }
  829. int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  830. int fsck_main(int argc UNUSED_PARAM, char **argv)
  831. {
  832. int i, status;
  833. /*int interactive;*/
  834. struct fs_info *fs;
  835. const char *fstab;
  836. char *tmp;
  837. char **devices;
  838. int num_devices;
  839. smallint opts_for_fsck;
  840. smallint doall;
  841. smallint notitle;
  842. /* we want wait() to be interruptible */
  843. signal_no_SA_RESTART_empty_mask(SIGINT, record_signo);
  844. signal_no_SA_RESTART_empty_mask(SIGTERM, record_signo);
  845. setbuf(stdout, NULL);
  846. opts_for_fsck = doall = notitle = 0;
  847. devices = NULL;
  848. num_devices = 0;
  849. new_args(); /* args[0] = NULL, will be replaced by fsck.<type> */
  850. /* instance_list = NULL; - in bss, so already zeroed */
  851. while (*++argv) {
  852. int j;
  853. int optpos;
  854. char *options;
  855. char *arg = *argv;
  856. /* "/dev/blk" or "/path" or "UUID=xxx" or "LABEL=xxx" */
  857. if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
  858. // FIXME: must check that arg is a blkdev, or resolve
  859. // "/path", "UUID=xxx" or "LABEL=xxx" into block device name
  860. // ("UUID=xxx"/"LABEL=xxx" can probably shifted to fsck.auto duties)
  861. devices = xrealloc_vector(devices, 2, num_devices);
  862. devices[num_devices++] = arg;
  863. continue;
  864. }
  865. if (arg[0] != '-' || opts_for_fsck) {
  866. *new_args() = arg;
  867. continue;
  868. }
  869. if (LONE_CHAR(arg + 1, '-')) { /* "--" ? */
  870. opts_for_fsck = 1;
  871. continue;
  872. }
  873. optpos = 0;
  874. options = NULL;
  875. for (j = 1; arg[j]; j++) {
  876. switch (arg[j]) {
  877. case 'A':
  878. doall = 1;
  879. break;
  880. #if DO_PROGRESS_INDICATOR
  881. case 'C':
  882. progress = 1;
  883. if (arg[++j]) { /* -Cn */
  884. progress_fd = xatoi_positive(&arg[j]);
  885. goto next_arg;
  886. }
  887. /* -C n */
  888. if (!*++argv)
  889. bb_show_usage();
  890. progress_fd = xatoi_positive(*argv);
  891. goto next_arg;
  892. #endif
  893. case 'V':
  894. verbose++;
  895. break;
  896. case 'N':
  897. noexecute = 1;
  898. break;
  899. case 'R':
  900. skip_root = 1;
  901. break;
  902. case 'T':
  903. notitle = 1;
  904. break;
  905. /* case 'M':
  906. like_mount = 1;
  907. break; */
  908. case 'P':
  909. parallel_root = 1;
  910. break;
  911. case 's':
  912. serialize = 1;
  913. break;
  914. case 't':
  915. if (fstype)
  916. bb_show_usage();
  917. if (arg[++j])
  918. tmp = &arg[j];
  919. else if (*++argv)
  920. tmp = *argv;
  921. else
  922. bb_show_usage();
  923. fstype = xstrdup(tmp);
  924. compile_fs_type(fstype);
  925. goto next_arg;
  926. case '?':
  927. bb_show_usage();
  928. break;
  929. default:
  930. optpos++;
  931. /* one extra for '\0' */
  932. options = xrealloc(options, optpos + 2);
  933. options[optpos] = arg[j];
  934. break;
  935. }
  936. }
  937. next_arg:
  938. if (optpos) {
  939. options[0] = '-';
  940. options[optpos + 1] = '\0';
  941. *new_args() = options;
  942. }
  943. }
  944. if (getenv("FSCK_FORCE_ALL_PARALLEL"))
  945. force_all_parallel = 1;
  946. tmp = getenv("FSCK_MAX_INST");
  947. if (tmp)
  948. max_running = xatoi(tmp);
  949. new_args(); /* args[num_args - 2] will be replaced by <device> */
  950. new_args(); /* args[num_args - 1] is the last, NULL element */
  951. if (!notitle)
  952. puts("fsck (busybox "BB_VER", "BB_BT")");
  953. /* Even plain "fsck /dev/hda1" needs fstab to get fs type,
  954. * so we are scanning it anyway */
  955. fstab = getenv("FSTAB_FILE");
  956. if (!fstab)
  957. fstab = "/etc/fstab";
  958. load_fs_info(fstab);
  959. /*interactive = (num_devices == 1) | serialize;*/
  960. if (num_devices == 0)
  961. /*interactive =*/ serialize = doall = 1;
  962. if (doall)
  963. return check_all();
  964. status = 0;
  965. for (i = 0; i < num_devices; i++) {
  966. if (bb_got_signal) {
  967. kill_all_if_got_signal();
  968. break;
  969. }
  970. fs = lookup(devices[i]);
  971. if (!fs)
  972. fs = create_fs_device(devices[i], "", "auto", NULL, -1);
  973. fsck_device(fs /*, interactive */);
  974. if (serialize
  975. || (max_running && (num_running >= max_running))
  976. ) {
  977. int exit_status = wait_one(0);
  978. if (exit_status >= 0)
  979. status |= exit_status;
  980. if (verbose > 1)
  981. puts("----------------------------------");
  982. }
  983. }
  984. status |= wait_many(FLAG_WAIT_ALL);
  985. return status;
  986. }