📄 mount.c
字号:
while ((fsname = procnext()) != NULL) if (!strcmp(fsname, type)) return 1; } return 0;}#endifstatic intalready (char *spec, char *node) { return 0;}#if 0/* Create mtab with a root entry. */static voidcreate_mtab (void) {}#endif/* count successful mount system calls */static int mountcount = 0;static intmount5 (char *special, char *dir, char *type, int flags, void *data) { int ret = mount (special, dir, type, 0xC0ED0000 | (flags), data); if (ret == 0) mountcount++; return ret;}/* Mount a single file system. Return status, so don't exit on non-fatal errors. */ static inttry_mount5 (char *spec, char *node, char **type, int flags, char *mount_opts) { char *fsname; if (*type && strcasecmp (*type, "auto") == 0) *type = NULL; if (!*type && !(flags & MS_REMOUNT)) { *type = fstype(spec); } if (*type || (flags & MS_REMOUNT)) return mount5 (spec, node, *type, flags & ~MS_NOSYS, mount_opts); if (!procopen()) return -1; while ((fsname = procnext()) != NULL) { if (tested (fsname)) continue; if (mount5 (spec, node, fsname, flags & ~MS_NOSYS, mount_opts) == 0) { *type = xstrdup(fsname); procclose(); return 0; } else if (errno != EINVAL) { *type = "guess"; procclose(); return 1; } } procclose(); *type = NULL; return -1;}/* * try_mount_one() * Try to mount one file system. When "bg" is 1, this is a retry * in the background. One additional exit code EX_BG is used here. * It is used to instruct the caller to retry the mount in the * background. */static inttry_mount_one (char *spec0, char *node0, char *type0, char *opts0, int freq, int pass, int bg){ int mnt_err; int flags; char *extra_opts; /* written in mtab */ char *mount_opts; /* actually used on system call */ char *spec, *node, *type, *opts; spec = xstrdup(spec0); node = xstrdup(node0); type = xstrdup(type0); opts = xstrdup(opts0); parse_opts (xstrdup (opts), &flags, &extra_opts); /* root may allow certain types of mounts by ordinary users */ if (suid && !(flags & MS_USER)) { if (already (spec, node)) die (EX_USAGE, "mount failed"); else die (EX_USAGE, "mount: only root can mount %s on %s", spec, node); } /* quietly succeed for fstab entries that don't get mounted automatically */ if (all && (flags & MS_NOAUTO)) return 0; mount_opts = extra_opts; if (!fake && type && streq (type, "nfs")) {#ifdef HAVE_NFS mnt_err = nfsmount (spec, node, &flags, &extra_opts, &mount_opts, bg); if (mnt_err) return mnt_err;#else die (EX_SOFTWARE, "mount: this version was compiled " "without support for the type `nfs'");#endif } block_signals (SIG_BLOCK); if (fake || (try_mount5 (spec, node, &type, flags & ~MS_NOSYS, mount_opts)) == 0) /* Mount succeeded, report this (if verbose) and write mtab entry. */ { block_signals (SIG_UNBLOCK); return 0; } mnt_err = errno; block_signals (SIG_UNBLOCK); /* Mount failed */ printf("mount failed \n"); return EX_FAIL;}/* * set_proc_name() * Update the argument vector, so that this process may be easily * identified in a "ps" listing. */static voidset_proc_name (char *spec){#ifdef DO_PS_FIDDLING int i, l; /* * Move the environment so we can reuse the memory. * (Code borrowed from sendmail.) * WARNING: ugly assumptions on memory layout here; if this ever causes * problems, #undef DO_PS_FIDDLING */ for (i = 0; envp0[i] != NULL; i++) continue; environ = (char **) xmalloc(sizeof(char *) * (i + 1)); for (i = 0; envp0[i] != NULL; i++) environ[i] = xstrdup(envp0[i]); environ[i] = NULL; if (i > 0) l = envp0[i-1] + strlen(envp0[i-1]) - argv0[0]; else l = argv0[argc0-1] + strlen(argv0[argc0-1]) - argv0[0]; if (l > sizeof(PROC_NAME)) { strcpy(argv0[0], PROC_NAME); strncpy(argv0[0] + sizeof(PROC_NAME) - 1, spec, l - sizeof(PROC_NAME) - 1); argv0[1] = NULL; }#endif}static intmount_one (char *spec, char *node, char *type, char *opts, char *cmdlineopts, int freq, int pass){ int status; int status2; /* Merge the fstab and command line options. */ if (opts == NULL) opts = cmdlineopts; else if (cmdlineopts != NULL) opts = xstrconcat3(opts, ",", cmdlineopts); if (type == NULL) { if (strchr (spec, ':') != NULL) { type = "nfs"; if (verbose) printf("mount: no type was given - " "I'll assume nfs because of the colon\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, type, opts, freq, pass, 0); if (status != EX_BG) return status; /* * Retry in the background. */ printf ("mount: backgrounding \"%s\"\n", spec); fflush( stdout ); /* prevent duplicate output */#ifdef EMBED printf("mount: not forking...\n");#else if (fork() > 0) return 0; /* parent returns "success" */#endif spec = xstrdup(spec); /* arguments will be destroyed */ node = xstrdup(node); /* by set_proc_name() */ type = xstrdup(type); opts = xstrdup(opts); set_proc_name (spec); /* make a nice "ps" listing */ status2 = try_mount_one (spec, node, type, opts, freq, pass, 1); if (verbose && status2) printf ("mount: giving up \"%s\"\n", spec); exit (0); /* child stops here */}#if 0/* Check if an fsname/dir pair was already in the old mtab. */static intmounted (char *spec, char *node) { struct mntentchn *mc; spec = canonicalize (spec); node = canonicalize (node); for (mc = mtab_head()->nxt; mc; mc = mc->nxt) if (streq (spec, mc->mnt_fsname) && streq (node, mc->mnt_dir)) return 1; return 0;}#endif/* 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 intmount_all (string_list types, char *options) { return -1;}extern char version[];#ifdef EMBED#define getopt_long(a,b,c,d,e) getopt(a,b,c)#elsestatic 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' }, { "types", 1, 0, 't' }, { NULL, 0, 0, 0 }};#endif#ifndef NAOSI_ABS32const#endifchar *usage_string = "\usage: mount [-hV]\n\ mount -a [-nfFrsvw] [-t vfstypes]\n\ mount [-nfrsvw] [-o options] special | node\n\ mount [-nfrsvw] [-t vfstype] [-o options] special node\n\";static voidusage (FILE *fp, int n){ fprintf (fp, "%s", usage_string); unlock_mtab(); exit (n);}intmain (int argc, char *argv[]) { int c, result = 0; char *options = NULL; string_list types = NULL; int fd; /* 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);#ifdef DO_PS_FIDDLING argc0 = argc; argv0 = argv; envp0 = environ;#endif while ((c = getopt_long (argc, argv, "afFhno:rsvVwt:", longopts, NULL)) != EOF) { switch (c) { case 'a': /* mount everything in fstab */ ++all; break; case 'f': /* fake (don't actually do mount(2) call) */ ++fake; break; case 'F': ++optfork; break; case 'h': /* help */ usage (stdout, 0); break; case 'n': /* mount without writing in /etc/mtab */ ++nomtab; break; case 'o': /* specify mount options */ if (options) options = xstrconcat3(options, ",", optarg); else options = xstrdup(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 = parse_list (optarg); break; case 'v': /* be chatty - very chatty 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 '?': default: usage (stderr, EX_USAGE); } } argc -= optind; argv += optind; if (argc == 0 && !all) { if (options) usage (stderr, EX_USAGE); return print_all (types); } if (getuid () != geteuid ()) { suid = 1; if (types || options || readwrite || nomtab || all || fake || argc != 1) die (EX_USAGE, "mount: only root can do that"); } switch (argc) { case 0: /* mount -a */ result = mount_all (types, options); if (result == 0 && verbose) error("not mounted anything"); break; case 1: printf("specify more\n"); break; case 2: /* mount [-nfrvw] [-t vfstype] [-o options] special node */ if (types == NULL) result = mount_one (argv[0], argv[1], NULL, NULL, options, 0, 0); else if (cdr (types) == NULL) result = mount_one (argv[0], argv[1], car (types), NULL, options, 0, 0); else usage (stderr, EX_USAGE); break; default: usage (stderr, EX_USAGE); } if (result == EX_SOMEOK) result = 0; exit (result);}#ifdef EMBEDint getdtablesize(){ return(64);}#endif#ifdef NAOSI_ABS32void naosi(void *pp, int *type);static char* naosi_tab[] = { (char*)naosi, (char*)naosi_tab,};void naosi(void *ptr, int *type){ int t, dt, dd; char *p, **pp; dt = (char*)naosi - naosi_tab[0]; dd = (char*)naosi_tab - naosi_tab[1]; for(pp = (char**)ptr; (t = *type++) >= 0; ++pp){ if((p = *pp) != 0){ if(t == 1){ p += dt; }else if(t == 2){ p += dd; } *pp = p; } }}int type_func[] = { 1, -1 };int type_data[] = { 2, -1 };#endif /* NAOSI_ABS32 */#ifdef NAOSI_ABS32#include <linux/init.h>static voidnaosi_mount(){ int i; /* printf("naosi_mount():\n"); */ for (i = 0; i < sizeof(opt_map) / sizeof(*opt_map); i++) { naosi(&opt_map[i].opt, type_data); } for (i = 0; i < sizeof(string_opt_map) / sizeof(*string_opt_map); i++) { naosi(&string_opt_map[i].tag, type_data); naosi(&string_opt_map[i].valptr, type_data); } for (i = 0; i < sizeof(magic_known) / sizeof(*magic_known); i++) { naosi(&magic_known[i], type_data); } naosi(&usage_string, type_data);}__initcall(naosi_mount);#endif /* NAOSI_ABS32 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -