示例#1
0
/*
 * Append a mntent structure to the
 * current mount table.
 */
void
write_mntent(mntent_t *mp, const char *mnttabname)
{
  int retries = 0;
  FILE *mfp;

  if (!mtab_is_writable()) {
    return;
  }

 enfile:
  mfp = open_locked_mtab(mnttabname, "a", mp->mnt_dir);
  if (mfp) {
    mtab_stripnl(mp->mnt_opts);
    if (addmntent(mfp, mp))
      plog(XLOG_ERROR, "Couldn't write %s: %m", mnttabname);
    if (fflush(mfp))
      plog(XLOG_ERROR, "Couldn't flush %s: %m", mnttabname);
    (void) endmntent(mfp);
  } else {
    if (errno == ENFILE && retries < NFILE_RETRIES) {
      sleep(1);
      goto enfile;
    }
    plog(XLOG_ERROR, "setmntent(\"%s\", \"a\"): %m", mnttabname);
  }

  unlock_mntlist();
}
示例#2
0
static int check_mtab(void)
{
	int res = 0;

	if (!nomtab) {
		if (mtab_is_writable())
			res++;
		else
			error(_("%s: cannot modify " MOUNTED ".\n"
				"Please remount the partition with -f option"
				" after making " MOUNTED " writable."),
			       progname);
	}
	return res;
}
示例#3
0
/*
 * Code based on similar function in util-linux-2.12p/mount/mount.c
 *
 */
static void update_mtab_entry(char *spec, char *node, char *type, 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) {
				com_err(progname, OCFS2_ET_IO, "%s, %s",
					MOUNTED, strerror(errno));
			} else {
				if ((my_addmntent (mfp, &mnt)) == 1) {
					com_err(progname, OCFS2_ET_IO, "%s, %s",
						MOUNTED, strerror(errno));
				}
			}
			my_endmntent(mfp);
			unlock_mtab();
		}
	}
	my_free(mnt.mnt_fsname);
	my_free(mnt.mnt_dir);
}
示例#4
0
/*
 * Write out a mount list
 */
