diff options
Diffstat (limited to 'src/lib/rib.c')
| -rw-r--r-- | src/lib/rib.c | 93 |
1 files changed, 70 insertions, 23 deletions
diff --git a/src/lib/rib.c b/src/lib/rib.c index 684c5dcd..6e421397 100644 --- a/src/lib/rib.c +++ b/src/lib/rib.c @@ -1,10 +1,10 @@ /* - * Ouroboros - Copyright (C) 2016 - 2020 + * Ouroboros - Copyright (C) 2016 - 2026 * * RIB export using FUSE * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -43,15 +43,14 @@ #define __USE_XOPEN #elif defined (__FreeBSD__) #define __XSI_VISIBLE 500 -#endif +#endif /* __linux__ */ +#include <sys/stat.h> #include <fuse.h> #ifndef CLOCK_REALTIME_COARSE #define CLOCK_REALTIME_COARSE CLOCK_REALTIME #endif -#define RT "/" - struct reg_comp { struct list_head next; @@ -106,22 +105,21 @@ static int rib_read(const char * path, strcpy(comp, path + 1); - c = strstr(comp, "/"); - + c = strstr(comp, RIB_SEPARATOR); if (c != NULL) *c = '\0'; (void) info; (void) offset; - pthread_rwlock_wrlock(&rib.lock); + pthread_rwlock_rdlock(&rib.lock); list_for_each(p, &rib.reg_comps) { struct reg_comp * r = list_entry(p, struct reg_comp, next); if (strcmp(comp, r->path) == 0) { - int ret = r->ops->read(c + 1, buf, size); + struct rib_ops * ops = r->ops; pthread_rwlock_unlock(&rib.lock); - return ret; + return ops->read(path + 1, buf, size); } } @@ -141,12 +139,16 @@ static int rib_readdir(const char * path, (void) offset; (void) info; + /* Fix ls calling readdir in an infinite loop on raspbian. */ + if (info != NULL && info->nonseekable != 0) + return -ENOENT; + filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); pthread_rwlock_rdlock(&rib.lock); - if (strcmp(path, RT) == 0) { + if (strcmp(path, RIB_SEPARATOR) == 0) { list_for_each(p, &rib.reg_comps) { struct reg_comp * c; c = list_entry(p, struct reg_comp, next); @@ -158,19 +160,25 @@ static int rib_readdir(const char * path, ssize_t len; ssize_t i; struct reg_comp * c; + struct rib_ops * ops; c = list_entry(p, struct reg_comp, next); if (strcmp(path + 1, c->path) != 0) continue; - assert(c->ops->readdir != NULL); + ops = c->ops; - len = c->ops->readdir(&dir_entries); + assert(ops->readdir != NULL); + + pthread_rwlock_unlock(&rib.lock); + + len = ops->readdir(&dir_entries); if (len < 0) - break; + return 0; for (i = 0; i < len; ++i) filler(buf, dir_entries[i], NULL, 0); freepp(char, dir_entries, len); + return 0; } } @@ -185,24 +193,35 @@ static size_t __getattr(const char * path, struct list_head * p; char comp[RIB_PATH_LEN + 1]; char * c; + struct rib_attr attr; if (strlen(path) > RIB_PATH_LEN) return -1; strcpy(comp, path + 1); - c = strstr(comp, "/"); - + c = strstr(comp, RIB_SEPARATOR); if (c != NULL) *c = '\0'; + memset(&attr, 0, sizeof(attr)); + pthread_rwlock_rdlock(&rib.lock); list_for_each(p, &rib.reg_comps) { struct reg_comp * r = list_entry(p, struct reg_comp, next); if (strcmp(comp, r->path) == 0) { - size_t ret = r->ops->getattr(c + 1, st); + size_t ret = r->ops->getattr(path + 1, &attr); pthread_rwlock_unlock(&rib.lock); + st->st_mode = S_IFREG | 0644; + st->st_blocks = 1; + st->st_nlink = 1; + st->st_uid = getuid(); + st->st_gid = getgid(); + st->st_size = attr.size; + st->st_atime = attr.mtime; + st->st_mtime = attr.mtime; + st->st_ctime = attr.mtime; return ret; } } @@ -220,7 +239,7 @@ static int rib_getattr(const char * path, memset(st, 0, sizeof(*st)); - if (strcmp(path, RT) == 0) + if (strcmp(path, RIB_SEPARATOR) == 0) goto finish_dir; pthread_rwlock_rdlock(&rib.lock); @@ -246,6 +265,8 @@ static int rib_getattr(const char * path, st->st_uid = getuid(); st->st_gid = getgid(); st->st_mtime = now.tv_sec; + st->st_atime = now.tv_sec; + st->st_ctime = now.tv_sec; return 0; } @@ -266,7 +287,6 @@ static void * fuse_thr(void * o) } #endif /* HAVE_FUSE */ - int rib_init(const char * mountpt) { #ifdef HAVE_FUSE @@ -280,8 +300,11 @@ int rib_init(const char * mountpt) NULL}; struct fuse_args args = FUSE_ARGS_INIT(3, argv); + if (access("/dev/fuse", R_OK)) + goto fail; + if (stat(FUSE_PREFIX, &st) == -1) - return -1; + goto fail; sprintf(rib.mnt, FUSE_PREFIX "/%s", mountpt); @@ -289,13 +312,13 @@ int rib_init(const char * mountpt) switch(errno) { case ENOENT: if (mkdir(rib.mnt, 0777)) - return -1; + goto fail_mnt; break; case ENOTCONN: fuse_unmount(rib.mnt, rib.ch); break; default: - return -1; + goto fail_mnt; } fuse_opt_parse(&args, NULL, NULL, NULL); @@ -329,6 +352,9 @@ int rib_init(const char * mountpt) fail_mount: fuse_opt_free_args(&args); rmdir(rib.mnt); + fail_mnt: + memset(rib.mnt, 0, sizeof(rib.mnt)); + fail: return -1; #else (void) mountpt; @@ -342,6 +368,9 @@ void rib_fini(void) struct list_head * p; struct list_head * h; + if (strlen(rib.mnt) == 0) + return; + fuse_exit(rib.fuse); fuse_unmount(rib.mnt, rib.ch); @@ -363,6 +392,18 @@ void rib_fini(void) pthread_rwlock_unlock(&rib.lock); pthread_rwlock_destroy(&rib.lock); + + memset(rib.mnt, 0, sizeof(rib.mnt)); +#endif +} + +void rib_cleanup(const char * mnt) +{ +#ifdef HAVE_FUSE + fuse_unmount(mnt, NULL); + rmdir(mnt); +#else + (void) mnt; #endif } @@ -373,6 +414,9 @@ int rib_reg(const char * path, struct reg_comp * rc; struct list_head * p; + if (strlen(rib.mnt) == 0) + return 0; + pthread_rwlock_wrlock(&rib.lock); list_for_each(p, &rib.reg_comps) { @@ -417,6 +461,9 @@ void rib_unreg(const char * path) struct list_head * p; struct list_head * h; + if (strlen(rib.mnt) == 0) + return; + pthread_rwlock_wrlock(&rib.lock); list_for_each_safe(p, h, &rib.reg_comps) { |
