fsck.c 24 KB

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