diff options
Diffstat (limited to 'usermux.c')
-rw-r--r-- | usermux.c | 252 |
1 files changed, 0 insertions, 252 deletions
diff --git a/usermux.c b/usermux.c deleted file mode 100644 index f2f11f3..0000000 --- a/usermux.c +++ /dev/null @@ -1,252 +0,0 @@ -#include <fuse.h> - -#include <pthread.h> -#include <glib.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <signal.h> -#include <wait.h> -#include <errno.h> -#include <pwd.h> -#include <grp.h> - -#define MOUNTDIR "/mnt/avfs" - -static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - -static struct fuse *um_fuse; -static const char *um_dir; - -#define MAX_USERS 100 -static uid_t users[MAX_USERS]; -static size_t numusers = 0; - -void avfs_main(struct fuse *fuse); - -static void reset_signal_handlers() -{ - struct sigaction sa; - - sa.sa_handler = SIG_DFL; - sigemptyset(&(sa.sa_mask)); - sa.sa_flags = 0; - - sigaction(SIGCHLD, &sa, NULL); -} - - -static void start_avfs(uid_t uid) -{ - int res; - char *userdir; - struct fuse *user_fuse; - struct passwd pw_buf; - struct passwd *pw; - char buf[1024]; - - res = getpwuid_r(uid, &pw_buf, buf, sizeof(buf), &pw); - if(pw == NULL) - return; - - user_fuse = fuse_new(FUSE_MULTITHREAD, 0); - - userdir = g_strdup_printf("%s/%010u", MOUNTDIR, uid); - mkdir(userdir, 0755); - chown(userdir, pw->pw_uid, pw->pw_gid); - res = fuse_mount(user_fuse, userdir); - g_free(userdir); - - if(res == -1) - return; - - res = fork(); - if(res == 0) { - reset_signal_handlers(); - - initgroups(pw->pw_name, pw->pw_gid); - setgid(pw->pw_gid); - setuid(pw->pw_uid); - - avfs_main(user_fuse); - exit(0); - } - - fuse_destroy(user_fuse); -} - - -static int find_user(const char *userstr, uid_t *uid) -{ - size_t i; - char *end; - - *uid = strtol(userstr, &end, 10); - if(*end != '\0') - return 0; - - pthread_mutex_lock(&lock); - for(i = 0; i < numusers; i++) { - if(users[i] == *uid) { - pthread_mutex_unlock(&lock); - return 1; - } - } - if(numusers == MAX_USERS) { - memmove(users, users + sizeof(users[0]), - (MAX_USERS - 1) * sizeof(users[0])); - numusers --; - } - - users[numusers++] = *uid; - pthread_mutex_unlock(&lock); - - start_avfs(*uid); - - return 1; -} - -static void root_attr(struct stat *stbuf) -{ - stbuf->st_mode = S_IFDIR | 0555; - stbuf->st_nlink = 2 + numusers; - stbuf->st_size = MAX_USERS; - stbuf->st_blksize = 1024; -} - -static int um_getattr(struct fuse_cred *cred, const char *path, - struct stat *stbuf) -{ - uid_t uid; - memset(stbuf, 0, sizeof(*stbuf)); - - if(strcmp(path, "/") == 0) { - root_attr(stbuf); - return 0; - } - - if(!find_user(path+1, &uid)) - return -ENOENT; - - stbuf->st_mode = S_IFLNK | 0777; - stbuf->st_nlink = 1; - stbuf->st_size = strlen(MOUNTDIR) + 1 + 10; - stbuf->st_blksize = 1024; - stbuf->st_uid = uid; - - return 0; -} - -static int um_readlink(struct fuse_cred *cred, const char *path, char *buf, - size_t size) -{ - uid_t uid; - - if(!find_user(path+1, &uid)) - return -ENOENT; - - snprintf(buf, size, "%s/%010u", MOUNTDIR, uid); - return 0; -} - -static int um_getdir(struct fuse_cred *cred, const char *path, fuse_dirh_t h, - fuse_dirfil_t filler) -{ - size_t i; - - if(strcmp(path, "/") != 0) - return 0; - - filler(h, ".", 0); - filler(h, "..", 0); - - pthread_mutex_lock(&lock); - for(i = 0; i < numusers; i++) { - char buf[32]; - - sprintf(buf, "%u", users[i]); - filler(h, buf, 0); - } - pthread_mutex_unlock(&lock); - - return 0; -} - - -static void exit_handler() -{ - exit(0); -} - -static void child_handler() -{ - int status; - wait(&status); -} - -static 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); - } - - sa.sa_handler = child_handler; - if(sigaction(SIGCHLD, &sa, NULL) == -1) { - perror("Cannot set child signal handler"); - exit(1); - } -} - -static void cleanup() -{ - fuse_unmount(um_fuse); - fuse_destroy(um_fuse); -} - -static struct fuse_operations um_oper = { - getattr: um_getattr, - getdir: um_getdir, - readlink: um_readlink, -}; - -int main(int argc, char *argv[]) -{ - int res; - if(argc != 2) { - fprintf(stderr, "usage: %s mount_dir\n", argv[0]); - exit(1); - } - - um_dir = argv[1]; - - set_signal_handlers(); - atexit(cleanup); - - um_fuse = fuse_new(FUSE_MULTITHREAD, 0); - res = fuse_mount(um_fuse, um_dir); - if(res == -1) - exit(1); - - fuse_set_operations(um_fuse, &um_oper); - fuse_loop(um_fuse); - - return 0; -} |