aboutsummaryrefslogtreecommitdiff
path: root/sbin/mount_unionfs/mount_unionfs.c
diff options
context:
space:
mode:
authorCraig Rodrigues <rodrigc@FreeBSD.org>2006-12-02 19:35:56 +0000
committerCraig Rodrigues <rodrigc@FreeBSD.org>2006-12-02 19:35:56 +0000
commitd00947d83af65a3ff545b9494c5cf67b40398dd3 (patch)
tree9c239765475d2d432117d23b880498481836ab65 /sbin/mount_unionfs/mount_unionfs.c
parent2229d0cfa2dd5242d9e9a425b6f66d9346ed86a9 (diff)
downloadsrc-d00947d83af65a3ff545b9494c5cf67b40398dd3.tar.gz
src-d00947d83af65a3ff545b9494c5cf67b40398dd3.zip
Many, many thanks to Masanori OZAWA <ozawa@ongs.co.jp>
and Daichi GOTO <daichi@FreeBSD.org> for submitting this major rewrite of unionfs. This rewrite was done to try to solve many of the longstanding crashing and locking issues in the existing unionfs implementation. This implementation also adds a 'MASQUERADE mode', which allows the user to set different user, group, and file permission modes in the upper layer. Submitted by: daichi, Masanori OZAWA Reviewed by: rodrigc (modified for minor style issues)
Notes
Notes: svn path=/head/; revision=164829
Diffstat (limited to 'sbin/mount_unionfs/mount_unionfs.c')
-rw-r--r--sbin/mount_unionfs/mount_unionfs.c177
1 files changed, 105 insertions, 72 deletions
diff --git a/sbin/mount_unionfs/mount_unionfs.c b/sbin/mount_unionfs/mount_unionfs.c
index 7b619eaf57fd..90ebd8a60864 100644
--- a/sbin/mount_unionfs/mount_unionfs.c
+++ b/sbin/mount_unionfs/mount_unionfs.c
@@ -1,6 +1,9 @@
-/*
+/*-
* Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
+ * The Regents of the University of California.
+ * Copyright (c) 2005, 2006 Masanori Ozawa <ozawa@ongs.co.jp>, ONGS Inc.
+ * Copyright (c) 2006 Daichi Goto <daichi@freebsd.org>
+ * All rights reserved.
*
* This code is derived from software donated to Berkeley by
* Jan-Simon Pendry.
@@ -48,6 +51,7 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/uio.h>
+#include <sys/errno.h>
#include <err.h>
#include <stdio.h>
@@ -55,54 +59,115 @@ static const char rcsid[] =
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
+#include <grp.h>
+#include <pwd.h>
#include "mntopts.h"
-static struct mntopt mopts[] = {
- MOPT_STDOPTS,
- MOPT_END
-};
+static int
+subdir(const char *p, const char *dir)
+{
+ int l;
-static int subdir(const char *, const char *);
-static void usage (void) __dead2;
+ l = strlen(dir);
+ if (l <= 1)
+ return (1);
-int
-main(argc, argv)
- int argc;
- char *argv[];
+ if ((strncmp(p, dir, l) == 0) && (p[l] == '/' || p[l] == '\0'))
+ return (1);
+
+ return (0);
+}
+
+static void
+usage(void)
{
- struct iovec iov[8];
- int ch, mntflags;
- char source[MAXPATHLEN];
- char target[MAXPATHLEN];
- int iovcnt;
+ (void)fprintf(stderr,
+ "usage: mount_unionfs [-o options] directory uniondir\n");
+ exit(EX_USAGE);
+}
+
+static void
+parse_gid(const char *s, char *buf, size_t bufsize)
+{
+ struct group *gr;
+ char *inval;
+
+ if ((gr = getgrnam(s)) != NULL)
+ snprintf(buf, bufsize, "%d", gr->gr_gid);
+ else {
+ strtol(s, &inval, 10);
+ if (*inval != 0) {
+ errx(EX_NOUSER, "unknown group id: %s", s);
+ usage();
+ } else {
+ strncpy(buf, s, bufsize);
+ }
+ }
+}
+
+static uid_t
+parse_uid(const char *s, char *buf, size_t bufsize)
+{
+ struct passwd *pw;
+ char *inval;
+
+ if ((pw = getpwnam(s)) != NULL)
+ snprintf(buf, bufsize, "%d", pw->pw_uid);
+ else {
+ strtol(s, &inval, 10);
+ if (*inval != 0) {
+ errx(EX_NOUSER, "unknown user id: %s", s);
+ usage();
+ } else {
+ strncpy(buf, s, bufsize);
+ }
+ }
+}
- iovcnt = 6;
+int
+main(int argc, char *argv[])
+{
+ struct iovec *iov;
+ int ch, mntflags, iovlen;
+ char source [MAXPATHLEN], target[MAXPATHLEN], errmsg[255];
+ char uid_str[20], gid_str[20];
+ char *p, *val;
+
+ iov = NULL;
+ iovlen = 0;
mntflags = 0;
- while ((ch = getopt(argc, argv, "bo:r")) != -1)
+ memset(errmsg, 0, sizeof(errmsg));
+
+ while ((ch = getopt(argc, argv, "bo:")) != -1) {
switch (ch) {
case 'b':
- iov[6].iov_base = "below";
- iov[6].iov_len = strlen(iov[6].iov_base) + 1;
- iov[7].iov_base = NULL;
- iov[7].iov_len = 0;
- iovcnt = 8;
+ printf("\n -b is deprecated. Use \"-o below\" instead\n");
+ build_iovec(&iov, &iovlen, "below", NULL, 0);
break;
case 'o':
- getmntopts(optarg, mopts, &mntflags, 0);
- break;
- case 'r':
- iov[6].iov_base = "replace";
- iov[6].iov_len = strlen(iov[6].iov_base) + 1;
- iov[7].iov_base = NULL;
- iov[7].iov_len = 0;
- iovcnt = 8;
+ p = strchr(optarg, '=');
+ val = NULL;
+ if (p != NULL) {
+ *p = '\0';
+ val = p + 1;
+ if (strncmp(optarg, "gid", 3) == 0) {
+ parse_gid(val, gid_str, sizeof(gid_str));
+ val = gid_str;
+ }
+ else if (strncmp(optarg, "uid", 3) == 0) {
+ parse_uid(val, uid_str, sizeof(uid_str));
+ val = uid_str;
+ }
+ }
+ build_iovec(&iov, &iovlen, optarg, val, (size_t)-1);
break;
case '?':
default:
usage();
/* NOTREACHED */
}
+ }
argc -= optind;
argv += optind;
@@ -115,46 +180,14 @@ main(argc, argv)
if (subdir(target, source) || subdir(source, target))
errx(EX_USAGE, "%s (%s) and %s (%s) are not distinct paths",
- argv[0], target, argv[1], source);
-
- iov[0].iov_base = "fstype";
- iov[0].iov_len = strlen(iov[0].iov_base) + 1;
- iov[1].iov_base = "unionfs";
- iov[1].iov_len = strlen(iov[1].iov_base) + 1;
- iov[2].iov_base = "fspath";
- iov[2].iov_len = strlen(iov[2].iov_base) + 1;
- iov[3].iov_base = source;
- iov[3].iov_len = strlen(source) + 1;
- iov[4].iov_base = "target";
- iov[4].iov_len = strlen(iov[4].iov_base) + 1;
- iov[5].iov_base = target;
- iov[5].iov_len = strlen(target) + 1;
- if (nmount(iov, iovcnt, mntflags))
- err(EX_OSERR, "%s", target);
- exit(0);
-}
-
-int
-subdir(p, dir)
- const char *p;
- const char *dir;
-{
- int l;
-
- l = strlen(dir);
- if (l <= 1)
- return (1);
+ argv[0], target, argv[1], source);
- if ((strncmp(p, dir, l) == 0) && (p[l] == '/' || p[l] == '\0'))
- return (1);
-
- return (0);
-}
+ build_iovec(&iov, &iovlen, "fstype", "unionfs", (size_t)-1);
+ build_iovec(&iov, &iovlen, "fspath", source, (size_t)-1);
+ build_iovec(&iov, &iovlen, "from", target, (size_t)-1);
+ build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
-void
-usage()
-{
- (void)fprintf(stderr,
- "usage: mount_unionfs [-br] [-o options] directory uniondir\n");
- exit(EX_USAGE);
+ if (nmount(iov, iovlen, mntflags))
+ err(EX_OSERR, "%s: %s", source, errmsg);
+ exit(0);
}