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

📄 fstab.c

📁 linux mount的源代码
💻 C
字号:
#include <unistd.h>#include <errno.h>#include <stdio.h>#include <string.h>#include <sys/stat.h>#include <mntent.h>#include "2mntent.h"#include "fstab.h"#include "sundries.h"		/* for xmalloc() etc */#define streq(s, t)	(strcmp ((s), (t)) == 0)#define PROC_MOUNTS		"/proc/mounts"/* Information about mtab. ------------------------------------*/static int have_mtab_info = 0;static int var_mtab_does_not_exist = 0;static int var_mtab_is_a_symlink = 0;static voidget_mtab_info(void) {     struct stat mtab_stat;     if (!have_mtab_info) {	  if (lstat(MOUNTED, &mtab_stat))	       var_mtab_does_not_exist = 1;	  else if (S_ISLNK(mtab_stat.st_mode))	       var_mtab_is_a_symlink = 1;	  have_mtab_info = 1;     }}intmtab_does_not_exist(void) {     get_mtab_info();     return var_mtab_does_not_exist;}intmtab_is_a_symlink(void) {     get_mtab_info();     return var_mtab_is_a_symlink;}intmtab_is_writable() {     static int ret = -1;     /* Should we write to /etc/mtab upon an update?	Probably not if it is a symlink to /proc/mounts, since that	would create a file /proc/mounts in case the proc filesystem	is not mounted. */     if (mtab_is_a_symlink())	  return 0;     if (ret == -1) {	  int fd = open(MOUNTED, O_RDWR | O_CREAT, 0644);	  if (fd >= 0) {	       close(fd);	       ret = 1;	  } else	       ret = 0;     }     return ret;}/* Contents of mtab and fstab ---------------------------------*/struct mntentchn mounttable, fstab;static int got_mtab = 0;static int got_fstab = 0;static void read_mounttable(void), read_fstab(void);struct mntentchn *mtab_head() {     if (!got_mtab)	  read_mounttable();     return &mounttable;}struct mntentchn *fstab_head() {     if (!got_fstab)	  read_fstab();     return &fstab;}static voidread_mntentchn( mntFILE *mfp, const char *fnam, struct mntentchn *mc0) {	struct mntentchn *mc = mc0;	struct mntent *mnt;	while ((mnt = my_getmntent (mfp)) != NULL	       && !streq (mnt->mnt_type, MNTTYPE_IGNORE)) {		mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc));		mc->nxt->prev = mc;		mc = mc->nxt;		mc->mnt_fsname = mnt->mnt_fsname;		mc->mnt_dir = mnt->mnt_dir;		mc->mnt_type = mnt->mnt_type;		mc->mnt_opts = mnt->mnt_opts;		mc->nxt = NULL;	}	mc0->prev = mc;	if (ferror (mfp->mntent_fp)) {		error("warning: error reading %s: %s", fnam, strerror (errno));		mc0->nxt = mc0->prev = NULL;	}	my_endmntent(mfp);}/* * Read /etc/mtab.  If that fails, try /proc/mounts. * This produces a linked list. The list head mounttable is a dummy. * Return 0 on success. */static voidread_mounttable() {     mntFILE *mfp;     const char *fnam;     struct mntentchn *mc = &mounttable;     got_mtab = 1;     mc->nxt = mc->prev = NULL;     fnam = MOUNTED;     mfp = my_setmntent (fnam, "r");     if (mfp == NULL || mfp->mntent_fp == NULL) {	  int errsv = errno;	  fnam = PROC_MOUNTS;	  mfp = my_setmntent (fnam, "r");	  if (mfp == NULL || mfp->mntent_fp == NULL) {	       error("warning: can't open %s: %s", MOUNTED, strerror (errsv));	       return;	  }	  if (verbose)	       printf ("mount: could not open %s - using %s instead\n",		       MOUNTED, PROC_MOUNTS);     }     read_mntentchn(mfp, fnam, mc);}static voidread_fstab() {     mntFILE *mfp = NULL;     const char *fnam;     struct mntentchn *mc = &fstab;     got_fstab = 1;     mc->nxt = mc->prev = NULL;     fnam = _PATH_FSTAB;     mfp = my_setmntent (fnam, "r");     if (mfp == NULL || mfp->mntent_fp == NULL) {	  error("warning: can't open %s: %s", _PATH_FSTAB, strerror (errno));	  return;     }     read_mntentchn(mfp, fnam, mc);}     /* Given the name NAME, try to find it in mtab.  */ struct mntentchn *getmntfile (const char *name) {    struct mntentchn *mc;    for (mc = mtab_head()->nxt; mc; mc = mc->nxt)        if (streq (mc->mnt_dir, name) || (streq (mc->mnt_fsname, name)))	    break;    return mc;}/* Given the name FILE, try to find the option "loop=FILE" in mtab.  */ struct mntentchn *getmntoptfile (const char *file){     struct mntentchn *mc;     char *opts, *s;     int l;     if (!file)	  return NULL;     l = strlen(file);     for (mc = mtab_head()->nxt; mc; mc = mc->nxt)	  if ((opts = mc->mnt_opts) != NULL	      && (s = strstr(opts, "loop="))	      && !strncmp(s+5, file, l)	      && (s == opts || s[-1] == ',')	      && (s[l+5] == 0 || s[l+5] == ','))	       return mc;     return NULL;}/* Find the dir FILE in fstab.  */struct mntentchn *getfsfile (const char *file) {    struct mntentchn *mc;    for (mc = fstab_head()->nxt; mc; mc = mc->nxt)        if (streq (mc->mnt_dir, file))	    break;    return mc;}/* Find the device SPEC in fstab.  */struct mntentchn *getfsspec (const char *spec){    struct mntentchn *mc;    for (mc = fstab_head()->nxt; mc; mc = mc->nxt)        if (streq (mc->mnt_fsname, spec))	    break;    return mc;}/* Updating mtab ----------------------------------------------*//* File descriptor for lock.  Value tested in unlock_mtab() to remove race.  */static int lock = -1;/* Flag for already existing lock file. */static int old_lockfile = 1;/* Ensure that the lock is released if we are interrupted.  */static voidhandler (int sig) {     die (EX_USER, "%s", sys_siglist[sig]);}static voidsetlkw_timeout (int sig) {     /* nothing, fcntl will fail anyway */}/* Create the lock file.  The lock file will be removed if we catch a signal   or when we exit.  The value of lock is tested to remove the race.  */voidlock_mtab (void) {     int sig = 0;     struct sigaction sa;     struct flock flock;     /* If this is the first time, ensure that the lock will be removed.  */     if (lock < 0) {	  struct stat st;	  sa.sa_handler = handler;	  sa.sa_flags = 0;	  sigfillset (&sa.sa_mask);  	  while (sigismember (&sa.sa_mask, ++sig) != -1 && sig != SIGCHLD) {	       if (sig == SIGALRM)		    sa.sa_handler = setlkw_timeout;	       else		    sa.sa_handler = handler;	       sigaction (sig, &sa, (struct sigaction *) 0);	  }	  /* This stat is performed so we know when not to be overly eager	     when cleaning up after signals. The window between stat and	     open is not significant. */	  if (lstat (MOUNTED_LOCK, &st) < 0 && errno == ENOENT)	       old_lockfile = 0;	  lock = open (MOUNTED_LOCK, O_WRONLY|O_CREAT, 0);	  if (lock < 0) {	       die (EX_FILEIO, "can't create lock file %s: %s "		       "(use -n flag to override)",		    MOUNTED_LOCK, strerror (errno));	  }	  flock.l_type = F_WRLCK;	  flock.l_whence = SEEK_SET;	  flock.l_start = 0;	  flock.l_len = 0;	  alarm(LOCK_TIMEOUT);	  if (fcntl (lock, F_SETLKW, &flock) == -1) {	       int errnosv = errno;	       close (lock);	       lock = -1;	/* The file should not be removed */	       die (EX_FILEIO, "can't lock lock file %s: %s",		    MOUNTED_LOCK,		    errnosv == EINTR ? "timed out" : strerror (errno));	  }	  /* We have now access to the lock, and it can always be removed */	  old_lockfile = 0;     }}/* Remove lock file.  */voidunlock_mtab (void) {     if (lock != -1) {	  close (lock);	  if (!old_lockfile)	       unlink (MOUNTED_LOCK);     }}/* * Update the mtab. *  Used by umount with null INSTEAD: remove any DIR entries. *  Used by mount upon a remount: update option part, *   and complain if a wrong device or type was given. *   [Note that often a remount will be a rw remount of / *    where there was no entry before, and we'll have to believe *    the values given in INSTEAD.] */voidupdate_mtab (const char *dir, struct mntent *instead) {     struct mntent *mnt;     struct mntent *next;     struct mntent remnt;     int added = 0;     mntFILE *mfp, *mftmp;     if (mtab_does_not_exist() || mtab_is_a_symlink())	  return;     lock_mtab();     mfp = my_setmntent(MOUNTED, "r");     if (mfp == NULL || mfp->mntent_fp == NULL) {	  error ("cannot open %s (%s) - mtab not updated",		 MOUNTED, strerror (errno));	  goto leave;     }     mftmp = my_setmntent (MOUNTED_TEMP, "w");     if (mftmp == NULL || mfp->mntent_fp == NULL) {	  error ("can't open %s (%s) - mtab not updated",		 MOUNTED_TEMP, strerror (errno));	  goto leave;     }       while ((mnt = my_getmntent (mfp))) {	  if (streq (mnt->mnt_dir, dir)) {	       added++;	       if (instead) {	/* a remount */		    remnt = *instead;		    next = &remnt;		    remnt.mnt_fsname = mnt->mnt_fsname;		    remnt.mnt_type = mnt->mnt_type;		    if (instead->mnt_fsname			&& !streq(mnt->mnt_fsname, instead->mnt_fsname))			 printf("mount: warning: cannot change "				"mounted device with a remount\n");		    else if (instead->mnt_type			     && !streq(instead->mnt_type, "unknown")			     && !streq(mnt->mnt_type, instead->mnt_type))			 printf("mount: warning: cannot change "				"filesystem type with a remount\n");	       } else		    next = NULL;	  } else	       next = mnt;	  if (next && my_addmntent(mftmp, next) == 1)	       die (EX_FILEIO, "error writing %s: %s",		    MOUNTED_TEMP, strerror (errno));     }     if (instead && !added && my_addmntent(mftmp, instead) == 1)	  die (EX_FILEIO, "error writing %s: %s",	       MOUNTED_TEMP, strerror (errno));     my_endmntent (mfp);     if (fchmod (fileno (mftmp->mntent_fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)	  fprintf(stderr, "error changing mode of %s: %s\n", MOUNTED_TEMP,		  strerror (errno));     my_endmntent (mftmp);     if (rename (MOUNTED_TEMP, MOUNTED) < 0)	  fprintf(stderr, "can't rename %s to %s: %s\n", MOUNTED_TEMP, MOUNTED,		  strerror(errno));leave:     unlock_mtab();}

⌨️ 快捷键说明

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