void
rewrite_mtab(mntlist *mp, const char *mnttabname)
{
  FILE *mfp;
  int error = 0;
  char tmpname[64];
  int retries;
  int tmpfd;
  char *cp;
  char mcp[128];

  if (!mtab_is_writable()) {
    return;
  }

  /*
   * Concoct a temporary name in the same directory as the target mount
   * table so that rename() will work.
   */
  xstrlcpy(mcp, mnttabname, sizeof(mcp));
  cp = strrchr(mcp, '/');
  if (cp) {
    memmove(tmpname, mcp, cp - mcp);
    tmpname[cp - mcp] = '\0';
  } else {
    plog(XLOG_WARNING, "No '/' in mtab (%s), using \".\" as tmp directory", mnttabname);
    tmpname[0] = '.';
    tmpname[1] = '\0';
  }
  xstrlcat(tmpname, "/mtabXXXXXX", sizeof(tmpname));
  retries = 0;
 enfile1:
#ifdef HAVE_MKSTEMP
  tmpfd = mkstemp(tmpname);
  fchmod(tmpfd, 0644);
#else /* not HAVE_MKSTEMP */
  mktemp(tmpname);
  tmpfd = open(tmpname, O_RDWR | O_CREAT | O_TRUNC, 0644);
#endif /* not HAVE_MKSTEMP */
  if (tmpfd < 0) {
    if (errno == ENFILE && retries++ < NFILE_RETRIES) {
      sleep(1);
      goto enfile1;
    }
    plog(XLOG_ERROR, "%s: open: %m", tmpname);
    return;
  }
  if (close(tmpfd) < 0)
    plog(XLOG_ERROR, "Couldn't close tmp file descriptor: %m");

  retries = 0;
 enfile2:
  mfp = setmntent(tmpname, "w");
  if (!mfp) {
    if (errno == ENFILE && retries++ < NFILE_RETRIES) {
      sleep(1);
      goto enfile2;
    }
    plog(XLOG_ERROR, "setmntent(\"%s\", \"w\"): %m", tmpname);
    error = 1;
    goto out;
  }
  while (mp) {
    if (mp->mnt) {
      if (addmntent(mfp, mp->mnt)) {
	plog(XLOG_ERROR, "Can't write entry to %s", tmpname);
	error = 1;
	goto out;
      }
    }
    mp = mp->mnext;
  }

  /*
   * SunOS 4.1 manuals say that the return code from entmntent()
   * is always 1 and to treat as a void.  That means we need to
   * call fflush() to make sure the new mtab file got written.
   */
  if (fflush(mfp)) {
    plog(XLOG_ERROR, "flush new mtab file: %m");
    error = 1;
    goto out;
  }
  (void) endmntent(mfp);

  /*
   * Rename temporary mtab to real mtab
   */
  if (rename(tmpname, mnttabname) < 0) {
    plog(XLOG_ERROR, "rename %s to %s: %m", tmpname, mnttabname);
    error = 1;
    goto out;
  }
 out:
  if (error)
    (void) unlink(tmpname);
}
示例#5
0
void
update_mtab (const char *dir, struct mntent *instead)
{
	mntFILE *mfp, *mftmp;
	const char *fnam = MOUNTED;
	struct mntentchn mtabhead;	/* dummy */
	struct mntentchn *mc, *mc0, *absent = NULL;

	if (mtab_does_not_exist() || !mtab_is_writable())
		return;

	lock_mtab();

	/* having locked mtab, read it again */
	mc0 = mc = &mtabhead;
	mc->nxt = mc->prev = NULL;

	mfp = nfs_setmntent(fnam, "r");
	if (mfp == NULL || mfp->mntent_fp == NULL) {
		int errsv = errno;
		nfs_error (_("cannot open %s (%s) - mtab not updated"),
		       fnam, strerror (errsv));
		goto leave;
	}

	read_mntentchn(mfp, fnam, mc);

	/* find last occurrence of dir */
	for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev)
		if (streq(mc->m.mnt_dir, dir))
			break;
	if (mc && mc != mc0) {
		if (instead == NULL) {
			/* An umount - remove entry */
			if (mc && mc != mc0) {
				mc->prev->nxt = mc->nxt;
				mc->nxt->prev = mc->prev;
				free(mc);
			}
		} else {
			/* A remount */
			mc->m.mnt_opts = instead->mnt_opts;
		}
	} else if (instead) {
		/* not found, add a new entry */
		absent = xmalloc(sizeof(*absent));
		absent->m = *instead;
		absent->nxt = mc0;
		absent->prev = mc0->prev;
		mc0->prev = absent;
		if (mc0->nxt == NULL)
			mc0->nxt = absent;
	}

	/* write chain to mtemp */
	mftmp = nfs_setmntent (MOUNTED_TEMP, "w");
	if (mftmp == NULL || mftmp->mntent_fp == NULL) {
		int errsv = errno;
		nfs_error (_("cannot open %s (%s) - mtab not updated"),
		       MOUNTED_TEMP, strerror (errsv));
		goto leave;
	}

	for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) {
		if (nfs_addmntent(mftmp, &(mc->m)) == 1) {
			int errsv = errno;
			die (EX_FILEIO, _("error writing %s: %s"),
			     MOUNTED_TEMP, strerror (errsv));
		}
	}

#if 0
	/* the chain might have strings copied from 'instead',
	 * so we cannot safely free it.
	 * And there is no need anyway because we are going to exit
	 * shortly.  So just don't call discard_mntentchn....
	 */
	discard_mntentchn(mc0);
#endif
	if (fchmod (fileno (mftmp->mntent_fp),
		    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
		int errsv = errno;
		nfs_error(_("%s: error changing mode of %s: %s"),
				progname, MOUNTED_TEMP, strerror (errsv));
	}
	nfs_endmntent (mftmp);

	{ /*
	   * If mount is setuid and some non-root user mounts sth,
	   * then mtab.tmp might get the group of this user. Copy uid/gid
	   * from the present mtab before renaming.
	   */
	    struct stat sbuf;
	    if (stat (MOUNTED, &sbuf) == 0) {
			if (chown (MOUNTED_TEMP, sbuf.st_uid, sbuf.st_gid) < 0) {
				nfs_error(_("%s: error changing owner of %s: %s"),
					progname, MOUNTED_TEMP, strerror (errno));
			}
		}
	}

	/* rename mtemp to mtab */
	if (rename (MOUNTED_TEMP, MOUNTED) < 0) {
		int errsv = errno;
		nfs_error(_("%s: can't rename %s to %s: %s\n"),
				progname, MOUNTED_TEMP, MOUNTED,
				strerror(errsv));
	}

 leave:
	unlock_mtab();
}
示例#6
0
/* Umount a single device.  Return a status code, so don't exit
   on a non-fatal error.  We lock/unlock around each umount.  */
