📄 mount.c
字号:
io_error: perror(device); close(fd); return 0;}FILE *procfs;static voidprocclose(void) { if (procfs) fclose (procfs); procfs = 0;}static intprocopen(void) { return ((procfs = fopen(PROC_FILESYSTEMS, "r")) != NULL);}static char *procnext(void) { char line[100]; static char fsname[50]; while (fgets(line, sizeof(line), procfs)) { if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue; if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue; return fsname; } return 0;}static intis_in_proc(char *type) { char *fsname; if (procopen()) { while ((fsname = procnext()) != NULL) if (!strcmp(fsname, type)) return 1; } return 0;}static intalready (char *spec, char *node) { struct mntentchn *mc; int ret = 1; if ((mc = getmntfile(node)) != NULL) error ("mount: according to mtab, %s is already mounted on %s", mc->mnt_fsname, node); else if ((mc = getmntfile(spec)) != NULL) error ("mount: according to mtab, %s is mounted on %s", spec, mc->mnt_dir); else ret = 0; return ret;}/* Create mtab with a root entry. */static voidcreate_mtab (void) { struct mntentchn *fstab; struct mntent mnt; int flags; char *extra_opts; mntFILE *mfp; lock_mtab(); mfp = my_setmntent (MOUNTED, "a+"); if (mfp == NULL || mfp->mntent_fp == NULL) die (EX_FILEIO, "mount: can't open %s for writing: %s", MOUNTED, strerror (errno)); /* Find the root entry by looking it up in fstab */ if ((fstab = getfsfile ("/")) || (fstab = getfsfile ("root"))) { parse_opts (xstrdup (fstab->mnt_opts), &flags, &extra_opts); mnt.mnt_dir = "/"; mnt.mnt_fsname = canonicalize (fstab->mnt_fsname); mnt.mnt_type = fstab->mnt_type; mnt.mnt_opts = fix_opts_string (flags, extra_opts); mnt.mnt_freq = mnt.mnt_passno = 0; if (my_addmntent (mfp, &mnt) == 1) die (EX_FILEIO, "mount: error writing %s: %s", MOUNTED, strerror (errno)); } if (fchmod (fileno (mfp->mntent_fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) if (errno != EROFS) die (EX_FILEIO, "mount: error changing mode of %s: %s", MOUNTED, strerror (errno)); my_endmntent (mfp); unlock_mtab();}/* 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 (mount_verbose) { printf ("mount: you didn't specify a filesystem type for %s\n", spec); if (*type) printf (" I will try type %s\n", *type); else printf (" I will try all types mentioned in %s\n", PROC_FILESYSTEMS); } } 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){ struct mntentchn mcn; struct mntent mnt; int mnt_err; int flags; char *extra_opts; /* written in mtab */ char *mount_opts; /* actually used on system call */ static int added_ro = 0; int loop, looptype, offset; char *spec, *node, *type, *opts, *loopdev, *loopfile; struct stat statbuf; 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 (mount_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; /* * In the case of a loop mount, either type is of the form lo@/dev/loop5 * or the option "-o loop=/dev/loop5" or just "-o loop" is given, or * mount just has to figure things out for itself from the fact that * spec is not a block device. We do not test for a block device * immediately: maybe later other types of mountable objects will occur. */ loopdev = opt_loopdev; looptype = (type && strncmp("lo@", type, 3) == 0); if (looptype) { if (loopdev) error("mount: loop device specified twice"); loopdev = type+3; type = opt_vfstype; } else if (opt_vfstype) { if (type) error("mount: type specified twice"); else type = opt_vfstype; } loop = ((flags & MS_LOOP) || loopdev || opt_offset || opt_encryption); loopfile = spec; if (loop) { flags |= MS_LOOP; if (fake) { if (mount_verbose) printf("mount: skipping the setup of a loop device\n"); } else { int loopro = (flags & MS_RDONLY); if (!loopdev || !*loopdev) loopdev = find_unused_loop_device(); if (!loopdev) return EX_SYSERR; /* no more loop devices */ if (mount_verbose) printf("mount: going to use the loop device %s\n", loopdev); offset = opt_offset ? strtoul(opt_offset, NULL, 0) : 0; if (set_loop (loopdev, loopfile, offset, opt_encryption, &loopro)) return EX_FAIL; spec = loopdev; if (loopro) flags |= MS_RDONLY; } } if (!fake && type && streq (type, "nfs")) {#if 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 } /* * Call mount.TYPE for types that require a separate * mount program. For the moment these types are ncp and smb. */ if (type)#ifndef ALWAYS_STAT if (streq (type, "smb") || streq (type, "ncp"))#else if (strlen (type) < 100)#endif { char mountprog[120]; sprintf(mountprog, "/sbin/mount.%s", type); if (stat(mountprog, &statbuf) == 0) { if (fork() == 0) { char *oo, *mountargs[10]; int i = 0; setuid(getuid()); setgid(getgid()); oo = fix_opts_string (flags, extra_opts); mountargs[i++] = mountprog; mountargs[i++] = spec; mountargs[i++] = node; if (mount_nomtab) mountargs[i++] = "-n"; if (mount_verbose) mountargs[i++] = "-v"; if (oo && *oo) { mountargs[i++] = "-o"; mountargs[i++] = oo; } mountargs[i] = NULL; execv(mountprog, mountargs); exit(1); /* exec failed */ } else if (fork() != -1) { int status; wait(&status); return status; } else error("cannot fork: %s", strerror(errno)); } } block_signals (SIG_BLOCK); if (fake || (try_mount5 (spec, node, &type, flags & ~MS_NOSYS, mount_opts)) == 0) /* Mount succeeded, report this (if mount_verbose) and write mtab entry. */ { if (loop) opt_loopdev = loopdev; mcn.mnt_fsname = mnt.mnt_fsname = canonicalize (loop ? loopfile : spec); mcn.mnt_dir = mnt.mnt_dir = canonicalize (node); mcn.mnt_type = mnt.mnt_type = type ? type : "unknown"; mcn.mnt_opts = mnt.mnt_opts = fix_opts_string (flags & ~MS_NOMTAB, extra_opts); mcn.nxt = 0; mnt.mnt_freq = freq; mnt.mnt_passno = pass; /* We get chatty now rather than after the update to mtab since the mount succeeded, even if the write to /etc/mtab should fail. */ if (mount_verbose) print_one (&mcn); if (!mount_nomtab && mtab_is_writable()) { if (flags & MS_REMOUNT) update_mtab (mnt.mnt_dir, &mnt); else { mntFILE *mfp; lock_mtab(); mfp = my_setmntent(MOUNTED, "a+"); if (mfp == NULL || mfp->mntent_fp == NULL) { error("mount: can't open %s: %s", MOUNTED, strerror (errno)); } else { if ((my_addmntent (mfp, &mnt)) == 1) error("mount: error writing %s: %s", MOUNTED, strerror (errno)); my_endmntent(mfp); } unlock_mtab(); } } block_signals (SIG_UNBLOCK); return 0; } mnt_err = errno; if (loop) del_loop(spec); block_signals (SIG_UNBLOCK); /* Mount failed, complain, but don't die. */ if (type == 0) error ("mount: you must specify the filesystem type"); else switch (mnt_err) { case EPERM: if (geteuid() == 0) { if (stat (node, &statbuf) || !S_ISDIR(statbuf.st_mode)) error ("mount: mount point %s is not a directory", node); else error ("mount: permission denied"); } else error ("mount: must be superuser to use mount"); break; case EBUSY: if (flags & MS_REMOUNT) { error ("mount: %s is busy", node); } else if (!strcmp(type, "proc") && !strcmp(node, "/proc")) { /* heuristic: if /proc/version exists, then probably proc is mounted */ if (stat ("/proc/version", &statbuf)) /* proc mounted? */ error ("mount: %s is busy", node); /* no */ else if(!all || mount_verbose) /* yes, don't mention it */ error ("mount: proc already mounted"); } else { error ("mount: %s already mounted or %s busy", spec, node); already (spec, node); } break; case ENOENT: if (lstat (node, &statbuf)) error ("mount: mount point %s does not exist", node); else if (stat (node, &statbuf)) error ("mount: mount point %s is a symbolic link to nowhere", node); else if (stat (spec, &statbuf)) error ("mount: special device %s does not exist", spec); else { errno = mnt_err; perror("mount"); } break; case ENOTDIR: error ("mount: mount point %s is not a directory", node); break; case EINVAL: { int fd, size; if (flags & MS_REMOUNT) { error ("mount: %s not mounted already, or bad option", node); } else { error ("mount: wrong fs type, bad option, bad superblock on %s,\n" " or too many mounted file systems", spec); if (stat (spec, &statbuf) == 0 && S_ISBLK(statbuf.st_mode) && (fd = open(spec, O_RDONLY)) >= 0) { if(ioctl(fd, BLKGETSIZE, &size) == 0 && size <= 2) error (" (aren't you trying to mount an extended partition,\n" " instead of some logical partition inside?)"); close(fd); } } break; } case EMFILE: error ("mount table full"); break; case EIO: error ("mount: %s: can't read superblock", spec); break; case ENODEV: if (is_in_proc(type) || !strcmp(type, "guess")) error("mount: %s has wrong major or minor number", spec); else if (procfs) { char *lowtype, *p; int u; error ("mount: fs type %s not supported by kernel", type); /* maybe this loser asked for FAT or ISO9660 or isofs */ lowtype = xstrdup(type); u = 0; for(p=lowtype; *p; p++) { if(tolower(*p) != *p) { *p = tolower(*p); u++; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -