summaryrefslogtreecommitdiff
path: root/src/userfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/userfs.c')
-rw-r--r--src/userfs.c78
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);
+}