"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.10.4/doc/html/subdir_8c_source.html" (9 Jun 2021, 105568 Bytes) of package /linux/misc/fuse-3.10.4.tar.xz:


Caution: In this restricted "Fossies" environment the current HTML page may not be correctly presentated and may have some non-functional links. You can here alternatively try to browse the pure source code or just view or download the uninterpreted raw source code. If the rendering is insufficient you may try to find and view the page on the project site itself.

libfuse
subdir.c
1 /*
2  fuse subdir module: offset paths with a base directory
3  Copyright (C) 2007 Miklos Szeredi <miklos@szeredi.hu>
4 
5  This program can be distributed under the terms of the GNU LGPLv2.
6  See the file COPYING.LIB
7 */
8 
9 #include <config.h>
10 
11 #include <fuse.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <stddef.h>
15 #include <string.h>
16 #include <errno.h>
17 
18 struct subdir {
19  char *base;
20  size_t baselen;
21  int rellinks;
22  struct fuse_fs *next;
23 };
24 
25 static struct subdir *subdir_get(void)
26 {
28 }
29 
30 static int subdir_addpath(struct subdir *d, const char *path, char **newpathp)
31 {
32  char *newpath = NULL;
33 
34  if (path != NULL) {
35  unsigned newlen = d->baselen + strlen(path);
36 
37  newpath = malloc(newlen + 2);
38  if (!newpath)
39  return -ENOMEM;
40 
41  if (path[0] == '/')
42  path++;
43  strcpy(newpath, d->base);
44  strcpy(newpath + d->baselen, path);
45  if (!newpath[0])
46  strcpy(newpath, ".");
47  }
48  *newpathp = newpath;
49 
50  return 0;
51 }
52 
53 static int subdir_getattr(const char *path, struct stat *stbuf,
54  struct fuse_file_info *fi)
55 {
56  struct subdir *d = subdir_get();
57  char *newpath;
58  int err = subdir_addpath(d, path, &newpath);
59  if (!err) {
60  err = fuse_fs_getattr(d->next, newpath, stbuf, fi);
61  free(newpath);
62  }
63  return err;
64 }
65 
66 static int subdir_access(const char *path, int mask)
67 {
68  struct subdir *d = subdir_get();
69  char *newpath;
70  int err = subdir_addpath(d, path, &newpath);
71  if (!err) {
72  err = fuse_fs_access(d->next, newpath, mask);
73  free(newpath);
74  }
75  return err;
76 }
77 
78 
79 static int count_components(const char *p)
80 {
81  int ctr;
82 
83  for (; *p == '/'; p++);
84  for (ctr = 0; *p; ctr++) {
85  for (; *p && *p != '/'; p++);
86  for (; *p == '/'; p++);
87  }
88  return ctr;
89 }
90 
91 static void strip_common(const char **sp, const char **tp)
92 {
93  const char *s = *sp;
94  const char *t = *tp;
95  do {
96  for (; *s == '/'; s++);
97  for (; *t == '/'; t++);
98  *tp = t;
99  *sp = s;
100  for (; *s == *t && *s && *s != '/'; s++, t++);
101  } while ((*s == *t && *s) || (!*s && *t == '/') || (*s == '/' && !*t));
102 }
103 
104 static void transform_symlink(struct subdir *d, const char *path,
105  char *buf, size_t size)
106 {
107  const char *l = buf;
108  size_t llen;
109  char *s;
110  int dotdots;
111  int i;
112 
113  if (l[0] != '/' || d->base[0] != '/')
114  return;
115 
116  strip_common(&l, &path);
117  if (l - buf < (long) d->baselen)
118  return;
119 
120  dotdots = count_components(path);
121  if (!dotdots)
122  return;
123  dotdots--;
124 
125  llen = strlen(l);
126  if (dotdots * 3 + llen + 2 > size)
127  return;
128 
129  s = buf + dotdots * 3;
130  if (llen)
131  memmove(s, l, llen + 1);
132  else if (!dotdots)
133  strcpy(s, ".");
134  else
135  *s = '\0';
136 
137  for (s = buf, i = 0; i < dotdots; i++, s += 3)
138  memcpy(s, "../", 3);
139 }
140 
141 
142 static int subdir_readlink(const char *path, char *buf, size_t size)
143 {
144  struct subdir *d = subdir_get();
145  char *newpath;
146  int err = subdir_addpath(d, path, &newpath);
147  if (!err) {
148  err = fuse_fs_readlink(d->next, newpath, buf, size);
149  if (!err && d->rellinks)
150  transform_symlink(d, newpath, buf, size);
151  free(newpath);
152  }
153  return err;
154 }
155 
156 static int subdir_opendir(const char *path, struct fuse_file_info *fi)
157 {
158  struct subdir *d = subdir_get();
159  char *newpath;
160  int err = subdir_addpath(d, path, &newpath);
161  if (!err) {
162  err = fuse_fs_opendir(d->next, newpath, fi);
163  free(newpath);
164  }
165  return err;
166 }
167 
168 static int subdir_readdir(const char *path, void *buf,
169  fuse_fill_dir_t filler, off_t offset,
170  struct fuse_file_info *fi,
171  enum fuse_readdir_flags flags)
172 {
173  struct subdir *d = subdir_get();
174  char *newpath;
175  int err = subdir_addpath(d, path, &newpath);
176  if (!err) {
177  err = fuse_fs_readdir(d->next, newpath, buf, filler, offset,
178  fi, flags);
179  free(newpath);
180  }
181  return err;
182 }
183 
184 static int subdir_releasedir(const char *path, struct fuse_file_info *fi)
185 {
186  struct subdir *d = subdir_get();
187  char *newpath;
188  int err = subdir_addpath(d, path, &newpath);
189  if (!err) {
190  err = fuse_fs_releasedir(d->next, newpath, fi);
191  free(newpath);
192  }
193  return err;
194 }
195 
196 static int subdir_mknod(const char *path, mode_t mode, dev_t rdev)
197 {
198  struct subdir *d = subdir_get();
199  char *newpath;
200  int err = subdir_addpath(d, path, &newpath);
201  if (!err) {
202  err = fuse_fs_mknod(d->next, newpath, mode, rdev);
203  free(newpath);
204  }
205  return err;
206 }
207 
208 static int subdir_mkdir(const char *path, mode_t mode)
209 {
210  struct subdir *d = subdir_get();
211  char *newpath;
212  int err = subdir_addpath(d, path, &newpath);
213  if (!err) {
214  err = fuse_fs_mkdir(d->next, newpath, mode);
215  free(newpath);
216  }
217  return err;
218 }
219 
220 static int subdir_unlink(const char *path)
221 {
222  struct subdir *d = subdir_get();
223  char *newpath;
224  int err = subdir_addpath(d, path, &newpath);
225  if (!err) {
226  err = fuse_fs_unlink(d->next, newpath);
227  free(newpath);
228  }
229  return err;
230 }
231 
232 static int subdir_rmdir(const char *path)
233 {
234  struct subdir *d = subdir_get();
235  char *newpath;
236  int err = subdir_addpath(d, path, &newpath);
237  if (!err) {
238  err = fuse_fs_rmdir(d->next, newpath);
239  free(newpath);
240  }
241  return err;
242 }
243 
244 static int subdir_symlink(const char *from, const char *path)
245 {
246  struct subdir *d = subdir_get();
247  char *newpath;
248  int err = subdir_addpath(d, path, &newpath);
249  if (!err) {
250  err = fuse_fs_symlink(d->next, from, newpath);
251  free(newpath);
252  }
253  return err;
254 }
255 
256 static int subdir_rename(const char *from, const char *to, unsigned int flags)
257 {
258  struct subdir *d = subdir_get();
259  char *newfrom;
260  char *newto;
261  int err = subdir_addpath(d, from, &newfrom);
262  if (!err) {
263  err = subdir_addpath(d, to, &newto);
264  if (!err) {
265  err = fuse_fs_rename(d->next, newfrom, newto, flags);
266  free(newto);
267  }
268  free(newfrom);
269  }
270  return err;
271 }
272 
273 static int subdir_link(const char *from, const char *to)
274 {
275  struct subdir *d = subdir_get();
276  char *newfrom;
277  char *newto;
278  int err = subdir_addpath(d, from, &newfrom);
279  if (!err) {
280  err = subdir_addpath(d, to, &newto);
281  if (!err) {
282  err = fuse_fs_link(d->next, newfrom, newto);
283  free(newto);
284  }
285  free(newfrom);
286  }
287  return err;
288 }
289 
290 static int subdir_chmod(const char *path, mode_t mode,
291  struct fuse_file_info *fi)
292 {
293  struct subdir *d = subdir_get();
294  char *newpath;
295  int err = subdir_addpath(d, path, &newpath);
296  if (!err) {
297  err = fuse_fs_chmod(d->next, newpath, mode, fi);
298  free(newpath);
299  }
300  return err;
301 }
302 
303 static int subdir_chown(const char *path, uid_t uid, gid_t gid,
304  struct fuse_file_info *fi)
305 {
306  struct subdir *d = subdir_get();
307  char *newpath;
308  int err = subdir_addpath(d, path, &newpath);
309  if (!err) {
310  err = fuse_fs_chown(d->next, newpath, uid, gid, fi);
311  free(newpath);
312  }
313  return err;
314 }
315 
316 static int subdir_truncate(const char *path, off_t size,
317  struct fuse_file_info *fi)
318 {
319  struct subdir *d = subdir_get();
320  char *newpath;
321  int err = subdir_addpath(d, path, &newpath);
322  if (!err) {
323  err = fuse_fs_truncate(d->next, newpath, size, fi);
324  free(newpath);
325  }
326  return err;
327 }
328 
329 static int subdir_utimens(const char *path, const struct timespec ts[2],
330  struct fuse_file_info *fi)
331 {
332  struct subdir *d = subdir_get();
333  char *newpath;
334  int err = subdir_addpath(d, path, &newpath);
335  if (!err) {
336  err = fuse_fs_utimens(d->next, newpath, ts, fi);
337  free(newpath);
338  }
339  return err;
340 }
341 
342 static int subdir_create(const char *path, mode_t mode,
343  struct fuse_file_info *fi)
344 {
345  struct subdir *d = subdir_get();
346  char *newpath;
347  int err = subdir_addpath(d, path, &newpath);
348  if (!err) {
349  err = fuse_fs_create(d->next, newpath, mode, fi);
350  free(newpath);
351  }
352  return err;
353 }
354 
355 static int subdir_open(const char *path, struct fuse_file_info *fi)
356 {
357  struct subdir *d = subdir_get();
358  char *newpath;
359  int err = subdir_addpath(d, path, &newpath);
360  if (!err) {
361  err = fuse_fs_open(d->next, newpath, fi);
362  free(newpath);
363  }
364  return err;
365 }
366 
367 static int subdir_read_buf(const char *path, struct fuse_bufvec **bufp,
368  size_t size, off_t offset, struct fuse_file_info *fi)
369 {
370  struct subdir *d = subdir_get();
371  char *newpath;
372  int err = subdir_addpath(d, path, &newpath);
373  if (!err) {
374  err = fuse_fs_read_buf(d->next, newpath, bufp, size, offset, fi);
375  free(newpath);
376  }
377  return err;
378 }
379 
380 static int subdir_write_buf(const char *path, struct fuse_bufvec *buf,
381  off_t offset, struct fuse_file_info *fi)
382 {
383  struct subdir *d = subdir_get();
384  char *newpath;
385  int err = subdir_addpath(d, path, &newpath);
386  if (!err) {
387  err = fuse_fs_write_buf(d->next, newpath, buf, offset, fi);
388  free(newpath);
389  }
390  return err;
391 }
392 
393 static int subdir_statfs(const char *path, struct statvfs *stbuf)
394 {
395  struct subdir *d = subdir_get();
396  char *newpath;
397  int err = subdir_addpath(d, path, &newpath);
398  if (!err) {
399  err = fuse_fs_statfs(d->next, newpath, stbuf);
400  free(newpath);
401  }
402  return err;
403 }
404 
405 static int subdir_flush(const char *path, struct fuse_file_info *fi)
406 {
407  struct subdir *d = subdir_get();
408  char *newpath;
409  int err = subdir_addpath(d, path, &newpath);
410  if (!err) {
411  err = fuse_fs_flush(d->next, newpath, fi);
412  free(newpath);
413  }
414  return err;
415 }
416 
417 static int subdir_release(const char *path, struct fuse_file_info *fi)
418 {
419  struct subdir *d = subdir_get();
420  char *newpath;
421  int err = subdir_addpath(d, path, &newpath);
422  if (!err) {
423  err = fuse_fs_release(d->next, newpath, fi);
424  free(newpath);
425  }
426  return err;
427 }
428 
429 static int subdir_fsync(const char *path, int isdatasync,
430  struct fuse_file_info *fi)
431 {
432  struct subdir *d = subdir_get();
433  char *newpath;
434  int err = subdir_addpath(d, path, &newpath);
435  if (!err) {
436  err = fuse_fs_fsync(d->next, newpath, isdatasync, fi);
437  free(newpath);
438  }
439  return err;
440 }
441 
442 static int subdir_fsyncdir(const char *path, int isdatasync,
443  struct fuse_file_info *fi)
444 {
445  struct subdir *d = subdir_get();
446  char *newpath;
447  int err = subdir_addpath(d, path, &newpath);
448  if (!err) {
449  err = fuse_fs_fsyncdir(d->next, newpath, isdatasync, fi);
450  free(newpath);
451  }
452  return err;
453 }
454 
455 static int subdir_setxattr(const char *path, const char *name,
456  const char *value, size_t size, int flags)
457 {
458  struct subdir *d = subdir_get();
459  char *newpath;
460  int err = subdir_addpath(d, path, &newpath);
461  if (!err) {
462  err = fuse_fs_setxattr(d->next, newpath, name, value, size,
463  flags);
464  free(newpath);
465  }
466  return err;
467 }
468 
469 static int subdir_getxattr(const char *path, const char *name, char *value,
470  size_t size)
471 {
472  struct subdir *d = subdir_get();
473  char *newpath;
474  int err = subdir_addpath(d, path, &newpath);
475  if (!err) {
476  err = fuse_fs_getxattr(d->next, newpath, name, value, size);
477  free(newpath);
478  }
479  return err;
480 }
481 
482 static int subdir_listxattr(const char *path, char *list, size_t size)
483 {
484  struct subdir *d = subdir_get();
485  char *newpath;
486  int err = subdir_addpath(d, path, &newpath);
487  if (!err) {
488  err = fuse_fs_listxattr(d->next, newpath, list, size);
489  free(newpath);
490  }
491  return err;
492 }
493 
494 static int subdir_removexattr(const char *path, const char *name)
495 {
496  struct subdir *d = subdir_get();
497  char *newpath;
498  int err = subdir_addpath(d, path, &newpath);
499  if (!err) {
500  err = fuse_fs_removexattr(d->next, newpath, name);
501  free(newpath);
502  }
503  return err;
504 }
505 
506 static int subdir_lock(const char *path, struct fuse_file_info *fi, int cmd,
507  struct flock *lock)
508 {
509  struct subdir *d = subdir_get();
510  char *newpath;
511  int err = subdir_addpath(d, path, &newpath);
512  if (!err) {
513  err = fuse_fs_lock(d->next, newpath, fi, cmd, lock);
514  free(newpath);
515  }
516  return err;
517 }
518 
519 static int subdir_flock(const char *path, struct fuse_file_info *fi, int op)
520 {
521  struct subdir *d = subdir_get();
522  char *newpath;
523  int err = subdir_addpath(d, path, &newpath);
524  if (!err) {
525  err = fuse_fs_flock(d->next, newpath, fi, op);
526  free(newpath);
527  }
528  return err;
529 }
530 
531 static int subdir_bmap(const char *path, size_t blocksize, uint64_t *idx)
532 {
533  struct subdir *d = subdir_get();
534  char *newpath;
535  int err = subdir_addpath(d, path, &newpath);
536  if (!err) {
537  err = fuse_fs_bmap(d->next, newpath, blocksize, idx);
538  free(newpath);
539  }
540  return err;
541 }
542 
543 static off_t subdir_lseek(const char *path, off_t off, int whence,
544  struct fuse_file_info *fi)
545 {
546  struct subdir *ic = subdir_get();
547  char *newpath;
548  int res = subdir_addpath(ic, path, &newpath);
549  if (!res) {
550  res = fuse_fs_lseek(ic->next, newpath, off, whence, fi);
551  free(newpath);
552  }
553  return res;
554 }
555 
556 static void *subdir_init(struct fuse_conn_info *conn,
557  struct fuse_config *cfg)
558 {
559  struct subdir *d = subdir_get();
560  fuse_fs_init(d->next, conn, cfg);
561  /* Don't touch cfg->nullpath_ok, we can work with
562  either */
563  return d;
564 }
565 
566 static void subdir_destroy(void *data)
567 {
568  struct subdir *d = data;
569  fuse_fs_destroy(d->next);
570  free(d->base);
571  free(d);
572 }
573 
574 static const struct fuse_operations subdir_oper = {
575  .destroy = subdir_destroy,
576  .init = subdir_init,
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,
589  .link = subdir_link,
590  .chmod = subdir_chmod,
591  .chown = subdir_chown,
592  .truncate = subdir_truncate,
593  .utimens = subdir_utimens,
594  .create = subdir_create,
595  .open = subdir_open,
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,
607  .lock = subdir_lock,
608  .flock = subdir_flock,
609  .bmap = subdir_bmap,
610  .lseek = subdir_lseek,
611 };
612 
613 static const struct fuse_opt subdir_opts[] = {
614  FUSE_OPT_KEY("-h", 0),
615  FUSE_OPT_KEY("--help", 0),
616  { "subdir=%s", offsetof(struct subdir, base), 0 },
617  { "rellinks", offsetof(struct subdir, rellinks), 1 },
618  { "norellinks", offsetof(struct subdir, rellinks), 0 },
620 };
621 
622 static void subdir_help(void)
623 {
624  printf(
625 " -o subdir=DIR prepend this directory to all paths (mandatory)\n"
626 " -o [no]rellinks transform absolute symlinks to relative\n");
627 }
628 
629 static int subdir_opt_proc(void *data, const char *arg, int key,
630  struct fuse_args *outargs)
631 {
632  (void) data; (void) arg; (void) outargs;
633 
634  if (!key) {
635  subdir_help();
636  return -1;
637  }
638 
639  return 1;
640 }
641 
642 static struct fuse_fs *subdir_new(struct fuse_args *args,
643  struct fuse_fs *next[])
644 {
645  struct fuse_fs *fs;
646  struct subdir *d;
647 
648  d = calloc(1, sizeof(struct subdir));
649  if (d == NULL) {
650  fuse_log(FUSE_LOG_ERR, "fuse-subdir: memory allocation failed\n");
651  return NULL;
652  }
653 
654  if (fuse_opt_parse(args, d, subdir_opts, subdir_opt_proc) == -1)
655  goto out_free;
656 
657  if (!next[0] || next[1]) {
658  fuse_log(FUSE_LOG_ERR, "fuse-subdir: exactly one next filesystem required\n");
659  goto out_free;
660  }
661 
662  if (!d->base) {
663  fuse_log(FUSE_LOG_ERR, "fuse-subdir: missing 'subdir' option\n");
664  goto out_free;
665  }
666 
667  if (d->base[0] && d->base[strlen(d->base)-1] != '/') {
668  char *tmp = realloc(d->base, strlen(d->base) + 2);
669  if (!tmp) {
670  fuse_log(FUSE_LOG_ERR, "fuse-subdir: memory allocation failed\n");
671  goto out_free;
672  }
673  d->base = tmp;
674  strcat(d->base, "/");
675  }
676  d->baselen = strlen(d->base);
677  d->next = next[0];
678  fs = fuse_fs_new(&subdir_oper, sizeof(subdir_oper), d);
679  if (!fs)
680  goto out_free;
681  return fs;
682 
683 out_free:
684  free(d->base);
685  free(d);
686  return NULL;
687 }
688 
689 FUSE_REGISTER_MODULE(subdir, subdir_new);
int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc)
Definition: fuse_opt.c:398
fuse_readdir_flags
Definition: fuse.h:42
#define FUSE_OPT_KEY(templ, key)
Definition: fuse_opt.h:98
#define FUSE_REGISTER_MODULE(name_, factory_)
Definition: fuse.h:1270
#define FUSE_OPT_END
Definition: fuse_opt.h:104
void * private_data
Definition: fuse.h:814
struct fuse_fs * fuse_fs_new(const struct fuse_operations *op, size_t op_size, void *private_data)
Definition: fuse.c:4811
int(* fuse_fill_dir_t)(void *buf, const char *name, const struct stat *stbuf, off_t off, enum fuse_fill_dir_flags flags)
Definition: fuse.h:85
void fuse_log(enum fuse_log_level level, const char *fmt,...)
Definition: fuse_log.c:33
struct fuse_context * fuse_get_context(void)
Definition: fuse.c:4607
void(* destroy)(void *private_data)
Definition: fuse.h:589