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

📄 mount.c

📁 Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理硬盘驱动器
💻 C
📖 第 1 页 / 共 3 页
字号:
	return (stat(s, &statbuf) == 0);}/* * Return 0 for success (either mounted sth or -a and NOAUTO was given) */static intmount_one (const char *spec, const char *node, const char *types,	   const char *opts, char *cmdlineopts, int freq, int pass) {	int status, status2;	const char *nspec;	/* Substitute values in opts, if required */	opts = usersubst(opts);	/* Merge the fstab and command line options.  */	if (opts == NULL)		opts = cmdlineopts;	else if (cmdlineopts != NULL)		opts = xstrconcat3(opts, ",", cmdlineopts);	/* Handle possible LABEL= and UUID= forms of spec */	nspec = mount_get_devname_for_mounting(spec);	if (nspec)		spec = nspec;	if (types == NULL && !mounttype && !is_existing_file(spec)) {		if (strchr (spec, ':') != NULL) {			types = "nfs";			if (verbose)				printf(_("mount: no type was given - "					 "I'll assume nfs because of "					 "the colon\n"));		} else if(!strncmp(spec, "//", 2)) {			types = "smbfs";			if (verbose)				printf(_("mount: no type was given - "					 "I'll assume smbfs because of "					 "the // prefix\n"));		}	}	/*	 * Try to mount the file system. When the exit status is EX_BG,	 * we will retry in the background. Otherwise, we're done.	 */	status = try_mount_one (spec, node, types, opts, freq, pass, 0, 0);	if (status != EX_BG)		return status;	/*	 * Retry in the background.	 */	printf (_("mount: backgrounding \"%s\"\n"), spec);	fflush( stdout );		/* prevent duplicate output */	if (fork() > 0)		return 0;			/* parent returns "success" */	spec = xstrdup(spec);		/* arguments will be destroyed */	node = xstrdup(node);		/* by set_proc_name()          */	types = xstrdup(types);	opts = xstrdup(opts);	set_proc_name (spec);		/* make a nice "ps" listing */	status2 = try_mount_one (spec, node, types, opts, freq, pass, 1, 0);	if (verbose && status2)		printf (_("mount: giving up \"%s\"\n"), spec);	exit (0);			/* child stops here */}/* Check if an fsname/dir pair was already in the old mtab.  */static intmounted (const char *spec0, const char *node0) {	struct mntentchn *mc, *mc0;	char *spec, *node;	int ret = 0;	/* Handle possible UUID= and LABEL= in spec */	spec0 = mount_get_devname(spec0);	if (!spec0)		return ret;	spec = canonicalize(spec0);	node = canonicalize(node0);	mc0 = mtab_head();	for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)		if (streq (spec, mc->m.mnt_fsname) &&		    streq (node, mc->m.mnt_dir)) {			ret = 1;			break;		}	my_free(spec);	my_free(node);	return ret;}/* avoid using stat() on things we are not going to mount anyway.. */static inthas_noauto (const char *opts) {	char *s;	if (!opts)		return 0;	s = strstr(opts, "noauto");	if (!s)		return 0;	return (s == opts || s[-1] == ',') && (s[6] == 0 || s[6] == ',');}/* Mount all filesystems of the specified types except swap and root.  *//* With the --fork option: fork and let different incarnations of   mount handle different filesystems.  However, try to avoid several   simultaneous mounts on the same physical disk, since that is very slow. */#define DISKMAJOR(m)	(((int) m) & ~0xf)static intdo_mount_all (char *types, char *options, char *test_opts) {	struct mntentchn *mc, *mc0, *mtmp;	int status = 0;	struct stat statbuf;	struct child {		pid_t pid;		char *group;		struct mntentchn *mec;		struct mntentchn *meclast;		struct child *nxt;	} childhead, *childtail, *cp;	char major[22];	char *g, *colon;	/* build a chain of what we have to do, or maybe	   several chains, one for each major or NFS host */	childhead.nxt = 0;	childtail = &childhead;	mc0 = fstab_head();	for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) {		if (has_noauto (mc->m.mnt_opts))			continue;		if (matching_type (mc->m.mnt_type, types)		    && matching_opts (mc->m.mnt_opts, test_opts)		    && !streq (mc->m.mnt_dir, "/")		    && !streq (mc->m.mnt_dir, "root")) {			if (mounted (mc->m.mnt_fsname, mc->m.mnt_dir)) {				if (verbose)					printf(_("mount: %s already mounted "						 "on %s\n"),					       mc->m.mnt_fsname,					       mc->m.mnt_dir);				continue;			}			mtmp = (struct mntentchn *) xmalloc(sizeof(*mtmp));			*mtmp = *mc;			mtmp->nxt = 0;			g = NULL;			if (optfork) {				if (stat(mc->m.mnt_fsname, &statbuf) == 0 &&				    S_ISBLK(statbuf.st_mode)) {					sprintf(major, "#%x",						DISKMAJOR(statbuf.st_rdev));					g = major;				}#ifdef HAVE_NFS				if (strcmp(mc->m.mnt_type, "nfs") == 0) {					g = xstrdup(mc->m.mnt_fsname);					colon = strchr(g, ':');					if (colon)						*colon = '\0';				}#endif			}			if (g) {				for (cp = childhead.nxt; cp; cp = cp->nxt)					if (cp->group &&					    strcmp(cp->group, g) == 0) {						cp->meclast->nxt = mtmp;						cp->meclast = mtmp;						goto fnd;					}			}			cp = (struct child *) xmalloc(sizeof *cp);			cp->nxt = 0;			cp->mec = cp->meclast = mtmp;			cp->group = xstrdup(g);			cp->pid = 0;			childtail->nxt = cp;			childtail = cp;		fnd:;		}	}			      	/* now do everything */	for (cp = childhead.nxt; cp; cp = cp->nxt) {		pid_t p = -1;		if (optfork) {			p = fork();			if (p == -1) {				int errsv = errno;				error(_("mount: cannot fork: %s"),				      strerror (errsv));			}			else if (p != 0)				cp->pid = p;		}		/* if child, or not forked, do the mounting */		if (p == 0 || p == -1) {			for (mc = cp->mec; mc; mc = mc->nxt) {				status |= mount_one (mc->m.mnt_fsname,						     mc->m.mnt_dir,						     mc->m.mnt_type,						     mc->m.mnt_opts,						     options, 0, 0);			}			if (mountcount)				status |= EX_SOMEOK;			if (p == 0)				exit(status);		}	}	/* wait for children, if any */	while ((cp = childhead.nxt) != NULL) {		childhead.nxt = cp->nxt;		if (cp->pid) {			int ret;		keep_waiting:			if(waitpid(cp->pid, &ret, 0) == -1) {				if (errno == EINTR)					goto keep_waiting;				perror("waitpid");			} else if (WIFEXITED(ret))				status |= WEXITSTATUS(ret);			else				status |= EX_SYSERR;		}	}	if (mountcount)		status |= EX_SOMEOK;	return status;}extern char version[];static struct option longopts[] = {	{ "all", 0, 0, 'a' },	{ "fake", 0, 0, 'f' },	{ "fork", 0, 0, 'F' },	{ "help", 0, 0, 'h' },	{ "no-mtab", 0, 0, 'n' },	{ "read-only", 0, 0, 'r' },	{ "ro", 0, 0, 'r' },	{ "verbose", 0, 0, 'v' },	{ "version", 0, 0, 'V' },	{ "read-write", 0, 0, 'w' },	{ "rw", 0, 0, 'w' },	{ "options", 1, 0, 'o' },	{ "test-opts", 1, 0, 'O' },	{ "pass-fd", 1, 0, 'p' },	{ "types", 1, 0, 't' },	{ "bind", 0, 0, 128 },	{ "replace", 0, 0, 129 },	{ "after", 0, 0, 130 },	{ "before", 0, 0, 131 },	{ "over", 0, 0, 132 },	{ "move", 0, 0, 133 },	{ "guess-fstype", 1, 0, 134 },	{ "rbind", 0, 0, 135 },	{ "internal-only", 0, 0, 'i' },	{ NULL, 0, 0, 0 }};/* Keep the usage message at max 22 lines, each at most 70 chars long.   The user should not need a pager to read it. */static voidusage (FILE *fp, int n) {	fprintf(fp, _(	  "Usage: mount -V                 : print version\n"	  "       mount -h                 : print this help\n"	  "       mount                    : list mounted filesystems\n"	  "       mount -l                 : idem, including volume labels\n"	  "So far the informational part. Next the mounting.\n"	  "The command is `mount [-t fstype] something somewhere'.\n"	  "Details found in /etc/fstab may be omitted.\n"	  "       mount -a [-t|-O] ...     : mount all stuff from /etc/fstab\n"	  "       mount device             : mount device at the known place\n"	  "       mount directory          : mount known device here\n"	  "       mount -t type dev dir    : ordinary mount command\n"	  "Note that one does not really mount a device, one mounts\n"	  "a filesystem (of the given type) found on the device.\n"	  "One can also mount an already visible directory tree elsewhere:\n"	  "       mount --bind olddir newdir\n"	  "or move a subtree:\n"	  "       mount --move olddir newdir\n"	  "A device can be given by name, say /dev/hda1 or /dev/cdrom,\n"	  "or by label, using  -L label  or by uuid, using  -U uuid .\n"	  "Other options: [-nfFrsvw] [-o options] [-p passwdfd].\n"	  "For many more details, say  man 8 mount .\n"	));/*	  "Union or stack mounts are specified using one of\n"	  "       --replace, --after, --before, --over\n"*/	unlock_mtab();	exit (n);}char *progname;intmain(int argc, char *argv[]) {	int c, result = 0, specseen;	char *options = NULL, *test_opts = NULL, *node;	const char *spec;	char *volumelabel = NULL;	char *uuid = NULL;	char *types = NULL;	char *p;	struct mntentchn *mc;	int fd;	sanitize_env();	setlocale(LC_ALL, "");	bindtextdomain(PACKAGE, LOCALEDIR);	textdomain(PACKAGE);	progname = argv[0];	if ((p = strrchr(progname, '/')) != NULL)		progname = p+1;	umask(033);	/* People report that a mount called from init without console	   writes error messages to /etc/mtab	   Let us try to avoid getting fd's 0,1,2 */	while((fd = open("/dev/null", O_RDWR)) == 0 || fd == 1 || fd == 2) ;	if (fd > 2)		close(fd);	mount_blkid_get_cache();#ifdef DO_PS_FIDDLING	initproctitle(argc, argv);#endif	while ((c = getopt_long (argc, argv, "afFhilL:no:O:p:rsU:vVwt:",				 longopts, NULL)) != -1) {		switch (c) {		case 'a':	       /* mount everything in fstab */			++mount_all;			break;		case 'f':	       /* fake: don't actually call mount(2) */			++fake;			break;		case 'F':			++optfork;			break;		case 'h':		/* help */			usage (stdout, 0);			break;		case 'i':			external_allowed = 0;			break;		case 'l':			list_with_volumelabel = 1;			break;		case 'L':			volumelabel = optarg;			break;		case 'n':		/* do not write /etc/mtab */			++nomtab;			break;		case 'o':		/* specify mount options */			if (options)				options = xstrconcat3(options, ",", optarg);			else				options = xstrdup(optarg);			break;		case 'O':		/* with -t: mount only if (not) opt */			if (test_opts)				test_opts = xstrconcat3(test_opts, ",", optarg);			else				test_opts = xstrdup(optarg);			break;		case 'p':		/* fd on which to read passwd */			set_pfd(optarg);			break;		case 'r':		/* mount readonly */			readonly = 1;			readwrite = 0;			break;		case 's':		/* allow sloppy mount options */			sloppy = 1;			break;		case 't':		/* specify file system types */			types = optarg;			break;		case 'U':			uuid = optarg;			break;		case 'v':		/* be chatty - more so if repeated */			++verbose;			break;		case 'V':		/* version */			printf ("mount: %s\n", version);			exit (0);		case 'w':		/* mount read/write */			readwrite = 1;			readonly = 0;			break;		case 0:			break;		case 128: /* bind */			mounttype = MS_BIND;			break;		case 129: /* replace */			mounttype = MS_REPLACE;			break;		case 130: /* after */			mounttype = MS_AFTER;			break;		case 131: /* before */			mounttype = MS_BEFORE;			break;		case 132: /* over */			mounttype = MS_OVER;			break;		case 133: /* move */			mounttype = MS_MOVE;			break;		case 134:			/* undocumented, may go away again:			   call: mount --guess-fstype device			   use only for testing purposes -			   the guessing is not reliable at all */		    {			char *fstype;			fstype = do_guess_fstype(optarg);			printf("%s\n", fstype ? fstype : "unknown");			exit(fstype ? 0 : EX_FAIL);		    }		case 135:			mounttype = (MS_BIND | MS_REC);			break;		case '?':		default:			usage (stderr, EX_USAGE);		}	}	argc -= optind;	argv += optind;	specseen = (uuid || volumelabel) ? 1 : 0; 	/* yes, .. i know */	if (argc+specseen == 0 && !mount_all) {		if (options || mounttype)			usage (stderr, EX_USAGE);		return print_all (types);	}	if (getuid () != geteuid ()) {		suid = 1;		if (types || options || readwrite || nomtab || mount_all ||		    fake || mounttype || (argc + specseen) != 1)			die (EX_USAGE, _("mount: only root can do that"));	}	if (!nomtab && mtab_does_not_exist()) {		if (verbose > 1)			printf(_("mount: no %s found - creating it..\n"),			       MOUNTED);		create_mtab ();	}	if (specseen) {		if (uuid)			spec = mount_get_devname_by_uuid(uuid);		else			spec = mount_get_devname_by_label(volumelabel);		if (!spec)			die (EX_USAGE, _("mount: no such partition found"));		if (verbose)			printf(_("mount: mounting %s\n"), spec);	} else		spec = NULL;		/* just for gcc */	switch (argc+specseen) {	case 0:		/* mount -a */		result = do_mount_all (types, options, test_opts);		if (result == 0 && verbose)			error(_("nothing was mounted"));		break;	case 1:		/* mount [-nfrvw] [-o options] special | node */		if (types != NULL)			usage (stderr, EX_USAGE);		if (specseen) {			/* We know the device. Where shall we mount it? */			mc = (uuid ? getfsuuidspec (uuid)			           : getfsvolspec (volumelabel));			if (mc == NULL)				mc = getfsspec (spec);			if (mc == NULL)				die (EX_USAGE,				     _("mount: cannot find %s in %s"),				     spec, _PATH_FSTAB);			mc->m.mnt_fsname = spec;		} else {			/* Try to find the other pathname in fstab.  */			spec = canonicalize (*argv);			if ((mc = getfsspec (spec)) == NULL &&			    (mc = getfsfile (spec)) == NULL &&			    /* Try noncanonical name in fstab			       perhaps /dev/cdrom or /dos is a symlink */			    (mc = getfsspec (*argv)) == NULL &&			    (mc = getfsfile (*argv)) == NULL &&			    /* Try mtab - maybe this was a remount */			    (mc = getmntfile (spec)) == NULL)				die (EX_USAGE,				     _("mount: can't find %s in %s or %s"),				     spec, _PATH_FSTAB, MOUNTED);			/* Earlier mtab was tried first, but this would			   sometimes try the wrong mount in case mtab had			   the root device entry wrong. */			my_free(spec);		}		result = mount_one (xstrdup (mc->m.mnt_fsname),				    xstrdup (mc->m.mnt_dir),				    xstrdup (mc->m.mnt_type),				    mc->m.mnt_opts, options, 0, 0);		break;	case 2:		/* mount [-nfrvw] [-t vfstype] [-o options] special node */		if (specseen) {			/* we have spec already */			node = argv[0];		} else {			spec = argv[0];			node = argv[1];		}		result = mount_one (spec, node, types, NULL, options, 0, 0);		break;      	default:		usage (stderr, EX_USAGE);	}	if (result == EX_SOMEOK)		result = 0;	mount_blkid_put_cache();	exit (result);}

⌨️ 快捷键说明

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