Esempio n. 1
0
/*
 * based on similar function in util-linux-2.12r/mount/mount.c
 */
static void
update_mtab_entry(const char *spec, const char *node, const char *type,
		  const char *opts, int freq, int pass, int addnew)
{
	struct my_mntent mnt;

	mnt.mnt_fsname = canonicalize (spec);
	mnt.mnt_dir = canonicalize (node);
	mnt.mnt_type = xstrdup(type);
	mnt.mnt_opts = xstrdup(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 (!addnew)
		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(_("%s: can't open %s, %s"),
			      progname, MOUNTED, strerror(errsv));
		} else {
			if ((my_addmntent (mfp, &mnt)) == 1) {
				int errsv = errno;
				error(_("%s: error writing %s, %s"),
				      progname, MOUNTED, strerror(errsv));
			}
		}
		my_endmntent(mfp);
		unlock_mtab();
	}
	my_free(mnt.mnt_fsname);
	my_free(mnt.mnt_dir);
	my_free(mnt.mnt_type);
	my_free(mnt.mnt_opts);
}
Esempio n. 2
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);
}
Esempio n. 3
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;
}
Esempio n. 4
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, struct mntentchn *mc) {
	int umnt_err = 0;
	int isroot;
	int res;
	int status;
	const char *loopdev;
	int myloop = 0;

	/* 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)
		nomtab++;

	/*
	 * Call umount.TYPE for types that require a separate umount program.
	 * All such special things must occur isolated in the types string.
	 */
	if (check_special_umountprog(spec, node, type, &status))
		return status;

	/*
	 * Ignore the option "-d" for non-loop devices and loop devices with
	 * LO_FLAGS_AUTOCLEAR flag.
	 */
	if (delloop && is_loop_device(spec) && !is_loop_autoclear(spec))
		myloop = 1;

	if (lazy) {
		res = umount2 (node, MNT_DETACH);
		if (res < 0)
			umnt_err = errno;
		goto writemtab;
	}

	if (force) {		/* only supported for NFS */
		res = umount2 (node, MNT_FORCE);
		if (res == -1) {
			int errsv = errno;
			perror("umount2");
			errno = errsv;
			if (errno == ENOSYS) {
				if (verbose)
					printf(_("no umount2, trying umount...\n"));
				res = umount (node);
			}
		}
	} else
		res = umount (node);

	if (res < 0)
		umnt_err = errno;

	if (res < 0 && remount && umnt_err == 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 my_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 = xstrdup("ro");
			if (!nomtab)
				update_mtab(node, &remnt);
			return 0;
		} else if (errno != EBUSY) { 	/* hmm ... */
			perror("remount");
			fprintf(stderr,
				_("umount: could not remount %s read-only\n"),
				spec);
		}
	}

	loopdev = 0;
	if (res >= 0) {
		/* Umount succeeded */
		if (verbose)
			printf (_("%s umounted\n"), spec);

		/* Free any loop devices that we allocated ourselves */
		if (mc) {
			char *optl;

			/* old style mtab line? */
			if (streq(mc->m.mnt_type, "loop")) {
				loopdev = spec;
				goto gotloop;
			}

			/* new style mtab line? */
			optl = mc->m.mnt_opts ? xstrdup(mc->m.mnt_opts) : "";
			for (optl = strtok (optl, ","); optl;
			     optl = strtok (NULL, ",")) {
				if (!strncmp(optl, "loop=", 5)) {
					loopdev = optl+5;
					goto gotloop;
				}
			}
		} else {
			/*
			 * If option "-o loop=spec" occurs in mtab,
			 * note the mount point, and delete mtab line.
			 */
			if ((mc = getmntoptfile (spec)) != NULL)
				node = mc->m.mnt_dir;
		}

		/* Also free loop devices when -d flag is given */
		if (myloop)
			loopdev = spec;
	}
 gotloop:
	if (loopdev)
		del_loop(loopdev);

 writemtab:
	if (!nomtab &&
	    (umnt_err == 0 || umnt_err == EINVAL || umnt_err == ENOENT)) {
		update_mtab (node, NULL);
	}

	if (res >= 0)
		return 0;
	if (umnt_err)
		complain(umnt_err, node);
	return 1;
}
Esempio n. 5
0
int au_update_mtab(char *mntpnt, int do_remount, int do_verbose)
{
	int err, fd, status, e2;
	pid_t pid;
	ino_t ino;
	struct stat st;
	struct statfs stfs;
	struct flock flock = {
		.l_type		= F_WRLCK,
		.l_whence	= SEEK_SET,
		.l_start	= 0,
		.l_len		= 0
	};
	char pid_file[sizeof(MTab "~.") + 20];
	FILE *fp;

	err = statfs(MTab, &stfs);
	if (stfs.f_type == PROC_SUPER_MAGIC)
		return 0;

	snprintf(pid_file, sizeof(pid_file), MTab "~.%d", getpid());
	fd = open(pid_file, O_RDWR | O_CREAT | O_EXCL,
		  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
	if (fd < 0)
		AuFin("%s", pid_file);
	err = fcntl(fd, F_SETLK, &flock);
	if (err)
		AuFin("%s", pid_file);
	fp = fdopen(fd, "r+");
	if (!fp)
		AuFin("%s", pid_file);

	pid = fork();
	if (!pid) {
		lock_mtab(pid_file);
		update_mtab(fp, mntpnt, do_remount, do_verbose);
		unlock_mtab();
		return 0;
	} else if (pid < 0)
		AuFin("fork");

	err = fstat(fd, &st);
	if (err)
		perror(pid_file);
	ino = st.st_ino;

	err = waitpid(pid, &status, 0);
	if (err < 0) {
		perror(pid_file);
		goto out;
	}
	err = !WIFEXITED(status);
	if (!err)
		err = WEXITSTATUS(status);

	e2 = unlink(pid_file);
	if (e2 && errno != ENOENT)
		perror(pid_file);
	e2 = stat(MTab "~", &st);
	if (!e2) {
		if (st.st_ino == ino) {
			/*
			 * The inode number is same,
			 * it means it is we who made the file.
			 * If someone else removed our file between stat(2) and
			 * unlink(2), it is a breakage of the rule.
			 */
			e2 = unlink(MTab "~");
			if (e2)
				perror(MTab);
		}
	} else if (errno != ENOENT)
		perror(MTab "~");
	fclose(fp);

 out:
	return err;
}