9#include <fuse_config.h> 
   25static struct subdir *subdir_get(
void)
 
   30static int subdir_addpath(
struct subdir *d, 
const char *path, 
char **newpathp)
 
   35                unsigned newlen = d->baselen + strlen(path);
 
   37                newpath = malloc(newlen + 2);
 
   43                strcpy(newpath, d->base);
 
   44                strcpy(newpath + d->baselen, path);
 
   53static int subdir_getattr(
const char *path, 
struct stat *stbuf,
 
   56        struct subdir *d = subdir_get();
 
   58        int err = subdir_addpath(d, path, &newpath);
 
   60                err = fuse_fs_getattr(d->next, newpath, stbuf, fi);
 
   66static int subdir_access(
const char *path, 
int mask)
 
   68        struct subdir *d = subdir_get();
 
   70        int err = subdir_addpath(d, path, &newpath);
 
   72                err = fuse_fs_access(d->next, newpath, mask);
 
   79static int count_components(
const char *p)
 
   83        for (; *p == 
'/'; p++);
 
   84        for (ctr = 0; *p; ctr++) {
 
   85                for (; *p && *p != 
'/'; p++);
 
   86                for (; *p == 
'/'; p++);
 
   91static void strip_common(
const char **sp, 
const char **tp)
 
   96                for (; *s == 
'/'; s++);
 
   97                for (; *t == 
'/'; t++);
 
  100                for (; *s == *t && *s && *s != 
'/'; s++, t++);
 
  101        } 
while ((*s == *t && *s) || (!*s && *t == 
'/') || (*s == 
'/' && !*t));
 
  104static void transform_symlink(
struct subdir *d, 
const char *path,
 
  105                              char *buf, 
size_t size)
 
  113        if (l[0] != 
'/' || d->base[0] != 
'/')
 
  116        strip_common(&l, &path);
 
  117        if (l - buf < (
long) d->baselen)
 
  120        dotdots = count_components(path);
 
  126        if (dotdots * 3 + llen + 2 > size)
 
  129        s = buf + dotdots * 3;
 
  131                memmove(s, l, llen + 1);
 
  137        for (s = buf, i = 0; i < dotdots; i++, s += 3)
 
  142static int subdir_readlink(
const char *path, 
char *buf, 
size_t size)
 
  144        struct subdir *d = subdir_get();
 
  146        int err = subdir_addpath(d, path, &newpath);
 
  148                err = fuse_fs_readlink(d->next, newpath, buf, size);
 
  149                if (!err && d->rellinks)
 
  150                        transform_symlink(d, newpath, buf, size);
 
  156static int subdir_opendir(
const char *path, 
struct fuse_file_info *fi)
 
  158        struct subdir *d = subdir_get();
 
  160        int err = subdir_addpath(d, path, &newpath);
 
  162                err = fuse_fs_opendir(d->next, newpath, fi);
 
  168static int subdir_readdir(
const char *path, 
void *buf,
 
  173        struct subdir *d = subdir_get();
 
  175        int err = subdir_addpath(d, path, &newpath);
 
  177                err = fuse_fs_readdir(d->next, newpath, buf, filler, offset,
 
  184static int subdir_releasedir(
const char *path, 
struct fuse_file_info *fi)
 
  186        struct subdir *d = subdir_get();
 
  188        int err = subdir_addpath(d, path, &newpath);
 
  190                err = fuse_fs_releasedir(d->next, newpath, fi);
 
  196static int subdir_mknod(
const char *path, mode_t mode, dev_t rdev)
 
  198        struct subdir *d = subdir_get();
 
  200        int err = subdir_addpath(d, path, &newpath);
 
  202                err = fuse_fs_mknod(d->next, newpath, mode, rdev);
 
  208static int subdir_mkdir(
const char *path, mode_t mode)
 
  210        struct subdir *d = subdir_get();
 
  212        int err = subdir_addpath(d, path, &newpath);
 
  214                err = fuse_fs_mkdir(d->next, newpath, mode);
 
  220static int subdir_unlink(
const char *path)
 
  222        struct subdir *d = subdir_get();
 
  224        int err = subdir_addpath(d, path, &newpath);
 
  226                err = fuse_fs_unlink(d->next, newpath);
 
  232static int subdir_rmdir(
const char *path)
 
  234        struct subdir *d = subdir_get();
 
  236        int err = subdir_addpath(d, path, &newpath);
 
  238                err = fuse_fs_rmdir(d->next, newpath);
 
  244static int subdir_symlink(
const char *from, 
const char *path)
 
  246        struct subdir *d = subdir_get();
 
  248        int err = subdir_addpath(d, path, &newpath);
 
  250                err = fuse_fs_symlink(d->next, from, newpath);
 
  256static int subdir_rename(
const char *from, 
const char *to, 
unsigned int flags)
 
  258        struct subdir *d = subdir_get();
 
  261        int err = subdir_addpath(d, from, &newfrom);
 
  263                err = subdir_addpath(d, to, &newto);
 
  265                        err = fuse_fs_rename(d->next, newfrom, newto, flags);
 
  273static int subdir_link(
const char *from, 
const char *to)
 
  275        struct subdir *d = subdir_get();
 
  278        int err = subdir_addpath(d, from, &newfrom);
 
  280                err = subdir_addpath(d, to, &newto);
 
  282                        err = fuse_fs_link(d->next, newfrom, newto);
 
  290static int subdir_chmod(
const char *path, mode_t mode,
 
  293        struct subdir *d = subdir_get();
 
  295        int err = subdir_addpath(d, path, &newpath);
 
  297                err = fuse_fs_chmod(d->next, newpath, mode, fi);
 
  303static int subdir_chown(
const char *path, uid_t uid, gid_t gid,
 
  306        struct subdir *d = subdir_get();
 
  308        int err = subdir_addpath(d, path, &newpath);
 
  310                err = fuse_fs_chown(d->next, newpath, uid, gid, fi);
 
  316static int subdir_truncate(
const char *path, off_t size,
 
  319        struct subdir *d = subdir_get();
 
  321        int err = subdir_addpath(d, path, &newpath);
 
  323                err = fuse_fs_truncate(d->next, newpath, size, fi);
 
  329static int subdir_utimens(
const char *path, 
const struct timespec ts[2],
 
  332        struct subdir *d = subdir_get();
 
  334        int err = subdir_addpath(d, path, &newpath);
 
  336                err = fuse_fs_utimens(d->next, newpath, ts, fi);
 
  342static int subdir_create(
const char *path, mode_t mode,
 
  345        struct subdir *d = subdir_get();
 
  347        int err = subdir_addpath(d, path, &newpath);
 
  349                err = fuse_fs_create(d->next, newpath, mode, fi);
 
  355static int subdir_open(
const char *path, 
struct fuse_file_info *fi)
 
  357        struct subdir *d = subdir_get();
 
  359        int err = subdir_addpath(d, path, &newpath);
 
  361                err = fuse_fs_open(d->next, newpath, fi);
 
  367static int subdir_read_buf(
const char *path, 
struct fuse_bufvec **bufp,
 
  370        struct subdir *d = subdir_get();
 
  372        int err = subdir_addpath(d, path, &newpath);
 
  374                err = fuse_fs_read_buf(d->next, newpath, bufp, size, offset, fi);
 
  380static int subdir_write_buf(
const char *path, 
struct fuse_bufvec *buf,
 
  383        struct subdir *d = subdir_get();
 
  385        int err = subdir_addpath(d, path, &newpath);
 
  387                err = fuse_fs_write_buf(d->next, newpath, buf, offset, fi);
 
  393static int subdir_statfs(
const char *path, 
struct statvfs *stbuf)
 
  395        struct subdir *d = subdir_get();
 
  397        int err = subdir_addpath(d, path, &newpath);
 
  399                err = fuse_fs_statfs(d->next, newpath, stbuf);
 
  405static int subdir_flush(
const char *path, 
struct fuse_file_info *fi)
 
  407        struct subdir *d = subdir_get();
 
  409        int err = subdir_addpath(d, path, &newpath);
 
  411                err = fuse_fs_flush(d->next, newpath, fi);
 
  417static int subdir_release(
const char *path, 
struct fuse_file_info *fi)
 
  419        struct subdir *d = subdir_get();
 
  421        int err = subdir_addpath(d, path, &newpath);
 
  423                err = fuse_fs_release(d->next, newpath, fi);
 
  429static int subdir_fsync(
const char *path, 
int isdatasync,
 
  432        struct subdir *d = subdir_get();
 
  434        int err = subdir_addpath(d, path, &newpath);
 
  436                err = fuse_fs_fsync(d->next, newpath, isdatasync, fi);
 
  442static int subdir_fsyncdir(
const char *path, 
int isdatasync,
 
  445        struct subdir *d = subdir_get();
 
  447        int err = subdir_addpath(d, path, &newpath);
 
  449                err = fuse_fs_fsyncdir(d->next, newpath, isdatasync, fi);
 
  455static int subdir_setxattr(
const char *path, 
const char *name,
 
  456                           const char *value, 
size_t size, 
int flags)
 
  458        struct subdir *d = subdir_get();
 
  460        int err = subdir_addpath(d, path, &newpath);
 
  462                err = fuse_fs_setxattr(d->next, newpath, name, value, size,
 
  469static int subdir_getxattr(
const char *path, 
const char *name, 
char *value,
 
  472        struct subdir *d = subdir_get();
 
  474        int err = subdir_addpath(d, path, &newpath);
 
  476                err = fuse_fs_getxattr(d->next, newpath, name, value, size);
 
  482static int subdir_listxattr(
const char *path, 
char *list, 
size_t size)
 
  484        struct subdir *d = subdir_get();
 
  486        int err = subdir_addpath(d, path, &newpath);
 
  488                err = fuse_fs_listxattr(d->next, newpath, list, size);
 
  494static int subdir_removexattr(
const char *path, 
const char *name)
 
  496        struct subdir *d = subdir_get();
 
  498        int err = subdir_addpath(d, path, &newpath);
 
  500                err = fuse_fs_removexattr(d->next, newpath, name);
 
  506static int subdir_lock(
const char *path, 
struct fuse_file_info *fi, 
int cmd,
 
  509        struct subdir *d = subdir_get();
 
  511        int err = subdir_addpath(d, path, &newpath);
 
  513                err = fuse_fs_lock(d->next, newpath, fi, cmd, lock);
 
  519static int subdir_flock(
const char *path, 
struct fuse_file_info *fi, 
int op)
 
  521        struct subdir *d = subdir_get();
 
  523        int err = subdir_addpath(d, path, &newpath);
 
  525                err = fuse_fs_flock(d->next, newpath, fi, op);
 
  531static int subdir_bmap(
const char *path, 
size_t blocksize, uint64_t *idx)
 
  533        struct subdir *d = subdir_get();
 
  535        int err = subdir_addpath(d, path, &newpath);
 
  537                err = fuse_fs_bmap(d->next, newpath, blocksize, idx);
 
  543static off_t subdir_lseek(
const char *path, off_t off, 
int whence,
 
  546        struct subdir *ic = subdir_get();
 
  548        int res = subdir_addpath(ic, path, &newpath);
 
  550                res = fuse_fs_lseek(ic->next, newpath, off, whence, fi);
 
  559        struct subdir *d = subdir_get();
 
  560        fuse_fs_init(d->next, conn, cfg);
 
  566static void subdir_destroy(
void *data)
 
  568        struct subdir *d = data;
 
  569        fuse_fs_destroy(d->next);
 
  577        .getattr        = subdir_getattr,
 
  578        .access         = subdir_access,
 
  579        .readlink       = subdir_readlink,
 
  580        .opendir        = subdir_opendir,
 
  581        .readdir        = subdir_readdir,
 
  582        .releasedir     = subdir_releasedir,
 
  583        .mknod          = subdir_mknod,
 
  584        .mkdir          = subdir_mkdir,
 
  585        .symlink        = subdir_symlink,
 
  586        .unlink         = subdir_unlink,
 
  587        .rmdir          = subdir_rmdir,
 
  588        .rename         = subdir_rename,
 
  590        .chmod          = subdir_chmod,
 
  591        .chown          = subdir_chown,
 
  592        .truncate       = subdir_truncate,
 
  593        .utimens        = subdir_utimens,
 
  594        .create         = subdir_create,
 
  596        .read_buf       = subdir_read_buf,
 
  597        .write_buf      = subdir_write_buf,
 
  598        .statfs         = subdir_statfs,
 
  599        .flush          = subdir_flush,
 
  600        .release        = subdir_release,
 
  601        .fsync          = subdir_fsync,
 
  602        .fsyncdir       = subdir_fsyncdir,
 
  603        .setxattr       = subdir_setxattr,
 
  604        .getxattr       = subdir_getxattr,
 
  605        .listxattr      = subdir_listxattr,
 
  606        .removexattr    = subdir_removexattr,
 
  608        .flock          = subdir_flock,
 
  610        .lseek          = subdir_lseek,
 
  613static const struct fuse_opt subdir_opts[] = {
 
  616        { 
"subdir=%s", offsetof(
struct subdir, base), 0 },
 
  617        { 
"rellinks", offsetof(
struct subdir, rellinks), 1 },
 
  618        { 
"norellinks", offsetof(
struct subdir, rellinks), 0 },
 
  622static void subdir_help(
void)
 
  625"    -o subdir=DIR          prepend this directory to all paths (mandatory)\n" 
  626"    -o [no]rellinks        transform absolute symlinks to relative\n");
 
  629static int subdir_opt_proc(
void *data, 
const char *arg, 
int key,
 
  632        (void) data; (void) arg; (void) outargs;
 
  642static struct fuse_fs *subdir_new(
struct fuse_args *args,
 
  643                                  struct fuse_fs *next[])
 
  648        d = calloc(1, 
sizeof(
struct subdir));
 
  650                fuse_log(FUSE_LOG_ERR, 
"fuse-subdir: memory allocation failed\n");
 
  657        if (!next[0] || next[1]) {
 
  658                fuse_log(FUSE_LOG_ERR, 
"fuse-subdir: exactly one next filesystem required\n");
 
  663                fuse_log(FUSE_LOG_ERR, 
"fuse-subdir: missing 'subdir' option\n");
 
  667        if (d->base[0] && d->base[strlen(d->base)-1] != 
'/') {
 
  668                char *tmp = realloc(d->base, strlen(d->base) + 2);
 
  670                        fuse_log(FUSE_LOG_ERR, 
"fuse-subdir: memory allocation failed\n");
 
  674                strcat(d->base, 
"/");
 
  676        d->baselen = strlen(d->base);
 
  678        fs = 
fuse_fs_new(&subdir_oper, 
sizeof(subdir_oper), d);
 
struct fuse_context * fuse_get_context(void)
int(* fuse_fill_dir_t)(void *buf, const char *name, const struct stat *stbuf, off_t off, enum fuse_fill_dir_flags flags)
struct fuse_fs * fuse_fs_new(const struct fuse_operations *op, size_t op_size, void *private_data)
#define FUSE_REGISTER_MODULE(name_, factory_)
void fuse_log(enum fuse_log_level level, const char *fmt,...)
#define FUSE_OPT_KEY(templ, key)
int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc)
void(* destroy)(void *private_data)