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

📄 mount.c

📁 Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理硬盘驱动器
💻 C
📖 第 1 页 / 共 3 页
字号:
	  *user = getusername();  }  *flags &= ~(MS_OWNER | MS_GROUP);}static intloop_check(const char **spec, const char **type, int *flags,	   int *loop, const char **loopdev, const char **loopfile) {  int looptype;  unsigned long long offset;  /*   * 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 (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 (verbose)	printf(_("mount: going to use the loop device %s\n"), *loopdev);      offset = opt_offset ? strtoull(opt_offset, NULL, 0) : 0;      if (set_loop(*loopdev, *loopfile, offset,		   opt_encryption, pfd, &loopro)) {	if (verbose)	  printf(_("mount: failed setting up loop device\n"));	return EX_FAIL;      }      if (verbose > 1)	printf(_("mount: setup loop device successfully\n"));      *spec = *loopdev;      if (loopro)	*flags |= MS_RDONLY;    }  }  return 0;}static voidupdate_mtab_entry(const char *spec, const char *node, const char *type,		  const char *opts, int flags, int freq, int pass) {	struct my_mntent mnt;	mnt.mnt_fsname = canonicalize (spec);	mnt.mnt_dir = canonicalize (node);	mnt.mnt_type = type;	mnt.mnt_opts = opts;	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 (verbose)		print_one (&mnt);	if (!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) {				int errsv = errno;				error(_("mount: can't open %s: %s"), MOUNTED,				      strerror (errsv));			} else {				if ((my_addmntent (mfp, &mnt)) == 1) {					int errsv = errno;					error(_("mount: error writing %s: %s"),					      MOUNTED, strerror (errsv));				}			}			my_endmntent(mfp);			unlock_mtab();		}	}	my_free(mnt.mnt_fsname);	my_free(mnt.mnt_dir);}static voidset_pfd(char *s) {	if (!isdigit(*s))		die(EX_USAGE,		    _("mount: argument to -p or --pass-fd must be a number"));	pfd = atoi(optarg);}static voidcdrom_setspeed(const char *spec) {#define CDROM_SELECT_SPEED      0x5322  /* Set the CD-ROM speed */	if (opt_speed) {		int cdrom;		int speed = atoi(opt_speed);		if ((cdrom = open(spec, O_RDONLY | O_NONBLOCK)) < 0)			die(EX_FAIL,			    _("mount: cannot open %s for setting speed"),			    spec);		if (ioctl(cdrom, CDROM_SELECT_SPEED, speed) < 0)			die(EX_FAIL, _("mount: cannot set speed: %s"),			    strerror(errno));		close(cdrom);	}}/* * check_special_mountprog() *	If there is a special mount program for this type, exec it. * returns: 0: no exec was done, 1: exec was done, status has result */static intcheck_special_mountprog(const char *spec, const char *node, const char *type,			int flags, char *extra_opts, int *status) {  char mountprog[120];  struct stat statbuf;  int res;  if (!external_allowed)      return 0;  if (type && strlen(type) < 100) {       sprintf(mountprog, "/sbin/mount.%s", type);       if (stat(mountprog, &statbuf) == 0) {	    res = fork();	    if (res == 0) {		 const char *oo, *mountargs[10];		 int i = 0;		 setuid(getuid());		 setgid(getgid());		 oo = fix_opts_string (flags, extra_opts, NULL);		 mountargs[i++] = mountprog;		 mountargs[i++] = spec;		 mountargs[i++] = node;		 if (nomtab)		      mountargs[i++] = "-n";		 if (verbose)		      mountargs[i++] = "-v";		 if (oo && *oo) {		      mountargs[i++] = "-o";		      mountargs[i++] = oo;		 }		 mountargs[i] = NULL;		 execv(mountprog, (char **) mountargs);		 exit(1);	/* exec failed */	    } else if (res != -1) {		 int st;		 wait(&st);		 *status = (WIFEXITED(st) ? WEXITSTATUS(st) : EX_SYSERR);		 return 1;	    } else {	    	 int errsv = errno;		 error(_("mount: cannot fork: %s"), strerror(errsv));	    }       }  }  return 0;}/* * 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. * returns: 0: OK, EX_SYSERR, EX_FAIL, return code from nfsmount, *      return status from wait */static inttry_mount_one (const char *spec0, const char *node0, const char *types0,	       const char *opts0, int freq, int pass, int bg, int ro) {  int res = 0, status;  int mnt5_res = 0;		/* only for gcc */  int mnt_err;  int flags;  char *extra_opts;		/* written in mtab */  char *mount_opts;		/* actually used on system call */  const char *opts, *spec, *node, *types;  char *user = 0;  int loop = 0;  const char *loopdev = 0, *loopfile = 0;  struct stat statbuf;  int nfs_mount_version = 0;	/* any version */  /* copies for freeing on exit */  const char *opts1, *spec1, *node1, *types1, *extra_opts1;  spec = spec1 = xstrdup(spec0);  node = node1 = xstrdup(node0);  types = types1 = xstrdup(types0);  opts = opts1 = xstrdup(opts0);  parse_opts (opts, &flags, &extra_opts);  extra_opts1 = extra_opts;  /* quietly succeed for fstab entries that don't get mounted automatically */  if (mount_all && (flags & MS_NOAUTO))      goto out;  suid_check(spec, node, &flags, &user);  mount_opts = extra_opts;  if (opt_speed)      cdrom_setspeed(spec);  if (!(flags & MS_REMOUNT)) {      /*       * Don't set up a (new) loop device if we only remount - this left       * stale assignments of files to loop devices. Nasty when used for       * encryption.       */      res = loop_check(&spec, &types, &flags, &loop, &loopdev, &loopfile);      if (res)	  goto out;  }  /*   * Call mount.TYPE for types that require a separate mount program.   * For the moment these types are ncpfs and smbfs. Maybe also vxfs.   * All such special things must occur isolated in the types string.   */  if (check_special_mountprog(spec, node, types, flags, extra_opts, &status)) {      res = status;      goto out;  }  /*   * Also nfs requires a separate program, but it is built in.   */  if (!fake && types && streq (types, "nfs")) {#ifdef HAVE_NFSretry_nfs:    mnt_err = nfsmount (spec, node, &flags, &extra_opts, &mount_opts,			&nfs_mount_version, bg);    if (mnt_err) {	res = mnt_err;	goto out;    }#else    die (EX_SOFTWARE, _("mount: this version was compiled "		      "without support for the type `nfs'"));#endif  }  block_signals (SIG_BLOCK);  if (!fake)    mnt5_res = guess_fstype_and_mount (spec, node, &types, flags & ~MS_NOSYS,				       mount_opts);  if (fake || mnt5_res == 0) {      /* Mount succeeded, report this (if verbose) and write mtab entry.  */      if (loop)	  opt_loopdev = loopdev;      update_mtab_entry(loop ? loopfile : spec,			node,			types ? types : "unknown",			fix_opts_string (flags & ~MS_NOMTAB, extra_opts, user),			flags,			freq,			pass);      block_signals (SIG_UNBLOCK);      res = 0;      goto out;  }  mnt_err = errno;  if (loop)	del_loop(spec);  block_signals (SIG_UNBLOCK);#ifdef HAVE_NFS  if (mnt_err && types && streq (types, "nfs")) {      if (nfs_mount_version == 4 && mnt_err != EBUSY && mnt_err != ENOENT) {	  if (verbose)	    printf(_("mount: failed with nfs mount version 4, trying 3..\n"));	  nfs_mount_version = 3;	  goto retry_nfs;      }  }#endif  /* Mount failed, complain, but don't die.  */  if (types == 0) {    if (suid)      error (_("mount: I could not determine the filesystem type, "	       "and none was specified"));    else      error (_("mount: you must specify the filesystem type"));  } else if (mnt5_res != -1) {      /* should not happen */      error (_("mount: mount failed"));  } 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(types, "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 (!mount_all || 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:      if (stat (node, &statbuf) || ! S_ISDIR(statbuf.st_mode))	   error (_("mount: mount point %s is not a directory"), node);      else if (stat (spec, &statbuf) && errno == ENOTDIR)	   error (_("mount: special device %s does not exist\n"		    "       (a path prefix is not a directory)\n"), spec);      else {	   errno = mnt_err;	   perror("mount");      }      break;    case EINVAL:    { int fd;      unsigned long size;      int warned=0;      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"	       "       missing codepage, or too many mounted file systems"),	       spec);	if (stat(spec, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)	   && (fd = open(spec, O_RDONLY | O_NONBLOCK)) >= 0) {	  if (ioctl(fd, BLKGETSIZE, &size) == 0) {	    if (size == 0 && !loop) {	      warned++;	  error ("       (could this be the IDE device where you in fact use\n"		 "       ide-scsi so that sr0 or sda or so is needed?)");	    }	    if (size && size <= 2) {	      warned++;	  error ("       (aren't you trying to mount an extended partition,\n"		 "       instead of some logical partition inside?)");	    }	  close(fd);	  }#if 0	  /* 0xf for SCSI, 0x3f for IDE. One might check /proc/partitions	     to see whether this thing really is partitioned.	     Do not suggest partitions for /dev/fd0. */	  if (!warned && (statbuf.st_rdev & 0xf) == 0) {	    warned++;	    error ("       (could this be the whole disk device\n"		   "       where you need a partition?)");	  }#endif	}      }      break;    }    case EMFILE:      error (_("mount table full")); break;    case EIO:      error (_("mount: %s: can't read superblock"), spec); break;    case ENODEV:    { int pfs;      if ((pfs = is_in_procfs(types)) == 1 || !strcmp(types, "guess"))        error(_("mount: %s: unknown device"), spec);      else if (pfs == 0) {	char *lowtype, *p;	int u;	error (_("mount: unknown filesystem type '%s'"), types);	/* maybe this loser asked for FAT or ISO9660 or isofs */	lowtype = xstrdup(types);	u = 0;	for(p=lowtype; *p; p++) {	  if(tolower(*p) != *p) {	    *p = tolower(*p);	    u++;	  }	}	if (u && is_in_procfs(lowtype) == 1)	  error (_("mount: probably you meant %s"), lowtype);	else if (!strncmp(lowtype, "iso", 3) && is_in_procfs("iso9660") == 1)	  error (_("mount: maybe you meant 'iso9660'?"));	else if (!strncmp(lowtype, "fat", 3) && is_in_procfs("vfat") == 1)	  error (_("mount: maybe you meant 'vfat'?"));	free(lowtype);      } else	error (_("mount: %s has wrong device number or fs type %s not supported"),	       spec, types);      break;    }    case ENOTBLK:      if (stat (spec, &statbuf)) /* strange ... */	error (_("mount: %s is not a block device, and stat fails?"), spec);      else if (S_ISBLK(statbuf.st_mode))        error (_("mount: the kernel does not recognize %s as a block device\n"	       "       (maybe `insmod driver'?)"), spec);      else if (S_ISREG(statbuf.st_mode))	error (_("mount: %s is not a block device (maybe try `-o loop'?)"),		 spec);      else	error (_("mount: %s is not a block device"), spec);      break;    case ENXIO:      error (_("mount: %s is not a valid block device"), spec); break;    case EACCES:  /* pre-linux 1.1.38, 1.1.41 and later */    case EROFS:   /* linux 1.1.38 and later */    { char *bd = (loop ? "" : _("block device "));      if (ro || (flags & MS_RDONLY)) {          error (_("mount: cannot mount %s%s read-only"),		 bd, spec);          break;      } else if (readwrite) {	  error (_("mount: %s%s is write-protected but explicit `-w' flag given"),		 bd, spec);	  break;      } else {	 if (loop) {	     opts = opts0;	     types = types0;	 }         if (opts) {	     char *opts2 = realloc(xstrdup(opts), strlen(opts)+4);             strcat(opts2, ",ro");	     my_free(opts1);	     opts = opts1 = opts2;         } else             opts = "ro";	 if (types && !strcmp(types, "guess"))	     types = 0;         error (_("mount: %s%s is write-protected, mounting read-only"),		bd, spec0);	 res = try_mount_one (spec0, node0, types, opts, freq, pass, bg, 1);	 goto out;      }      break;    }    default:      error ("mount: %s", strerror (mnt_err)); break;    }  }  res = EX_FAIL; out:  my_free(extra_opts1);  my_free(spec1);  my_free(node1);  my_free(opts1);  my_free(types1);  return res;}/* * set_proc_name() *	Update the argument vector, so that this process may be easily *	identified in a "ps" listing. */static voidset_proc_name (const char *spec){#ifdef DO_PS_FIDDLING	setproctitle ("mount", spec);#endif}static char *subst_string(const char *s, const char *sub, int sublen, const char *repl) {	char *n;	n = (char *) xmalloc(strlen(s)-sublen+strlen(repl)+1);	strncpy (n, s, sub-s);	strcpy (n + (sub-s), repl);	strcat (n, sub+sublen);	return n;}static const char *usersubst(const char *opts) {	char *s, *w;	char id[40];	s = "uid=useruid";	if (opts && (w = strstr(opts, s)) != NULL) {		sprintf(id, "uid=%d", getuid());		opts = subst_string(opts, w, strlen(s), id);	}	s = "gid=usergid";	if (opts && (w = strstr(opts, s)) != NULL) {		sprintf(id, "gid=%d", getgid());		opts = subst_string(opts, w, strlen(s), id);	}	return opts;}static intis_existing_file (const char *s) {	struct stat statbuf;

⌨️ 快捷键说明

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