static int
umount_one (const char *spec, const char *node, const char *type,
	    const char *opts)
{
  int umnt_err, umnt_err2;
  int isroot;
  int res;

  /* Special case for root.  As of 0.99pl10 we can (almost) unmount root;
     the kernel will remount it readonly so that we can carry on running
     afterwards.  The readonly remount is illegal if any files are opened
     for writing at the time, so we can't update mtab for an unmount of
     root.  As it is only really a remount, this doesn't matter too
     much.  [sct May 29, 1993] */
  isroot = (streq (node, "/") || streq (node, "root")
	                      || streq (node, "rootfs"));
  if (isroot)
    umount_nomtab++;

#if HAVE_NFS
  /* Ignore any RPC errors, so that you can umount the filesystem
     if the server is down.  */
  if (strcasecmp(type, "nfs") == 0)
	  nfs_umount_rpc_call(spec, opts);
#endif
 

  umnt_err = umnt_err2 = 0;
  res = umount (node);
  if (res < 0) {
       umnt_err = errno;
       /* A device might have been mounted on a node that has since
	  been deleted or renamed, so if node fails, also try spec. */
       /* if (umnt_err == ENOENT || umnt_err == EINVAL) */
       if (umnt_err != EBUSY && strcmp(node, spec)) {
	    if (umount_verbose)
		 printf ("could not umount %s - trying %s instead\n",
			 node, spec);
	    res = umount (spec);
	    if (res < 0)
		 umnt_err2 = errno;
	    /* Do not complain about remote NFS mount points */
	    if (errno == ENOENT && index(spec, ':'))
		 umnt_err2 = 0;
       }
  }

  if (res < 0 && remount && (umnt_err == EBUSY || umnt_err2 == EBUSY)) {
       /* Umount failed - let us try a remount */
       res=mount(spec, node, NULL, MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
       if (res == 0) {
	    struct mntent remnt;
	    fprintf(stderr, "umount: %s busy - remounted read-only\n", spec);
	    remnt.mnt_type = remnt.mnt_fsname = NULL;
	    remnt.mnt_dir = xstrdup(node);
	    remnt.mnt_opts = "ro";
	    update_mtab(node, &remnt);
	    return 0;
       } else if (errno != EBUSY) { 	/* hmm ... */
	    perror("remount");
	    fprintf(stderr, "umount: could not remount %s read-only\n",
		    spec);
       }
  }

  if (res >= 0) {
      /* Umount succeeded, update mtab.  */
      if (umount_verbose)
	printf ("%s umounted\n", spec);

      if (!umount_nomtab && mtab_is_writable()) {
	  struct mntentchn *mc;
				/* Special stuff for loop devices */

	  if ((mc = getmntfile (spec)) || (mc = getmntfile (node))) {
	     char *opts;

	     /* old style mtab line? */
	     if (streq(mc->mnt_type, "loop"))
		if (del_loop(spec))
		      goto fail;

	     /* new style mtab line? */
	     opts = mc->mnt_opts ? xstrdup(mc->mnt_opts) : "";
	     for (opts = strtok (opts, ","); opts; opts = strtok (NULL, ",")) {
		 if (!strncmp(opts, "loop=", 5)) {
		     if (del_loop(opts+5))
		       goto fail;
		     break;
		 }
	     }
	  } else {
	      /* maybe spec is a loop device? */
	      /* no del_loop() - just delete it from mtab */
	      if ((mc = getmntoptfile (spec)) != NULL)
		node = mc->mnt_dir;
	  }

				/* Non-loop stuff */
	  update_mtab (node, NULL);
      }
      return 0;
  }

fail:
  /* Umount or del_loop failed, complain, but don't die.  */
  if (!umount_nomtab) {
      /* remove obsolete entry */
      if (umnt_err == EINVAL || umnt_err == ENOENT)
	  update_mtab (node, NULL);
  }

  if (umnt_err2)
       complain(umnt_err2, spec);
  if (umnt_err && umnt_err != umnt_err2)
       complain(umnt_err, node);
  return 1;
}