diff options
Diffstat (limited to 'fusemount.c')
-rw-r--r-- | fusemount.c | 399 |
1 files changed, 0 insertions, 399 deletions
diff --git a/fusemount.c b/fusemount.c deleted file mode 100644 index 574a3fd..0000000 --- a/fusemount.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - AVFS: A Virtual File System Library - Copyright (C) 1998-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.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> -#include <signal.h> -#include <dirent.h> -#include <assert.h> -#include <errno.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/mount.h> -#include <mntent.h> -#include <glib.h> - -static char *mount_dir; - -const char *basedir = "/tmp/pro"; - -struct node { - char *name; - unsigned long ino; -}; - -static GNode *root; -static GHashTable *nodetab; -static unsigned long inoctr = FUSE_ROOT_INO; - -static GNode *new_node(const char *name, unsigned long ino) -{ - struct node *node = g_new0(struct node, 1); - GNode *gn = g_node_new(node); - - node->name = g_strdup(name); - node->ino = ino; - - return gn; -} - -static unsigned long find_node(unsigned long ino, const char *name) -{ - GNode *cn; - GNode *pn = g_hash_table_lookup(nodetab, (gpointer) ino); - if(pn == NULL) { - fprintf(stderr, "Can't find parent node %li\n", ino); - return 0; - } - - for(cn = pn->children; cn != NULL; cn = cn->next) { - struct node *node = (struct node *) cn->data; - if(strcmp(node->name, name) == 0) - return node->ino; - } - - do inoctr++; - while(!inoctr && g_hash_table_lookup(nodetab, (gpointer) ino) != NULL); - - cn = new_node(name, inoctr); - g_node_insert(pn, -1, cn); - g_hash_table_insert(nodetab, (gpointer) inoctr, cn); - - return inoctr; -} - -static char *real_path(unsigned long ino) -{ - GString *s; - char *ss; - GNode *gn = g_hash_table_lookup(nodetab, (gpointer) ino); - - if(gn == NULL) { - fprintf(stderr, "Can't find node %li\n", ino); - return NULL; - } - - s = g_string_new(""); - for(; gn != NULL; gn = gn->parent) { - g_string_prepend(s, ((struct node *) gn->data)->name); - g_string_prepend_c(s, '/'); - } - g_string_prepend(s, basedir); - ss = s->str; - g_string_free(s, FALSE); - - return ss; -} - -static int get_dir(unsigned long dir) -{ - int dirfd; - struct fuse_dirent dirent; - DIR *dp; - struct dirent *de; - size_t reclen; - char *path; - - path = real_path(dir); - if(path == NULL) - return -ENOENT; - - dp = opendir(path); - g_free(path); - if(dp == NULL) { - perror(path); - return -errno; - } - dirfd = open("/tmp/dirtmp", O_RDWR | O_TRUNC | O_CREAT, 0600); - if(dirfd == -1) { - perror("/tmp/dirtmp"); - exit(1); - } - while((de = readdir(dp)) != NULL) { - unsigned long ino = find_node(dir, de->d_name); - assert(ino != 0); - - dirent.ino = ino; - dirent.namelen = strlen(de->d_name); - assert(dirent.namelen <= NAME_MAX); - strcpy(dirent.name, de->d_name); - dirent.type = de->d_type; - - reclen = FUSE_DIRENT_SIZE(&dirent); - write(dirfd, &dirent, reclen); - } - closedir(dp); - - return dirfd; -} - -static int get_attributes(unsigned long ino, struct fuse_attr *attr) -{ - char *path; - struct stat buf; - int res; - - path = real_path(ino); - if(path == NULL) - return -ENOENT; - - res = stat(path, &buf); - g_free(path); - if(res == -1) - return -errno; - - attr->mode = buf.st_mode; - attr->nlink = buf.st_nlink; - attr->uid = buf.st_uid; - attr->gid = buf.st_gid; - attr->rdev = buf.st_rdev; - attr->size = buf.st_size; - attr->blksize = buf.st_blksize; - attr->blocks = buf.st_blocks; - attr->atime = buf.st_atime; - attr->mtime = buf.st_mtime; - attr->ctime = buf.st_ctime; - - return 0; -} - -static void loop(int devfd) -{ - int res; - struct fuse_param param; - struct fuse_outparam out; - struct fuse_inparam in; - int dirfd; - - while(1) { - res = read(devfd, ¶m, sizeof(param)); - if(res == -1) { - perror("read"); - exit(1); - } - - printf("unique: %i, opcode: %i\n", param.unique, param.u.i.opcode); - - dirfd = -1; - in = param.u.i; - switch(in.opcode) { - case FUSE_LOOKUP: - out.u.lookup.ino = find_node(in.ino, in.u.lookup.name); - if(out.u.lookup.ino == 0) - out.result = -ENOENT; - else - out.result = get_attributes(out.u.lookup.ino, - &out.u.lookup.attr); - break; - - case FUSE_GETATTR: - out.result = get_attributes(in.ino, &out.u.getattr.attr); - break; - - case FUSE_OPEN: - dirfd = get_dir(in.ino); - if(dirfd >= 0) { - out.u.open.fd = dirfd; - out.result = 0; - } - else - out.result = dirfd; - break; - - case FUSE_RELEASE: - out.result = 0; - break; - - default: - out.result = -EOPNOTSUPP; - } - param.u.o = out; - - res = write(devfd, ¶m, sizeof(param)); - if(res == -1) { - perror("write"); - exit(1); - } - if(dirfd != -1) { - close(dirfd); - unlink("/tmp/dirtmp"); - } - } -} - -static int mount_fuse(const char *dev, const char *dir, int devfd) -{ - int res; - const char *type; - FILE *fd; - struct mntent ent; - struct fuse_mount_data data; - - data.version = FUSE_MOUNT_VERSION; - data.fd = devfd; - - type = "fuse"; - res = mount(dev, dir, type, MS_MGC_VAL | MS_NOSUID | MS_NODEV, &data); - - if(res == -1) { - fprintf(stderr, "mount failed: %s\n", strerror(errno)); - return -1; - } - - fd = setmntent("/etc/mtab", "a"); - if(fd == NULL) { - fprintf(stderr, "setmntent(\"/etc/mtab\") failed: %s\n", - strerror(errno)); - return -1; - } - - 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(fd, & ent); - if(res != 0) - fprintf(stderr, "addmntent() failed: %s\n", strerror(errno)); - - endmntent(fd); - - return 0; -} - -int unmount_fuse(const char *dir) -{ - int res; - FILE *fdold, *fdnew; - struct mntent *entp; - - res = umount(dir); - - if(res == -1) { - fprintf(stderr, "umount failed: %s\n", strerror(errno)); - return -1; - } - - fdold = setmntent("/etc/mtab", "r"); - if(fdold == NULL) { - fprintf(stderr, "setmntent(\"/etc/mtab\") failed: %s\n", - strerror(errno)); - return -1; - } - - fdnew = setmntent("/etc/mtab~", "w"); - if(fdnew == NULL) { - fprintf(stderr, "setmntent(\"/etc/mtab~\") failed: %s\n", - strerror(errno)); - return -1; - } - - do { - entp = getmntent(fdold); - if(entp != NULL) { - if(strcmp(entp->mnt_dir, dir) != 0) { - res = addmntent(fdnew, entp); - if(res != 0) { - fprintf(stderr, "addmntent() failed: %s\n", - strerror(errno)); - } - } - } - } while(entp != NULL); - - endmntent(fdold); - endmntent(fdnew); - - res = rename("/etc/mtab~", "/etc/mtab"); - if(res == -1) { - fprintf(stderr, "rename(\"/etc/mtab~\", \"/etc/mtab\") failed: %s\n", - strerror(errno)); - return -1; - } - - return 0; -} - -void cleanup() -{ - unmount_fuse(mount_dir); -} - - -void exit_handler() -{ - exit(0); -} - -void set_signal_handlers() -{ - struct sigaction sa; - - sa.sa_handler = exit_handler; - sigemptyset(&(sa.sa_mask)); - sa.sa_flags = 0; - - if (sigaction(SIGHUP, &sa, NULL) == -1 || - sigaction(SIGINT, &sa, NULL) == -1 || - sigaction(SIGTERM, &sa, NULL) == -1) { - - perror("Cannot set exit signal handlers"); - exit(1); - } - - sa.sa_handler = SIG_IGN; - - if(sigaction(SIGPIPE, &sa, NULL) == -1) { - perror("Cannot set ignored signals"); - exit(1); - } -} - - -int main(int argc, char *argv[]) -{ - const char *dev; - int devfd; - - if(argc < 3) { - fprintf(stderr, "usage: %s dev dir\n", argv[0]); - exit(1); - } - - dev = argv[1]; - mount_dir = argv[2]; - - devfd = open(dev, O_RDWR); - if(devfd == -1) { - fprintf(stderr, "failed to open %s: %s\n", dev, strerror(errno)); - exit(1); - } - - mount_fuse(dev, mount_dir, devfd); - - set_signal_handlers(); - atexit(cleanup); - - root = new_node("/", FUSE_ROOT_INO); - nodetab = g_hash_table_new(NULL, NULL); - g_hash_table_insert(nodetab, (gpointer) FUSE_ROOT_INO, root); - - loop(devfd); - - return 0; -} - - - |