diff options
Diffstat (limited to 'src/userfs.c')
-rw-r--r-- | src/userfs.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/userfs.c b/src/userfs.c new file mode 100644 index 0000000..bb76ed1 --- /dev/null +++ b/src/userfs.c @@ -0,0 +1,78 @@ +#define FUSE_USE_VERSION 30 + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <pwd.h> + +#include <fuse.h> + +static int usersfs_getattr(const char *path, struct stat *stbuf) +{ + if (strcmp(path, "/") == 0) { + stbuf->st_mode = S_IFDIR | 0755; + stbuf->st_nlink = 2; + } else { + struct passwd *pwent = getpwnam(path + 1); + if (pwent && pwent->pw_dir) { + stbuf->st_mode = S_IFLNK | 0444; + stbuf->st_nlink = 1; + } else { + return -ENOENT; + } + } + return 0; +} + +static int usersfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info *fi) +{ + if (strcmp(path, "/") != 0) { + return -ENOENT; + } + + (void) offset; + (void) fi; + + filler(buf, ".", NULL, 0); + filler(buf, "..", NULL, 0); + + struct passwd *pwent; + setpwent(); + while ((pwent = getpwent())) { + if ((pwent->pw_uid == 0 || pwent->pw_uid >= 1000) && pwent->pw_name && pwent->pw_dir) { + filler(buf, pwent->pw_name, NULL, 0); + } + } + setpwent(); + + return 0; +} + +static int usersfs_readlink(const char *path, char *buf, size_t size) +{ + if (strcmp(path, "/") == 0) { + return -EINVAL; + } + + struct passwd *pwent = getpwnam(path + 1); + if (pwent && pwent->pw_dir) { + strcpy(buf, pwent->pw_dir); + return 0; + } else { + return -ENOENT; + } +} + +static struct fuse_operations usersfs_oper = { + .getattr = usersfs_getattr, + .readdir = usersfs_readdir, + .readlink = usersfs_readlink +}; + +int main(int argc, char *argv[]) +{ + return fuse_main(argc, argv, &usersfs_oper, NULL); +} |