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);
546 struct subdir *d = subdir_get();
547 fuse_fs_init(d->next, conn, cfg);
553 static void subdir_destroy(
void *data)
555 struct subdir *d = data;
556 fuse_fs_destroy(d->next);
564 .getattr = subdir_getattr,
565 .access = subdir_access,
566 .readlink = subdir_readlink,
567 .opendir = subdir_opendir,
568 .readdir = subdir_readdir,
569 .releasedir = subdir_releasedir,
570 .mknod = subdir_mknod,
571 .mkdir = subdir_mkdir,
572 .symlink = subdir_symlink,
573 .unlink = subdir_unlink,
574 .rmdir = subdir_rmdir,
575 .rename = subdir_rename,
577 .chmod = subdir_chmod,
578 .chown = subdir_chown,
579 .truncate = subdir_truncate,
580 .utimens = subdir_utimens,
581 .create = subdir_create,
583 .read_buf = subdir_read_buf,
584 .write_buf = subdir_write_buf,
585 .statfs = subdir_statfs,
586 .flush = subdir_flush,
587 .release = subdir_release,
588 .fsync = subdir_fsync,
589 .fsyncdir = subdir_fsyncdir,
590 .setxattr = subdir_setxattr,
591 .getxattr = subdir_getxattr,
592 .listxattr = subdir_listxattr,
593 .removexattr = subdir_removexattr,
595 .flock = subdir_flock,
599 static const struct fuse_opt subdir_opts[] = {
602 {
"subdir=%s", offsetof(
struct subdir, base), 0 },
603 {
"rellinks", offsetof(
struct subdir, rellinks), 1 },
604 {
"norellinks", offsetof(
struct subdir, rellinks), 0 },
608 static void subdir_help(
void)
611 " -o subdir=DIR prepend this directory to all paths (mandatory)\n" 612 " -o [no]rellinks transform absolute symlinks to relative\n");
615 static int subdir_opt_proc(
void *data,
const char *arg,
int key,
618 (void) data; (void) arg; (void) outargs;
628 static struct fuse_fs *subdir_new(
struct fuse_args *args,
629 struct fuse_fs *next[])
634 d = calloc(1,
sizeof(
struct subdir));
636 fprintf(stderr,
"fuse-subdir: memory allocation failed\n");
643 if (!next[0] || next[1]) {
644 fprintf(stderr,
"fuse-subdir: exactly one next filesystem required\n");
649 fprintf(stderr,
"fuse-subdir: missing 'subdir' option\n");
653 if (d->base[0] && d->base[strlen(d->base)-1] !=
'/') {
654 char *tmp = realloc(d->base, strlen(d->base) + 2);
656 fprintf(stderr,
"fuse-subdir: memory allocation failed\n");
660 strcat(d->base,
"/");
662 d->baselen = strlen(d->base);
664 fs =
fuse_fs_new(&subdir_oper,
sizeof(subdir_oper), d);
void(* destroy)(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)
#define FUSE_REGISTER_MODULE(name_, factory_)
struct fuse_fs * fuse_fs_new(const struct fuse_operations *op, size_t op_size, void *private_data)
struct fuse_context * fuse_get_context(void)
#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)