⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsck.c

📁 busybox最新版的源码:学习和应用的好东东,多的不说了,大家看后再说吧
💻 C
📖 第 1 页 / 共 2 页
字号:
		goto ret_inst;	}	/*	 * gcc -Wall fails saving throw against stupidity	 * (inst and prev are thought to be uninitialized variables)	 */	inst = prev = NULL;	do {		pid = waitpid(-1, &status, flags);		if (cancel_requested && !kill_sent) {			kill_all(SIGTERM);			kill_sent++;		}		if ((pid == 0) && (flags & WNOHANG))			return NULL;		if (pid < 0) {			if ((errno == EINTR) || (errno == EAGAIN))				continue;			if (errno == ECHILD) {				bb_error_msg("wait: no more child process?!?");				return NULL;			}			perror("wait");			continue;		}		for (prev = 0, inst = instance_list;		     inst;		     prev = inst, inst = inst->next) {			if (inst->pid == pid)				break;		}	} while (!inst);	if (WIFEXITED(status))		status = WEXITSTATUS(status);	else if (WIFSIGNALED(status)) {		sig = WTERMSIG(status);		if (sig == SIGINT) {			status = EXIT_UNCORRECTED;		} else {			printf("Warning... %s for device %s exited "			       "with signal %d.\n",			       inst->prog, inst->device, sig);			status = EXIT_ERROR;		}	} else {		printf("%s %s: status is %x, should never happen.\n",		       inst->prog, inst->device, status);		status = EXIT_ERROR;	}	inst->exit_status = status;	if (progress && (inst->flags & FLAG_PROGRESS) &&	    !progress_active()) {		for (inst2 = instance_list; inst2; inst2 = inst2->next) {			if (inst2->flags & FLAG_DONE)				continue;			if (strcmp(inst2->type, "ext2") &&			    strcmp(inst2->type, "ext3"))				continue;			/*			 * If we've just started the fsck, wait a tiny			 * bit before sending the kill, to give it			 * time to set up the signal handler			 */			if (inst2->start_time < time(0)+2) {				if (fork() == 0) {					sleep(1);					kill(inst2->pid, SIGUSR1);					exit(0);				}			} else				kill(inst2->pid, SIGUSR1);			inst2->flags |= FLAG_PROGRESS;			break;		}	}ret_inst:	if (prev)		prev->next = inst->next;	else		instance_list = inst->next;	if (verbose > 1)		printf("Finished with %s (exit status %d)\n",		       inst->device, inst->exit_status);	num_running--;	return inst;}#define FLAG_WAIT_ALL           0#define FLAG_WAIT_ATLEAST_ONE   1/* * Wait until all executing child processes have exited; return the * logical OR of all of their exit code values. */static int wait_many(int flags){	struct fsck_instance *inst;	int     global_status = 0;	int     wait_flags = 0;	while ((inst = wait_one(wait_flags))) {		global_status |= inst->exit_status;		free_instance(inst);#ifdef RANDOM_DEBUG		if (noexecute && (flags & WNOHANG) && !(random() % 3))			break;#endif		if (flags & FLAG_WAIT_ATLEAST_ONE)			wait_flags = WNOHANG;	}	return global_status;}/* * Run the fsck program on a particular device * * If the type is specified using -t, and it isn't prefixed with "no" * (as in "noext2") and only one filesystem type is specified, then * use that type regardless of what is specified in /etc/fstab. * * If the type isn't specified by the user, then use either the type * specified in /etc/fstab, or DEFAULT_FSTYPE. */static void fsck_device(struct fs_info *fs, int interactive){	const char *type;	int retval;	interpret_type(fs);	if (strcmp(fs->type, "auto") != 0)		type = fs->type;	else if (fstype && strncmp(fstype, "no", 2) &&	    strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) &&	    !strchr(fstype, ','))		type = fstype;	else		type = DEFAULT_FSTYPE;	num_running++;	retval = execute(type, fs->device, fs->mountpt, interactive);	if (retval) {		bb_error_msg("error %d while executing fsck.%s for %s",						retval, type, fs->device);		num_running--;	}}/* * Deal with the fsck -t argument. */struct fs_type_compile {	char **list;	int *type;	int  negate;} fs_type_compiled;#define FS_TYPE_NORMAL  0#define FS_TYPE_OPT     1#define FS_TYPE_NEGOPT  2static const char fs_type_syntax_error[] ="Either all or none of the filesystem types passed to -t must be prefixed\n"   "with 'no' or '!'.";static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp){	char    *cp, *list, *s;	int     num = 2;	int     negate, first_negate = 1;	if (fs_type) {		for (cp=fs_type; *cp; cp++) {			if (*cp == ',')				num++;		}	}	cmp->list = xzalloc(num * sizeof(char *));	cmp->type = xzalloc(num * sizeof(int));	cmp->negate = 0;	if (!fs_type)		return;	list = string_copy(fs_type);	num = 0;	s = strtok(list, ",");	while(s) {		negate = 0;		if (strncmp(s, "no", 2) == 0) {			s += 2;			negate = 1;		} else if (*s == '!') {			s++;			negate = 1;		}		if (strcmp(s, "loop") == 0)			/* loop is really short-hand for opts=loop */			goto loop_special_case;		else if (strncmp(s, "opts=", 5) == 0) {			s += 5;		loop_special_case:			cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT;		} else {			if (first_negate) {				cmp->negate = negate;				first_negate = 0;			}			if ((negate && !cmp->negate) ||			    (!negate && cmp->negate)) {				bb_error_msg_and_die("%s", fs_type_syntax_error);			}		}		cmp->list[num++] = string_copy(s);		s = strtok(NULL, ",");	}	free(list);}/* * This function returns true if a particular option appears in a * comma-delimited options list */static int opt_in_list(char *opt, char *optlist){	char    *list, *s;	if (!optlist)		return 0;	list = string_copy(optlist);	s = strtok(list, ",");	while(s) {		if (strcmp(s, opt) == 0) {			free(list);			return 1;		}		s = strtok(NULL, ",");	}	free(list);	return 0;}/* See if the filesystem matches the criteria given by the -t option */static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp){	int n, ret = 0, checked_type = 0;	char *cp;	if (cmp->list == 0 || cmp->list[0] == 0)		return 1;	for (n=0; (cp = cmp->list[n]); n++) {		switch (cmp->type[n]) {		case FS_TYPE_NORMAL:			checked_type++;			if (strcmp(cp, fs->type) == 0) {				ret = 1;			}			break;		case FS_TYPE_NEGOPT:			if (opt_in_list(cp, fs->opts))				return 0;			break;		case FS_TYPE_OPT:			if (!opt_in_list(cp, fs->opts))				return 0;			break;		}	}	if (checked_type == 0)		return 1;	return (cmp->negate ? !ret : ret);}/* Check if we should ignore this filesystem. */static int ignore(struct fs_info *fs){	int wanted;	char *s;	/*	 * If the pass number is 0, ignore it.	 */	if (fs->passno == 0)		return 1;	interpret_type(fs);	/*	 * If a specific fstype is specified, and it doesn't match,	 * ignore it.	 */	if (!fs_match(fs, &fs_type_compiled)) return 1;	/* Are we ignoring this type? */	if (index_in_str_array(ignored_types, fs->type) >= 0)		return 1;	/* Do we really really want to check this fs? */	wanted = index_in_str_array(really_wanted, fs->type) >= 0;	/* See if the <fsck.fs> program is available. */	s = find_fsck(fs->type);	if (s == NULL) {		if (wanted)			bb_error_msg("cannot check %s: fsck.%s not found",				fs->device, fs->type);		return 1;	}	free(s);	/* We can and want to check this file system type. */	return 0;}/* * Returns TRUE if a partition on the same disk is already being * checked. */static int device_already_active(char *device){	struct fsck_instance *inst;	char *base;	if (force_all_parallel)		return 0;#ifdef BASE_MD	/* Don't check a soft raid disk with any other disk */	if (instance_list &&	    (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) ||	     !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)))		return 1;#endif	base = base_device(device);	/*	 * If we don't know the base device, assume that the device is	 * already active if there are any fsck instances running.	 */	if (!base)		return (instance_list != 0);	for (inst = instance_list; inst; inst = inst->next) {		if (!inst->base_device || !strcmp(base, inst->base_device)) {			free(base);			return 1;		}	}	free(base);	return 0;}/* Check all file systems, using the /etc/fstab table. */static int check_all(void){	struct fs_info *fs = NULL;	int status = EXIT_OK;	int not_done_yet = 1;	int passno = 1;	int pass_done;	if (verbose)		fputs("Checking all file systems.\n", stdout);	/*	 * Do an initial scan over the filesystem; mark filesystems	 * which should be ignored as done, and resolve any "auto"	 * filesystem types (done as a side-effect of calling ignore()).	 */	for (fs = filesys_info; fs; fs = fs->next) {		if (ignore(fs))			fs->flags |= FLAG_DONE;	}	/*	 * Find and check the root filesystem.	 */	if (!parallel_root) {		for (fs = filesys_info; fs; fs = fs->next) {			if (LONE_CHAR(fs->mountpt, '/'))				break;		}		if (fs) {			if (!skip_root && !ignore(fs)) {				fsck_device(fs, 1);				status |= wait_many(FLAG_WAIT_ALL);				if (status > EXIT_NONDESTRUCT)					return status;			}			fs->flags |= FLAG_DONE;		}	}	/*	 * This is for the bone-headed user who enters the root	 * filesystem twice.  Skip root will skep all root entries.	 */	if (skip_root)		for (fs = filesys_info; fs; fs = fs->next)			if (LONE_CHAR(fs->mountpt, '/'))				fs->flags |= FLAG_DONE;	while (not_done_yet) {		not_done_yet = 0;		pass_done = 1;		for (fs = filesys_info; fs; fs = fs->next) {			if (cancel_requested)				break;			if (fs->flags & FLAG_DONE)				continue;			/*			 * If the filesystem's pass number is higher			 * than the current pass number, then we don't			 * do it yet.			 */			if (fs->passno > passno) {				not_done_yet++;				continue;			}			/*			 * If a filesystem on a particular device has			 * already been spawned, then we need to defer			 * this to another pass.			 */			if (device_already_active(fs->device)) {				pass_done = 0;				continue;			}			/*			 * Spawn off the fsck process			 */			fsck_device(fs, serialize);			fs->flags |= FLAG_DONE;			/*			 * Only do one filesystem at a time, or if we			 * have a limit on the number of fsck's extant			 * at one time, apply that limit.			 */			if (serialize ||			    (max_running && (num_running >= max_running))) {				pass_done = 0;				break;			}		}		if (cancel_requested)			break;		if (verbose > 1)			printf("--waiting-- (pass %d)\n", passno);		status |= wait_many(pass_done ? FLAG_WAIT_ALL :				    FLAG_WAIT_ATLEAST_ONE);		if (pass_done) {			if (verbose > 1)				printf("----------------------------------\n");			passno++;		} else			not_done_yet++;	}	if (cancel_requested && !kill_sent) {		kill_all(SIGTERM);		kill_sent++;	}	status |= wait_many(FLAG_WAIT_ATLEAST_ONE);	return status;}static void signal_cancel(int sig FSCK_ATTR((unused))){	cancel_requested++;}static void PRS(int argc, char **argv){	int     i, j;	char    *arg, *dev, *tmp = 0;	char    options[128];	int     opt = 0;	int     opts_for_fsck = 0;	struct sigaction        sa;	/*	 * Set up signal action	 */	memset(&sa, 0, sizeof(struct sigaction));	sa.sa_handler = signal_cancel;	sigaction(SIGINT, &sa, 0);	sigaction(SIGTERM, &sa, 0);	num_devices = 0;	num_args = 0;	instance_list = 0;	for (i=1; i < argc; i++) {		arg = argv[i];		if (!arg)			continue;		if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {			if (num_devices >= MAX_DEVICES) {				bb_error_msg_and_die("too many devices");			}			dev = blkid_get_devname(cache, arg, NULL);			if (!dev && strchr(arg, '=')) {				/*				 * Check to see if we failed because				 * /proc/partitions isn't found.				 */				if (access("/proc/partitions", R_OK) < 0) {					bb_perror_msg_and_die("cannot open /proc/partitions "							"(is /proc mounted?)");				}				/*				 * Check to see if this is because				 * we're not running as root				 */				if (geteuid())					bb_error_msg_and_die(		"must be root to scan for matching filesystems: %s\n", arg);				else					bb_error_msg_and_die(		"cannot find matching filesystem: %s", arg);			}			devices[num_devices++] = dev ? dev : string_copy(arg);			continue;		}		if (arg[0] != '-' || opts_for_fsck) {			if (num_args >= MAX_ARGS) {				bb_error_msg_and_die("too many arguments");			}			args[num_args++] = string_copy(arg);			continue;		}		for (j=1; arg[j]; j++) {			if (opts_for_fsck) {				options[++opt] = arg[j];				continue;			}			switch (arg[j]) {			case 'A':				doall++;				break;			case 'C':				progress++;				if (arg[j+1]) {					progress_fd = string_to_int(arg+j+1);					if (progress_fd < 0)						progress_fd = 0;					else						goto next_arg;				} else if ((i+1) < argc				 && argv[i+1][0] != '-') {					progress_fd = string_to_int(argv[i]);					if (progress_fd < 0)						progress_fd = 0;					else {						goto next_arg;						i++;					}				}				break;			case 'V':				verbose++;				break;			case 'N':				noexecute++;				break;			case 'R':				skip_root++;				break;			case 'T':				notitle++;				break;			case 'M':				like_mount++;				break;			case 'P':				parallel_root++;				break;			case 's':				serialize++;				break;			case 't':				tmp = 0;				if (fstype)					bb_show_usage();				if (arg[j+1])					tmp = arg+j+1;				else if ((i+1) < argc)					tmp = argv[++i];				else					bb_show_usage();				fstype = string_copy(tmp);				compile_fs_type(fstype, &fs_type_compiled);				goto next_arg;			case '-':				opts_for_fsck++;				break;			case '?':				bb_show_usage();				break;			default:				options[++opt] = arg[j];				break;			}		}	next_arg:		if (opt) {			options[0] = '-';			options[++opt] = '\0';			if (num_args >= MAX_ARGS) {				bb_error_msg("too many arguments");			}			args[num_args++] = string_copy(options);			opt = 0;		}	}	if (getenv("FSCK_FORCE_ALL_PARALLEL"))		force_all_parallel++;	if ((tmp = getenv("FSCK_MAX_INST")))	    max_running = atoi(tmp);}int fsck_main(int argc, char **argv);int fsck_main(int argc, char **argv){	int i, status = 0;	int interactive = 0;	const char *fstab;	struct fs_info *fs;	setvbuf(stdout, NULL, _IONBF, BUFSIZ);	setvbuf(stderr, NULL, _IONBF, BUFSIZ);	blkid_get_cache(&cache, NULL);	PRS(argc, argv);	if (!notitle)		printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);	fstab = getenv("FSTAB_FILE");	if (!fstab)		fstab = _PATH_MNTTAB;	load_fs_info(fstab);	fsck_path = e2fs_set_sbin_path();	if ((num_devices == 1) || (serialize))		interactive = 1;	/* If -A was specified ("check all"), do that! */	if (doall)		return check_all();	if (num_devices == 0) {		serialize++;		interactive++;		return check_all();	}	for (i = 0; i < num_devices; i++) {		if (cancel_requested) {			if (!kill_sent) {				kill_all(SIGTERM);				kill_sent++;			}			break;		}		fs = lookup(devices[i]);		if (!fs) {			fs = create_fs_device(devices[i], 0, "auto",					      0, -1, -1);			if (!fs)				continue;		}		fsck_device(fs, interactive);		if (serialize ||		    (max_running && (num_running >= max_running))) {			struct fsck_instance *inst;			inst = wait_one(0);			if (inst) {				status |= inst->exit_status;				free_instance(inst);			}			if (verbose > 1)				printf("----------------------------------\n");		}	}	status |= wait_many(FLAG_WAIT_ALL);	blkid_put_cache(cache);	return status;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -