10f66f451Sopenharmony_ci/* fsck.c - check and repair a Linux filesystem 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2013 Sandeep Sharma <sandeep.jack2756@gmail.com> 40f66f451Sopenharmony_ci * Copyright 2013 Kyungwan Han <asura321@gmail.com> 50f66f451Sopenharmony_ci 60f66f451Sopenharmony_ciUSE_FSCK(NEWTOY(fsck, "?t:ANPRTVsC#", TOYFLAG_USR|TOYFLAG_BIN)) 70f66f451Sopenharmony_ci 80f66f451Sopenharmony_ciconfig FSCK 90f66f451Sopenharmony_ci bool "fsck" 100f66f451Sopenharmony_ci default n 110f66f451Sopenharmony_ci help 120f66f451Sopenharmony_ci usage: fsck [-ANPRTV] [-C FD] [-t FSTYPE] [FS_OPTS] [BLOCKDEV]... 130f66f451Sopenharmony_ci 140f66f451Sopenharmony_ci Check and repair filesystems 150f66f451Sopenharmony_ci 160f66f451Sopenharmony_ci -A Walk /etc/fstab and check all filesystems 170f66f451Sopenharmony_ci -N Don't execute, just show what would be done 180f66f451Sopenharmony_ci -P With -A, check filesystems in parallel 190f66f451Sopenharmony_ci -R With -A, skip the root filesystem 200f66f451Sopenharmony_ci -T Don't show title on startup 210f66f451Sopenharmony_ci -V Verbose 220f66f451Sopenharmony_ci -C n Write status information to specified file descriptor 230f66f451Sopenharmony_ci -t TYPE List of filesystem types to check 240f66f451Sopenharmony_ci 250f66f451Sopenharmony_ci*/ 260f66f451Sopenharmony_ci 270f66f451Sopenharmony_ci#define FOR_fsck 280f66f451Sopenharmony_ci#include "toys.h" 290f66f451Sopenharmony_ci#include <mntent.h> 300f66f451Sopenharmony_ci 310f66f451Sopenharmony_ci#define FLAG_WITHOUT_NO_PRFX 1 320f66f451Sopenharmony_ci#define FLAG_WITH_NO_PRFX 2 330f66f451Sopenharmony_ci#define FLAG_DONE 1 340f66f451Sopenharmony_ci 350f66f451Sopenharmony_ciGLOBALS( 360f66f451Sopenharmony_ci int fd_num; 370f66f451Sopenharmony_ci char *t_list; 380f66f451Sopenharmony_ci 390f66f451Sopenharmony_ci struct double_list *devices; 400f66f451Sopenharmony_ci char *arr_flag; 410f66f451Sopenharmony_ci char **arr_type; 420f66f451Sopenharmony_ci int negate; 430f66f451Sopenharmony_ci int sum_status; 440f66f451Sopenharmony_ci int nr_run; 450f66f451Sopenharmony_ci int sig_num; 460f66f451Sopenharmony_ci long max_nr_run; 470f66f451Sopenharmony_ci) 480f66f451Sopenharmony_ci 490f66f451Sopenharmony_cistruct f_sys_info { 500f66f451Sopenharmony_ci char *device, *mountpt, *type, *opts; 510f66f451Sopenharmony_ci int passno, flag; 520f66f451Sopenharmony_ci struct f_sys_info *next; 530f66f451Sopenharmony_ci}; 540f66f451Sopenharmony_ci 550f66f451Sopenharmony_cistruct child_list { 560f66f451Sopenharmony_ci struct child_list *next; 570f66f451Sopenharmony_ci pid_t pid; 580f66f451Sopenharmony_ci char *prog_name, *dev_name; 590f66f451Sopenharmony_ci}; 600f66f451Sopenharmony_ci 610f66f451Sopenharmony_cistatic struct f_sys_info *filesys_info = NULL; //fstab entry list 620f66f451Sopenharmony_cistatic struct child_list *c_list = NULL; //fsck.type child list. 630f66f451Sopenharmony_ci 640f66f451Sopenharmony_cistatic void kill_all(void) 650f66f451Sopenharmony_ci{ 660f66f451Sopenharmony_ci struct child_list *child; 670f66f451Sopenharmony_ci 680f66f451Sopenharmony_ci for (child = c_list; child; child = child->next) 690f66f451Sopenharmony_ci kill(child->pid, SIGTERM); 700f66f451Sopenharmony_ci _exit(0); 710f66f451Sopenharmony_ci} 720f66f451Sopenharmony_ci 730f66f451Sopenharmony_cistatic long strtol_range(char *str, int min, int max) 740f66f451Sopenharmony_ci{ 750f66f451Sopenharmony_ci char *endptr = NULL; 760f66f451Sopenharmony_ci errno = 0; 770f66f451Sopenharmony_ci long ret_value = strtol(str, &endptr, 10); 780f66f451Sopenharmony_ci 790f66f451Sopenharmony_ci if(errno) perror_exit("Invalid num %s", str); 800f66f451Sopenharmony_ci else if(endptr && (*endptr != '\0' || endptr == str)) 810f66f451Sopenharmony_ci perror_exit("Not a valid num %s", str); 820f66f451Sopenharmony_ci if(ret_value >= min && ret_value <= max) return ret_value; 830f66f451Sopenharmony_ci else perror_exit("Number %s is not in valid [%d-%d] Range", str, min, max); 840f66f451Sopenharmony_ci} 850f66f451Sopenharmony_ci 860f66f451Sopenharmony_ci//create fstab entries list. 870f66f451Sopenharmony_cistatic struct f_sys_info* create_db(struct mntent *f_info) 880f66f451Sopenharmony_ci{ 890f66f451Sopenharmony_ci struct f_sys_info *temp = filesys_info; 900f66f451Sopenharmony_ci if (temp) { 910f66f451Sopenharmony_ci while (temp->next) temp = temp->next; 920f66f451Sopenharmony_ci temp->next = xzalloc(sizeof(struct f_sys_info)); 930f66f451Sopenharmony_ci temp = temp->next; 940f66f451Sopenharmony_ci } else filesys_info = temp = xzalloc(sizeof(struct f_sys_info)); 950f66f451Sopenharmony_ci 960f66f451Sopenharmony_ci temp->device = xstrdup(f_info->mnt_fsname); 970f66f451Sopenharmony_ci temp->mountpt = xstrdup(f_info->mnt_dir); 980f66f451Sopenharmony_ci if (strchr(f_info->mnt_type, ',')) temp->type = xstrdup("auto"); 990f66f451Sopenharmony_ci else temp->type = xstrdup(f_info->mnt_type); 1000f66f451Sopenharmony_ci temp->opts = xstrdup(f_info->mnt_opts); 1010f66f451Sopenharmony_ci temp->passno = f_info->mnt_passno; 1020f66f451Sopenharmony_ci return temp; 1030f66f451Sopenharmony_ci} 1040f66f451Sopenharmony_ci 1050f66f451Sopenharmony_ci//is we have 'no' or ! before type. 1060f66f451Sopenharmony_cistatic int is_no_prefix(char **p) 1070f66f451Sopenharmony_ci{ 1080f66f451Sopenharmony_ci int no = 0; 1090f66f451Sopenharmony_ci 1100f66f451Sopenharmony_ci if ((*p[0] == 'n' && *(*p + 1) == 'o')) no = 2; 1110f66f451Sopenharmony_ci else if (*p[0] == '!') no = 1; 1120f66f451Sopenharmony_ci *p += no; 1130f66f451Sopenharmony_ci return ((no) ? 1 :0); 1140f66f451Sopenharmony_ci} 1150f66f451Sopenharmony_ci 1160f66f451Sopenharmony_cistatic void fix_tlist(void) 1170f66f451Sopenharmony_ci{ 1180f66f451Sopenharmony_ci char *p, *s = TT.t_list; 1190f66f451Sopenharmony_ci int n = 1, no; 1200f66f451Sopenharmony_ci 1210f66f451Sopenharmony_ci while ((s = strchr(s, ','))) { 1220f66f451Sopenharmony_ci s++; 1230f66f451Sopenharmony_ci n++; 1240f66f451Sopenharmony_ci } 1250f66f451Sopenharmony_ci 1260f66f451Sopenharmony_ci TT.arr_flag = xzalloc(n + 1); 1270f66f451Sopenharmony_ci TT.arr_type = xzalloc((n + 1) * sizeof(char *)); 1280f66f451Sopenharmony_ci s = TT.t_list; 1290f66f451Sopenharmony_ci n = 0; 1300f66f451Sopenharmony_ci while ((p = strsep(&s, ","))) { 1310f66f451Sopenharmony_ci no = is_no_prefix(&p); 1320f66f451Sopenharmony_ci if (!strcmp(p, "loop")) { 1330f66f451Sopenharmony_ci TT.arr_flag[n] = no ? FLAG_WITH_NO_PRFX :FLAG_WITHOUT_NO_PRFX; 1340f66f451Sopenharmony_ci TT.negate = no; 1350f66f451Sopenharmony_ci } else if (!strncmp(p, "opts=", 5)) { 1360f66f451Sopenharmony_ci p+=5; 1370f66f451Sopenharmony_ci TT.arr_flag[n] = is_no_prefix(&p) ?FLAG_WITH_NO_PRFX :FLAG_WITHOUT_NO_PRFX; 1380f66f451Sopenharmony_ci TT.negate = no; 1390f66f451Sopenharmony_ci } else { 1400f66f451Sopenharmony_ci if (!n) TT.negate = no; 1410f66f451Sopenharmony_ci if (n && TT.negate != no) error_exit("either all or none of the filesystem" 1420f66f451Sopenharmony_ci " types passed to -t must be prefixed with 'no' or '!'"); 1430f66f451Sopenharmony_ci } 1440f66f451Sopenharmony_ci TT.arr_type[n++] = p; 1450f66f451Sopenharmony_ci } 1460f66f451Sopenharmony_ci} 1470f66f451Sopenharmony_ci 1480f66f451Sopenharmony_ci//ignore these types... 1490f66f451Sopenharmony_cistatic int ignore_type(char *type) 1500f66f451Sopenharmony_ci{ 1510f66f451Sopenharmony_ci int i = 0; 1520f66f451Sopenharmony_ci char *str; 1530f66f451Sopenharmony_ci char *ignored_types[] = { 1540f66f451Sopenharmony_ci "ignore","iso9660", "nfs","proc", 1550f66f451Sopenharmony_ci "sw","swap", "tmpfs","devpts",NULL 1560f66f451Sopenharmony_ci }; 1570f66f451Sopenharmony_ci while ((str = ignored_types[i++])) { 1580f66f451Sopenharmony_ci if (!strcmp(str, type)) return 1; 1590f66f451Sopenharmony_ci } 1600f66f451Sopenharmony_ci return 0; 1610f66f451Sopenharmony_ci} 1620f66f451Sopenharmony_ci 1630f66f451Sopenharmony_ci// return true if has to ignore the filesystem. 1640f66f451Sopenharmony_cistatic int to_be_ignored(struct f_sys_info *finfo) 1650f66f451Sopenharmony_ci{ 1660f66f451Sopenharmony_ci int i, ret = 0, type_present = 0; 1670f66f451Sopenharmony_ci 1680f66f451Sopenharmony_ci if (!finfo->passno) return 1; //Ignore with pass num = 0 1690f66f451Sopenharmony_ci if (TT.arr_type) { 1700f66f451Sopenharmony_ci for (i = 0; TT.arr_type[i]; i++) { 1710f66f451Sopenharmony_ci if (!TT.arr_flag[i]) { //it is type of filesys. 1720f66f451Sopenharmony_ci type_present = 2; 1730f66f451Sopenharmony_ci if (!strcmp(TT.arr_type[i], finfo->type)) ret = 0; 1740f66f451Sopenharmony_ci else ret = 1; 1750f66f451Sopenharmony_ci } else if (TT.arr_flag[i] == FLAG_WITH_NO_PRFX) { //it is option of filesys 1760f66f451Sopenharmony_ci if (hasmntopt((const struct mntent *)finfo, TT.arr_type[i])) return 1; 1770f66f451Sopenharmony_ci } else { //FLAG_WITHOUT_NO_PRFX 1780f66f451Sopenharmony_ci if (!hasmntopt((const struct mntent *)finfo, TT.arr_type[i])) return 1; 1790f66f451Sopenharmony_ci } 1800f66f451Sopenharmony_ci } 1810f66f451Sopenharmony_ci } 1820f66f451Sopenharmony_ci if (ignore_type(finfo->type)) return 1; 1830f66f451Sopenharmony_ci if (TT.arr_type && type_present != 2) return 0; 1840f66f451Sopenharmony_ci return ((TT.negate) ? !ret : ret); 1850f66f451Sopenharmony_ci} 1860f66f451Sopenharmony_ci 1870f66f451Sopenharmony_ci// find type and execute corresponding fsck.type prog. 1880f66f451Sopenharmony_cistatic void do_fsck(struct f_sys_info *finfo) 1890f66f451Sopenharmony_ci{ 1900f66f451Sopenharmony_ci struct child_list *child; 1910f66f451Sopenharmony_ci char **args; 1920f66f451Sopenharmony_ci char *type; 1930f66f451Sopenharmony_ci pid_t pid; 1940f66f451Sopenharmony_ci int i = 1, j = 0; 1950f66f451Sopenharmony_ci 1960f66f451Sopenharmony_ci if (strcmp(finfo->type, "auto")) type = finfo->type; 1970f66f451Sopenharmony_ci else if (TT.t_list && (TT.t_list[0] != 'n' || TT.t_list[1] != 'o' || TT.t_list[0] != '!') 1980f66f451Sopenharmony_ci && strncmp(TT.t_list, "opts=", 5) && strncmp(TT.t_list , "loop", 4) 1990f66f451Sopenharmony_ci && !TT.arr_type[1]) type = TT.t_list; //one file sys at cmdline 2000f66f451Sopenharmony_ci else type = "auto"; 2010f66f451Sopenharmony_ci 2020f66f451Sopenharmony_ci args = xzalloc((toys.optc + 2 + 1 + 1) * sizeof(char*)); //+1, for NULL, +1 if -C 2030f66f451Sopenharmony_ci args[0] = xmprintf("fsck.%s", type); 2040f66f451Sopenharmony_ci 2050f66f451Sopenharmony_ci if(toys.optflags & FLAG_C) args[i++] = xmprintf("%s %d","-C", TT.fd_num); 2060f66f451Sopenharmony_ci while(toys.optargs[j]) { 2070f66f451Sopenharmony_ci if(*toys.optargs[j]) args[i++] = xstrdup(toys.optargs[j]); 2080f66f451Sopenharmony_ci j++; 2090f66f451Sopenharmony_ci } 2100f66f451Sopenharmony_ci args[i] = finfo->device; 2110f66f451Sopenharmony_ci 2120f66f451Sopenharmony_ci TT.nr_run++; 2130f66f451Sopenharmony_ci if ((toys.optflags & FLAG_V) || (toys.optflags & FLAG_N)) { 2140f66f451Sopenharmony_ci printf("[%s (%d) -- %s]", args[0], TT.nr_run, 2150f66f451Sopenharmony_ci finfo->mountpt ? finfo->mountpt : finfo->device); 2160f66f451Sopenharmony_ci for (i = 0; args[i]; i++) xprintf(" %s", args[i]); 2170f66f451Sopenharmony_ci xputc('\n'); 2180f66f451Sopenharmony_ci } 2190f66f451Sopenharmony_ci 2200f66f451Sopenharmony_ci if (toys.optflags & FLAG_N) { 2210f66f451Sopenharmony_ci for (j=0;j<i;j++) free(args[i]); 2220f66f451Sopenharmony_ci free(args); 2230f66f451Sopenharmony_ci return; 2240f66f451Sopenharmony_ci } else { 2250f66f451Sopenharmony_ci if ((pid = fork()) < 0) { 2260f66f451Sopenharmony_ci perror_msg_raw(*args); 2270f66f451Sopenharmony_ci for (j=0;j<i;j++) free(args[i]); 2280f66f451Sopenharmony_ci free(args); 2290f66f451Sopenharmony_ci return; 2300f66f451Sopenharmony_ci } 2310f66f451Sopenharmony_ci if (!pid) xexec(args); //child, executes fsck.type 2320f66f451Sopenharmony_ci } 2330f66f451Sopenharmony_ci 2340f66f451Sopenharmony_ci child = xzalloc(sizeof(struct child_list)); //Parent, add to child list. 2350f66f451Sopenharmony_ci child->dev_name = xstrdup(finfo->device); 2360f66f451Sopenharmony_ci child->prog_name = args[0]; 2370f66f451Sopenharmony_ci child->pid = pid; 2380f66f451Sopenharmony_ci 2390f66f451Sopenharmony_ci if (c_list) { 2400f66f451Sopenharmony_ci child->next = c_list; 2410f66f451Sopenharmony_ci c_list = child; 2420f66f451Sopenharmony_ci } else { 2430f66f451Sopenharmony_ci c_list = child; 2440f66f451Sopenharmony_ci child->next =NULL; 2450f66f451Sopenharmony_ci } 2460f66f451Sopenharmony_ci} 2470f66f451Sopenharmony_ci 2480f66f451Sopenharmony_ci// for_all = 1; wait for all child to exit 2490f66f451Sopenharmony_ci// for_all = 0; wait for any one to exit 2500f66f451Sopenharmony_cistatic int wait_for(int for_all) 2510f66f451Sopenharmony_ci{ 2520f66f451Sopenharmony_ci pid_t pid; 2530f66f451Sopenharmony_ci int status = 0, child_exited; 2540f66f451Sopenharmony_ci struct child_list *prev, *temp; 2550f66f451Sopenharmony_ci 2560f66f451Sopenharmony_ci errno = 0; 2570f66f451Sopenharmony_ci if (!c_list) return 0; 2580f66f451Sopenharmony_ci while ((pid = wait(&status))) { 2590f66f451Sopenharmony_ci temp = c_list; 2600f66f451Sopenharmony_ci prev = temp; 2610f66f451Sopenharmony_ci if (TT.sig_num) kill_all(); 2620f66f451Sopenharmony_ci child_exited = 0; 2630f66f451Sopenharmony_ci if (pid < 0) { 2640f66f451Sopenharmony_ci if (errno == EINTR) continue; 2650f66f451Sopenharmony_ci else if (errno == ECHILD) break; //No child to wait, break and return status. 2660f66f451Sopenharmony_ci else perror_exit("option arg Invalid\n"); //paranoid. 2670f66f451Sopenharmony_ci } 2680f66f451Sopenharmony_ci while (temp) { 2690f66f451Sopenharmony_ci if (temp->pid == pid) { 2700f66f451Sopenharmony_ci child_exited = 1; 2710f66f451Sopenharmony_ci break; 2720f66f451Sopenharmony_ci } 2730f66f451Sopenharmony_ci prev = temp; 2740f66f451Sopenharmony_ci temp = temp->next; 2750f66f451Sopenharmony_ci } 2760f66f451Sopenharmony_ci if (child_exited) { 2770f66f451Sopenharmony_ci if (WIFEXITED(status)) TT.sum_status |= WEXITSTATUS(status); 2780f66f451Sopenharmony_ci else if (WIFSIGNALED(status)) { 2790f66f451Sopenharmony_ci TT.sum_status |= 4; //Uncorrected. 2800f66f451Sopenharmony_ci if (WTERMSIG(status) != SIGINT) 2810f66f451Sopenharmony_ci perror_msg("child Term. by sig: %d\n",(WTERMSIG(status))); 2820f66f451Sopenharmony_ci TT.sum_status |= 8; //Operatinal error 2830f66f451Sopenharmony_ci } else { 2840f66f451Sopenharmony_ci TT.sum_status |= 4; //Uncorrected. 2850f66f451Sopenharmony_ci perror_msg("%s %s: status is %x, should never happen\n", 2860f66f451Sopenharmony_ci temp->prog_name, temp->dev_name, status); 2870f66f451Sopenharmony_ci } 2880f66f451Sopenharmony_ci TT.nr_run--; 2890f66f451Sopenharmony_ci if (prev == temp) c_list = c_list->next; //first node 2900f66f451Sopenharmony_ci else prev->next = temp->next; 2910f66f451Sopenharmony_ci free(temp->prog_name); 2920f66f451Sopenharmony_ci free(temp->dev_name); 2930f66f451Sopenharmony_ci free(temp); 2940f66f451Sopenharmony_ci if (!for_all) break; 2950f66f451Sopenharmony_ci } 2960f66f451Sopenharmony_ci } 2970f66f451Sopenharmony_ci return TT.sum_status; 2980f66f451Sopenharmony_ci} 2990f66f451Sopenharmony_ci 3000f66f451Sopenharmony_ci//scan all the fstab entries or -t matches with fstab. 3010f66f451Sopenharmony_cistatic int scan_all(void) 3020f66f451Sopenharmony_ci{ 3030f66f451Sopenharmony_ci struct f_sys_info *finfo = filesys_info; 3040f66f451Sopenharmony_ci int ret = 0, passno; 3050f66f451Sopenharmony_ci 3060f66f451Sopenharmony_ci if (toys.optflags & FLAG_V) xprintf("Checking all filesystem\n"); 3070f66f451Sopenharmony_ci while (finfo) { 3080f66f451Sopenharmony_ci if (to_be_ignored(finfo)) finfo->flag |= FLAG_DONE; 3090f66f451Sopenharmony_ci finfo = finfo->next; 3100f66f451Sopenharmony_ci } 3110f66f451Sopenharmony_ci finfo = filesys_info; 3120f66f451Sopenharmony_ci 3130f66f451Sopenharmony_ci if (!(toys.optflags & FLAG_P)) { 3140f66f451Sopenharmony_ci while (finfo) { 3150f66f451Sopenharmony_ci if (!strcmp(finfo->mountpt, "/")) { // man says: check / in parallel with others if -P is absent. 3160f66f451Sopenharmony_ci if ((toys.optflags & FLAG_R) || to_be_ignored(finfo)) { 3170f66f451Sopenharmony_ci finfo->flag |= FLAG_DONE; 3180f66f451Sopenharmony_ci break; 3190f66f451Sopenharmony_ci } else { 3200f66f451Sopenharmony_ci do_fsck(finfo); 3210f66f451Sopenharmony_ci finfo->flag |= FLAG_DONE; 3220f66f451Sopenharmony_ci if (TT.sig_num) kill_all(); 3230f66f451Sopenharmony_ci if ((ret |= wait_for(1)) > 4) return ret; //destruction in filesys. 3240f66f451Sopenharmony_ci break; 3250f66f451Sopenharmony_ci } 3260f66f451Sopenharmony_ci } 3270f66f451Sopenharmony_ci finfo = finfo->next; 3280f66f451Sopenharmony_ci } 3290f66f451Sopenharmony_ci } 3300f66f451Sopenharmony_ci if (toys.optflags & FLAG_R) { // with -PR we choose to skip root. 3310f66f451Sopenharmony_ci for (finfo = filesys_info; finfo; finfo = finfo->next) { 3320f66f451Sopenharmony_ci if(!strcmp(finfo->mountpt, "/")) finfo->flag |= FLAG_DONE; 3330f66f451Sopenharmony_ci } 3340f66f451Sopenharmony_ci } 3350f66f451Sopenharmony_ci passno = 1; 3360f66f451Sopenharmony_ci while (1) { 3370f66f451Sopenharmony_ci for (finfo = filesys_info; finfo; finfo = finfo->next) 3380f66f451Sopenharmony_ci if (!finfo->flag) break; 3390f66f451Sopenharmony_ci if (!finfo) break; 3400f66f451Sopenharmony_ci 3410f66f451Sopenharmony_ci for (finfo = filesys_info; finfo; finfo = finfo->next) { 3420f66f451Sopenharmony_ci if (finfo->flag) continue; 3430f66f451Sopenharmony_ci if (finfo->passno == passno) { 3440f66f451Sopenharmony_ci do_fsck(finfo); 3450f66f451Sopenharmony_ci finfo->flag |= FLAG_DONE; 3460f66f451Sopenharmony_ci if ((toys.optflags & FLAG_s) || (TT.nr_run 3470f66f451Sopenharmony_ci && (TT.nr_run >= TT.max_nr_run))) ret |= wait_for(0); 3480f66f451Sopenharmony_ci } 3490f66f451Sopenharmony_ci } 3500f66f451Sopenharmony_ci if (TT.sig_num) kill_all(); 3510f66f451Sopenharmony_ci ret |= wait_for(1); 3520f66f451Sopenharmony_ci passno++; 3530f66f451Sopenharmony_ci } 3540f66f451Sopenharmony_ci return ret; 3550f66f451Sopenharmony_ci} 3560f66f451Sopenharmony_ci 3570f66f451Sopenharmony_civoid record_sig_num(int sig) 3580f66f451Sopenharmony_ci{ 3590f66f451Sopenharmony_ci TT.sig_num = sig; 3600f66f451Sopenharmony_ci} 3610f66f451Sopenharmony_ci 3620f66f451Sopenharmony_civoid fsck_main(void) 3630f66f451Sopenharmony_ci{ 3640f66f451Sopenharmony_ci struct mntent mt; 3650f66f451Sopenharmony_ci struct double_list *dev; 3660f66f451Sopenharmony_ci struct f_sys_info *finfo; 3670f66f451Sopenharmony_ci FILE *fp; 3680f66f451Sopenharmony_ci char *tmp, **arg = toys.optargs; 3690f66f451Sopenharmony_ci 3700f66f451Sopenharmony_ci sigatexit(record_sig_num); 3710f66f451Sopenharmony_ci while (*arg) { 3720f66f451Sopenharmony_ci if ((**arg == '/') || strchr(*arg, '=')) { 3730f66f451Sopenharmony_ci dlist_add(&TT.devices, xstrdup(*arg)); 3740f66f451Sopenharmony_ci **arg = '\0'; 3750f66f451Sopenharmony_ci } 3760f66f451Sopenharmony_ci arg++; 3770f66f451Sopenharmony_ci } 3780f66f451Sopenharmony_ci if (toys.optflags & FLAG_t) fix_tlist(); 3790f66f451Sopenharmony_ci if (!(tmp = getenv("FSTAB_FILE"))) tmp = "/etc/fstab"; 3800f66f451Sopenharmony_ci if (!(fp = setmntent(tmp, "r"))) perror_exit("setmntent failed:"); 3810f66f451Sopenharmony_ci while (getmntent_r(fp, &mt, toybuf, 4096)) create_db(&mt); 3820f66f451Sopenharmony_ci endmntent(fp); 3830f66f451Sopenharmony_ci 3840f66f451Sopenharmony_ci if (!(toys.optflags & FLAG_T)) xprintf("fsck ----- (Toybox)\n"); 3850f66f451Sopenharmony_ci 3860f66f451Sopenharmony_ci if ((tmp = getenv("FSCK_MAX_INST"))) 3870f66f451Sopenharmony_ci TT.max_nr_run = strtol_range(tmp, 0, INT_MAX); 3880f66f451Sopenharmony_ci if (!TT.devices || (toys.optflags & FLAG_A)) { 3890f66f451Sopenharmony_ci toys.exitval = scan_all(); 3900f66f451Sopenharmony_ci if (CFG_TOYBOX_FREE) goto free_all; 3910f66f451Sopenharmony_ci return; //if CFG_TOYBOX_FREE is not set, exit. 3920f66f451Sopenharmony_ci } 3930f66f451Sopenharmony_ci 3940f66f451Sopenharmony_ci dev = TT.devices; 3950f66f451Sopenharmony_ci dev->prev->next = NULL; //break double list to traverse. 3960f66f451Sopenharmony_ci for (; dev; dev = dev->next) { 3970f66f451Sopenharmony_ci for (finfo = filesys_info; finfo; finfo = finfo->next) 3980f66f451Sopenharmony_ci if (!strcmp(finfo->device, dev->data) 3990f66f451Sopenharmony_ci || !strcmp(finfo->mountpt, dev->data)) break; 4000f66f451Sopenharmony_ci if (!finfo) { //if not present, fill def values. 4010f66f451Sopenharmony_ci mt.mnt_fsname = dev->data; 4020f66f451Sopenharmony_ci mt.mnt_dir = ""; 4030f66f451Sopenharmony_ci mt.mnt_type = "auto"; 4040f66f451Sopenharmony_ci mt.mnt_opts = ""; 4050f66f451Sopenharmony_ci mt.mnt_passno = -1; 4060f66f451Sopenharmony_ci finfo = create_db(&mt); 4070f66f451Sopenharmony_ci } 4080f66f451Sopenharmony_ci do_fsck(finfo); 4090f66f451Sopenharmony_ci finfo->flag |= FLAG_DONE; 4100f66f451Sopenharmony_ci if ((toys.optflags & FLAG_s) || (TT.nr_run && (TT.nr_run >= TT.max_nr_run))) 4110f66f451Sopenharmony_ci toys.exitval |= wait_for(0); 4120f66f451Sopenharmony_ci } 4130f66f451Sopenharmony_ci if (TT.sig_num) kill_all(); 4140f66f451Sopenharmony_ci toys.exitval |= wait_for(1); 4150f66f451Sopenharmony_ci finfo = filesys_info; 4160f66f451Sopenharmony_ci 4170f66f451Sopenharmony_cifree_all: 4180f66f451Sopenharmony_ci if (CFG_TOYBOX_FREE) { 4190f66f451Sopenharmony_ci struct f_sys_info *finfo, *temp; 4200f66f451Sopenharmony_ci 4210f66f451Sopenharmony_ci llist_traverse(TT.devices, llist_free_double); 4220f66f451Sopenharmony_ci free(TT.arr_type); 4230f66f451Sopenharmony_ci free(TT.arr_flag); 4240f66f451Sopenharmony_ci for (finfo = filesys_info; finfo;) { 4250f66f451Sopenharmony_ci temp = finfo->next; 4260f66f451Sopenharmony_ci free(finfo->device); 4270f66f451Sopenharmony_ci free(finfo->mountpt); 4280f66f451Sopenharmony_ci free(finfo->type); 4290f66f451Sopenharmony_ci free(finfo->opts); 4300f66f451Sopenharmony_ci free(finfo); 4310f66f451Sopenharmony_ci finfo = temp; 4320f66f451Sopenharmony_ci } 4330f66f451Sopenharmony_ci } 4340f66f451Sopenharmony_ci} 435