| /* |
| FUSE: Filesystem in Userspace |
| Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu) |
| |
| This program can be distributed under the terms of the GNU GPL. |
| See the file COPYING. |
| */ |
| |
| #include "fuse_i.h" |
| #include <linux/fuse.h> |
| |
| #include <stdio.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <fcntl.h> |
| #include <sys/mount.h> |
| #include <mntent.h> |
| |
| static int do_mount(const char *dev, const char *dir, const char *type, int fd) |
| { |
| int res; |
| struct fuse_mount_data data; |
| |
| data.version = FUSE_MOUNT_VERSION; |
| data.fd = fd; |
| |
| res = mount(dev, dir, type, MS_MGC_VAL | MS_NOSUID | MS_NODEV, &data); |
| if(res == -1) { |
| perror("mount failed"); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| static void add_mntent(const char *dev, const char *dir, const char *type) |
| { |
| int res; |
| FILE *fp; |
| struct mntent ent; |
| |
| fp = setmntent("/etc/mtab", "a"); |
| if(fp == NULL) { |
| perror("setmntent"); |
| return; |
| } |
| |
| ent.mnt_fsname = (char *) dev; |
| ent.mnt_dir = (char *) dir; |
| ent.mnt_type = (char *) type; |
| ent.mnt_opts = "rw,nosuid,nodev"; |
| ent.mnt_freq = 0; |
| ent.mnt_passno = 0; |
| res = addmntent(fp, & ent); |
| if(res != 0) |
| perror("addmntent"); |
| |
| endmntent(fp); |
| |
| } |
| |
| static void remove_mntent(const char *dir) |
| { |
| int res; |
| FILE *fdold, *fdnew; |
| struct mntent *entp; |
| |
| fdold = setmntent("/etc/mtab", "r"); |
| if(fdold == NULL) { |
| perror("/etc/mtab"); |
| return; |
| } |
| |
| fdnew = setmntent("/etc/mtab~", "w"); |
| if(fdnew == NULL) { |
| perror("/etc/mtab~"); |
| return; |
| } |
| |
| do { |
| entp = getmntent(fdold); |
| if(entp != NULL && strcmp(entp->mnt_dir, dir) != 0) { |
| res = addmntent(fdnew, entp); |
| if(res != 0) |
| perror("addmntent"); |
| } |
| } while(entp != NULL); |
| |
| endmntent(fdold); |
| endmntent(fdnew); |
| |
| res = rename("/etc/mtab~", "/etc/mtab"); |
| if(res == -1) |
| perror("renameing /etc/mtab~ to /etc/mtab"); |
| } |
| |
| int fuse_mount(struct fuse *f, const char *dir) |
| { |
| int res; |
| const char *dev = FUSE_DEV; |
| const char *type = "fuse"; |
| |
| if(f->dir != NULL) |
| return 0; |
| |
| f->fd = open(dev, O_RDWR); |
| if(f->fd == -1) { |
| perror(dev); |
| return -1; |
| } |
| |
| res = do_mount(dev, dir, type, f->fd); |
| if(res == -1) |
| return -1; |
| |
| add_mntent(dev, dir, type); |
| f->dir = g_strdup(dir); |
| |
| return 0; |
| } |
| |
| int fuse_unmount(struct fuse *f) |
| { |
| int res; |
| |
| if(f->dir == NULL) |
| return 0; |
| |
| close(f->fd); |
| f->fd = -1; |
| |
| res = umount(f->dir); |
| if(res == -1) |
| perror("umount failed"); |
| else |
| remove_mntent(f->dir); |
| |
| g_free(f->dir); |
| f->dir = NULL; |
| |
| return res; |
| } |