aboutsummaryrefslogtreecommitdiff
path: root/util/fusermount.c
diff options
context:
space:
mode:
authorGravatar Miklos Szeredi <miklos@szeredi.hu>2004-11-23 22:32:16 +0000
committerGravatar Miklos Szeredi <miklos@szeredi.hu>2004-11-23 22:32:16 +0000
commita25d4c2e7ea3741c5cf44d17d955c9bae91ca128 (patch)
treed269cd16628e5ceddf1f9c3693223d40e4fdace2 /util/fusermount.c
parent72cf5c9d9eced708d212db49a9ae9f261b8cfcd9 (diff)
various fixes
Diffstat (limited to 'util/fusermount.c')
-rw-r--r--util/fusermount.c330
1 files changed, 200 insertions, 130 deletions
diff --git a/util/fusermount.c b/util/fusermount.c
index 98a705b..a7d26ed 100644
--- a/util/fusermount.c
+++ b/util/fusermount.c
@@ -38,8 +38,8 @@
#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
#define FUSE_DEV_OLD "/proc/fs/fuse/dev"
-#define FUSE_DEV_NEW "/dev/fuse"
#define FUSE_SYS_DEV "/sys/class/misc/fuse/dev"
+#define FUSE_VERSION_FILE_OLD "/proc/fs/fuse/version"
const char *progname;
@@ -54,66 +54,7 @@ static const char *get_user_name()
}
}
-/* use a lock file so that multiple fusermount processes don't try and
- modify the mtab file at once! */
-static int lock_mtab()
-{
- const char *mtab_lock = _PATH_MOUNTED ".fuselock";
- int mtablock;
- int res;
-
- mtablock = open(mtab_lock, O_RDWR | O_CREAT, 0600);
- if (mtablock >= 0) {
- res = lockf(mtablock, F_LOCK, 0);
- if (res < 0)
- perror("error getting lock");
- } else
- fprintf(stderr, "unable to open fuse lock file, continuing anyway\n");
-
- return mtablock;
-}
-
-static void unlock_mtab(int mtablock)
-{
- if (mtablock >= 0) {
- lockf(mtablock, F_ULOCK, 0);
- close(mtablock);
- }
-}
-
-static int add_mount(const char *fsname, const char *mnt, const char *type,
- const char *opts)
-{
- int res;
- const char *mtab = _PATH_MOUNTED;
- struct mntent ent;
- FILE *fp;
-
- fp = setmntent(mtab, "a");
- if (fp == NULL) {
- fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
- strerror(errno));
- return -1;
- }
-
- ent.mnt_fsname = (char *) fsname;
- ent.mnt_dir = (char *) mnt;
- ent.mnt_type = (char *) type;
- ent.mnt_opts = (char *) opts;
- ent.mnt_freq = 0;
- ent.mnt_passno = 0;
- res = addmntent(fp, &ent);
- if (res != 0) {
- fprintf(stderr, "%s: failed to add entry to %s: %s\n", progname,
- mtab, strerror(errno));
- return -1;
- }
-
- endmntent(fp);
- return 0;
-}
-
-
+#ifndef USE_UCLIBC
/* Until there is a nice interface for capabilities in _libc_, this will
remain here. I don't think it is fair to expect users to compile libcap
for this program. And anyway what's all this fuss about versioning the
@@ -140,7 +81,7 @@ static uid_t oldfsuid;
static gid_t oldfsgid;
static struct __user_cap_data_struct oldcaps;
-static int drop_privs()
+static int drop_privs(void)
{
int res;
struct __user_cap_header_struct head;
@@ -174,7 +115,7 @@ static int drop_privs()
return 0;
}
-static void restore_privs()
+static void restore_privs(void)
{
struct __user_cap_header_struct head;
int res;
@@ -189,12 +130,81 @@ static void restore_privs()
setfsuid(oldfsuid);
setfsgid(oldfsgid);
}
+#else /* USE_UCLIBC */
+static int drop_privs(void)
+{
+ return 0;
+}
+static void restore_privs(void)
+{
+}
+#endif /* USE_UCLIBC */
+
+
+#ifndef USE_UCLIBC
+/* use a lock file so that multiple fusermount processes don't try and
+ modify the mtab file at once! */
+static int lock_mtab()
+{
+ const char *mtab_lock = _PATH_MOUNTED ".fuselock";
+ int mtablock;
+ int res;
+
+ mtablock = open(mtab_lock, O_RDWR | O_CREAT, 0600);
+ if (mtablock >= 0) {
+ res = lockf(mtablock, F_LOCK, 0);
+ if (res < 0)
+ perror("error getting lock");
+ } else
+ fprintf(stderr, "unable to open fuse lock file, continuing anyway\n");
+
+ return mtablock;
+}
+
+static void unlock_mtab(int mtablock)
+{
+ if (mtablock >= 0) {
+ lockf(mtablock, F_ULOCK, 0);
+ close(mtablock);
+ }
+}
-static int remove_mount(const char *mnt, int quiet, int lazy)
+static int add_mount(const char *fsname, const char *mnt, const char *type,
+ const char *opts)
{
int res;
const char *mtab = _PATH_MOUNTED;
- const char *mtab_new = _PATH_MOUNTED "~fuse~";
+ struct mntent ent;
+ FILE *fp;
+
+ fp = setmntent(mtab, "a");
+ if (fp == NULL) {
+ fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
+ strerror(errno));
+ return -1;
+ }
+
+ ent.mnt_fsname = (char *) fsname;
+ ent.mnt_dir = (char *) mnt;
+ ent.mnt_type = (char *) type;
+ ent.mnt_opts = (char *) opts;
+ ent.mnt_freq = 0;
+ ent.mnt_passno = 0;
+ res = addmntent(fp, &ent);
+ if (res != 0) {
+ fprintf(stderr, "%s: failed to add entry to %s: %s\n", progname,
+ mtab, strerror(errno));
+ return -1;
+ }
+
+ endmntent(fp);
+ return 0;
+}
+
+static int remove_mount(const char *mnt, int quiet, const char *mtab,
+ const char *mtab_new)
+{
+ int res;
struct mntent *entp;
FILE *fp;
FILE *newfp;
@@ -248,46 +258,67 @@ static int remove_mount(const char *mnt, int quiet, int lazy)
endmntent(fp);
endmntent(newfp);
-
- if (found) {
- if (getuid() != 0) {
- res = drop_privs();
- if (res == -1) {
- unlink(mtab_new);
- return -1;
- }
- }
- res = umount2(mnt, lazy ? 2 : 0);
- if (res == -1) {
- if (!quiet)
- fprintf(stderr, "%s: failed to unmount %s: %s\n",
- progname, mnt,strerror(errno));
- found = -1;
- }
- if (getuid() != 0)
- restore_privs();
+ if (!found) {
+ if (!quiet)
+ fprintf(stderr, "%s: entry for %s not found in %s\n", progname,
+ mnt, mtab);
+ unlink(mtab_new);
+ return -1;
}
- if (found == 1) {
- res = rename(mtab_new, mtab);
- if (res == -1) {
- fprintf(stderr, "%s: failed to rename %s to %s: %s\n", progname,
- mtab_new, mtab, strerror(errno));
+ return 0;
+}
+
+
+static int do_unmount(const char *mnt, int quiet, int lazy, const char *mtab,
+ const char *mtab_new)
+{
+ int res;
+
+ if (getuid() != 0) {
+ res = drop_privs();
+ if (res == -1)
return -1;
- }
}
- else {
- if (!found && !quiet)
- fprintf(stderr, "%s: entry for %s not found in %s\n", progname,
- mnt, mtab);
- unlink(mtab_new);
+ res = umount2(mnt, lazy ? 2 : 0);
+ if (res == -1) {
+ if (!quiet)
+ fprintf(stderr, "%s: failed to unmount %s: %s\n",
+ progname, mnt, strerror(errno));
return -1;
}
+ if (getuid() != 0)
+ restore_privs();
+ res = rename(mtab_new, mtab);
+ if (res == -1) {
+ fprintf(stderr, "%s: failed to rename %s to %s: %s\n", progname,
+ mtab_new, mtab, strerror(errno));
+ return -1;
+ }
return 0;
}
+static int unmount_fuse(const char *mnt, int quiet, int lazy)
+{
+ int res;
+ const char *mtab = _PATH_MOUNTED;
+ const char *mtab_new = _PATH_MOUNTED "~fuse~";
+
+ res = remove_mount(mnt, quiet, mtab, mtab_new);
+ if (res == -1)
+ return -1;
+
+ res = do_unmount(mnt, quiet, lazy, mtab, mtab_new);
+ if (res == -1) {
+ unlink(mtab_new);
+ return -1;
+ }
+ return 0;
+}
+#endif /* USE_UCLIBC */
+
static int begins_with(const char *s, const char *beg)
{
if (strncmp(s, beg, strlen(beg)) == 0)
@@ -475,20 +506,32 @@ static int do_mount(const char *mnt, const char *type, mode_t rootmode,
return res;
}
-static int check_version(void)
+static int check_version(const char *dev)
{
int res;
int majorver;
int minorver;
- const char *version_file = FUSE_VERSION_FILE;
- FILE *vf = fopen(version_file, "r");
+ const char *version_file;
+ int isold = 0;
+ FILE *vf;
+
+ if (strcmp(dev, FUSE_DEV_OLD) == 0)
+ isold = 1;
+
+ if (isold)
+ version_file = FUSE_VERSION_FILE_OLD;
+ else
+ version_file = FUSE_VERSION_FILE;
+
+ vf = fopen(version_file, "r");
if (vf == NULL) {
- version_file = "/sys/fs/fuse/version";
- vf = fopen(version_file, "r");
- if (vf == NULL) {
+ if (isold) {
fprintf(stderr, "%s: kernel interface too old\n", progname);
return -1;
- }
+ } else
+ /* If /sys/fs/fuse/version doesn't exist, just skip
+ version checking */
+ return 0;
}
res = fscanf(vf, "%i.%i", &majorver, &minorver);
fclose(vf);
@@ -606,7 +649,7 @@ static int try_open_new_temp(unsigned devnum, char **devp)
return fd;
}
-static int try_open_new(char **devp)
+static int try_open_new(char **devp, int final)
{
const char *dev;
unsigned minor;
@@ -616,8 +659,18 @@ static int try_open_new(char **devp)
unsigned devnum;
char buf[256];
int fd = open(FUSE_SYS_DEV, O_RDONLY);
- if (fd == -1)
- return -2;
+ if (fd == -1) {
+ if (!final)
+ return -2;
+ fd = try_open(FUSE_DEV, devp, 0);
+ if (fd != -1)
+ return fd;
+ if (errno == ENODEV)
+ return -2;
+ fprintf(stderr, "%s: failed to open %s: %s\n", progname,
+ FUSE_DEV, strerror(errno));
+ return -1;
+ }
res = read(fd, buf, sizeof(buf)-1);
close(fd);
@@ -635,10 +688,17 @@ static int try_open_new(char **devp)
}
devnum = (major << 8) + (minor & 0xff) + ((minor & 0xff00) << 12);
- dev = FUSE_DEV_NEW;
+ dev = FUSE_DEV;
res = stat(dev, &stbuf);
- if (res == -1)
- return try_open_new_temp(devnum, devp);
+ if (res == -1) {
+ if (major == FUSE_MAJOR && minor == FUSE_MINOR)
+ return try_open_new_temp(devnum, devp);
+ else {
+ fprintf(stderr, "%s: failed to open %s: %s\n", progname,
+ dev, strerror(errno));
+ return -1;
+ }
+ }
if ((stbuf.st_mode & S_IFMT) != S_IFCHR || stbuf.st_rdev != devnum) {
fprintf(stderr, "%s: %s exists but has wrong attributes\n", progname,
@@ -652,21 +712,27 @@ static int open_fuse_device(char **devp)
{
int fd;
- fd = try_open_new(devp);
- if (fd != -2)
- return fd;
-
- fd = try_open(FUSE_DEV_OLD, devp, 1);
- if (fd != -1)
- return fd;
-
if (1
#ifndef AUTO_MODPROBE
&& getuid() == 0
#endif
) {
int status;
- pid_t pid = fork();
+ pid_t pid;
+
+ fd = try_open(FUSE_DEV_OLD, devp, 1);
+ if (fd != -1)
+ return fd;
+
+ fd = try_open_new(devp, 0);
+ if (fd != -2)
+ return fd;
+
+#ifndef USE_UCLIBC
+ pid = fork();
+#else
+ pid = vfork();
+#endif
if (pid == 0) {
setuid(0);
execl("/sbin/modprobe", "/sbin/modprobe", "fuse", NULL);
@@ -674,16 +740,15 @@ static int open_fuse_device(char **devp)
}
if (pid != -1)
waitpid(pid, &status, 0);
+ }
- fd = try_open_new(devp);
- if (fd != -2)
- return fd;
+ fd = try_open(FUSE_DEV_OLD, devp, 1);
+ if (fd != -1)
+ return fd;
- fd = try_open(FUSE_DEV_OLD, devp, 1);
- if (fd != -1)
- return fd;
-
- }
+ fd = try_open_new(devp, 1);
+ if (fd != -2)
+ return fd;
fprintf(stderr, "fuse device not found, try 'modprobe fuse' first\n");
return -1;
@@ -697,7 +762,6 @@ static int mount_fuse(const char *mnt, const char *opts)
char *dev;
const char *type = "fuse";
struct stat stbuf;
- int mtablock;
char *fsname;
char *mnt_opts;
const char *real_mnt = mnt;
@@ -713,7 +777,7 @@ static int mount_fuse(const char *mnt, const char *opts)
return -1;
}
- res = check_version();
+ res = check_version(dev);
if (res != -1) {
res = check_perm(&real_mnt, &stbuf, &currdir_fd);
if (res != -1)
@@ -731,9 +795,10 @@ static int mount_fuse(const char *mnt, const char *opts)
fchdir(currdir_fd);
close(currdir_fd);
}
-
+
+#ifndef USE_UCLIBC
if (geteuid() == 0) {
- mtablock = lock_mtab();
+ int mtablock = lock_mtab();
res = add_mount(fsname, mnt, type, mnt_opts);
unlock_mtab(mtablock);
if (res == -1) {
@@ -741,6 +806,8 @@ static int mount_fuse(const char *mnt, const char *opts)
return -1;
}
}
+#endif
+
free(fsname);
free(mnt_opts);
free(dev);
@@ -928,11 +995,14 @@ int main(int argc, char *argv[])
restore_privs();
if (unmount) {
+#ifndef USE_UCLIBC
if (geteuid() == 0) {
int mtablock = lock_mtab();
- res = remove_mount(mnt, quiet, lazy);
+ res = unmount_fuse(mnt, quiet, lazy);
unlock_mtab(mtablock);
- } else {
+ } else
+#endif
+ {
res = umount2(mnt, lazy ? 2 : 0);
if (res == -1) {
if (!quiet)