9 #include <fuse_config.h> 
   25 static struct subdir *subdir_get(
void)
 
   30 static 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);
 
   53 static 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);
 
   66 static 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);
 
   79 static 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++);
 
   91 static 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));
 
  104 static 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)
 
  142 static 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);
 
  156 static 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);
 
  168 static 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,
 
  184 static 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);
 
  196 static 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);
 
  208 static 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);
 
  220 static 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);
 
  232 static 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);
 
  244 static 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);
 
  256 static 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);
 
  273 static 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);
 
  290 static 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);
 
  303 static 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);
 
  316 static 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);
 
  329 static 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);
 
  342 static 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);
 
  355 static 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);
 
  367 static 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);
 
  380 static 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);
 
  393 static 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);
 
  405 static 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);
 
  417 static 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);
 
  429 static 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);
 
  442 static 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);
 
  455 static 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,
 
  469 static 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);
 
  482 static 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);
 
  494 static 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);
 
  506 static 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);
 
  519 static 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);
 
  531 static 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);
 
  543 static 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);
 
  566 static 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,
 
  613 static 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 },
 
  622 static 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");
 
  629 static int subdir_opt_proc(
void *data, 
const char *arg, 
int key,
 
  632         (void) data; (void) arg; (void) outargs;
 
  642 static 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_fs * fuse_fs_new(const struct fuse_operations *op, size_t op_size, void *private_data)
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_context * fuse_get_context(void)
#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)