aboutsummaryrefslogtreecommitdiff
path: root/sbin/mount_unionfs/mount_unionfs.c
diff options
context:
space:
mode:
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);
}