"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.2.1/example/passthrough.c" (14 Nov 2017, 8705 Bytes) of package /linux/misc/fuse-3.2.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "passthrough.c": 3.0.2_vs_3.1.0.

    1 /*
    2   FUSE: Filesystem in Userspace
    3   Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
    4   Copyright (C) 2011       Sebastian Pipping <sebastian@pipping.org>
    5 
    6   This program can be distributed under the terms of the GNU GPL.
    7   See the file COPYING.
    8 */
    9 
   10 /** @file
   11  *
   12  * This file system mirrors the existing file system hierarchy of the
   13  * system, starting at the root file system. This is implemented by
   14  * just "passing through" all requests to the corresponding user-space
   15  * libc functions. Its performance is terrible.
   16  *
   17  * Compile with
   18  *
   19  *     gcc -Wall passthrough.c `pkg-config fuse3 --cflags --libs` -o passthrough
   20  *
   21  * ## Source code ##
   22  * \include passthrough.c
   23  */
   24 
   25 
   26 #define FUSE_USE_VERSION 31
   27 
   28 #ifdef HAVE_CONFIG_H
   29 #include <config.h>
   30 #endif
   31 
   32 #ifdef linux
   33 /* For pread()/pwrite()/utimensat() */
   34 #define _XOPEN_SOURCE 700
   35 #endif
   36 
   37 #include <fuse.h>
   38 #include <stdio.h>
   39 #include <string.h>
   40 #include <unistd.h>
   41 #include <fcntl.h>
   42 #include <sys/stat.h>
   43 #include <dirent.h>
   44 #include <errno.h>
   45 #include <sys/time.h>
   46 #ifdef HAVE_SETXATTR
   47 #include <sys/xattr.h>
   48 #endif
   49 
   50 static void *xmp_init(struct fuse_conn_info *conn,
   51               struct fuse_config *cfg)
   52 {
   53     (void) conn;
   54     cfg->use_ino = 1;
   55 
   56     /* Pick up changes from lower filesystem right away. This is
   57        also necessary for better hardlink support. When the kernel
   58        calls the unlink() handler, it does not know the inode of
   59        the to-be-removed entry and can therefore not invalidate
   60        the cache of the associated inode - resulting in an
   61        incorrect st_nlink value being reported for any remaining
   62        hardlinks to this inode. */
   63     cfg->entry_timeout = 0;
   64     cfg->attr_timeout = 0;
   65     cfg->negative_timeout = 0;
   66 
   67     return NULL;
   68 }
   69 
   70 static int xmp_getattr(const char *path, struct stat *stbuf,
   71                struct fuse_file_info *fi)
   72 {
   73     (void) fi;
   74     int res;
   75 
   76     res = lstat(path, stbuf);
   77     if (res == -1)
   78         return -errno;
   79 
   80     return 0;
   81 }
   82 
   83 static int xmp_access(const char *path, int mask)
   84 {
   85     int res;
   86 
   87     res = access(path, mask);
   88     if (res == -1)
   89         return -errno;
   90 
   91     return 0;
   92 }
   93 
   94 static int xmp_readlink(const char *path, char *buf, size_t size)
   95 {
   96     int res;
   97 
   98     res = readlink(path, buf, size - 1);
   99     if (res == -1)
  100         return -errno;
  101 
  102     buf[res] = '\0';
  103     return 0;
  104 }
  105 
  106 
  107 static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
  108                off_t offset, struct fuse_file_info *fi,
  109                enum fuse_readdir_flags flags)
  110 {
  111     DIR *dp;
  112     struct dirent *de;
  113 
  114     (void) offset;
  115     (void) fi;
  116     (void) flags;
  117 
  118     dp = opendir(path);
  119     if (dp == NULL)
  120         return -errno;
  121 
  122     while ((de = readdir(dp)) != NULL) {
  123         struct stat st;
  124         memset(&st, 0, sizeof(st));
  125         st.st_ino = de->d_ino;
  126         st.st_mode = de->d_type << 12;
  127         if (filler(buf, de->d_name, &st, 0, 0))
  128             break;
  129     }
  130 
  131     closedir(dp);
  132     return 0;
  133 }
  134 
  135 static int xmp_mknod(const char *path, mode_t mode, dev_t rdev)
  136 {
  137     int res;
  138 
  139     /* On Linux this could just be 'mknod(path, mode, rdev)' but this
  140        is more portable */
  141     if (S_ISREG(mode)) {
  142         res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode);
  143         if (res >= 0)
  144             res = close(res);
  145     } else if (S_ISFIFO(mode))
  146         res = mkfifo(path, mode);
  147     else
  148         res = mknod(path, mode, rdev);
  149     if (res == -1)
  150         return -errno;
  151 
  152     return 0;
  153 }
  154 
  155 static int xmp_mkdir(const char *path, mode_t mode)
  156 {
  157     int res;
  158 
  159     res = mkdir(path, mode);
  160     if (res == -1)
  161         return -errno;
  162 
  163     return 0;
  164 }
  165 
  166 static int xmp_unlink(const char *path)
  167 {
  168     int res;
  169 
  170     res = unlink(path);
  171     if (res == -1)
  172         return -errno;
  173 
  174     return 0;
  175 }
  176 
  177 static int xmp_rmdir(const char *path)
  178 {
  179     int res;
  180 
  181     res = rmdir(path);
  182     if (res == -1)
  183         return -errno;
  184 
  185     return 0;
  186 }
  187 
  188 static int xmp_symlink(const char *from, const char *to)
  189 {
  190     int res;
  191 
  192     res = symlink(from, to);
  193     if (res == -1)
  194         return -errno;
  195 
  196     return 0;
  197 }
  198 
  199 static int xmp_rename(const char *from, const char *to, unsigned int flags)
  200 {
  201     int res;
  202 
  203     if (flags)
  204         return -EINVAL;
  205 
  206     res = rename(from, to);
  207     if (res == -1)
  208         return -errno;
  209 
  210     return 0;
  211 }
  212 
  213 static int xmp_link(const char *from, const char *to)
  214 {
  215     int res;
  216 
  217     res = link(from, to);
  218     if (res == -1)
  219         return -errno;
  220 
  221     return 0;
  222 }
  223 
  224 static int xmp_chmod(const char *path, mode_t mode,
  225              struct fuse_file_info *fi)
  226 {
  227     (void) fi;
  228     int res;
  229 
  230     res = chmod(path, mode);
  231     if (res == -1)
  232         return -errno;
  233 
  234     return 0;
  235 }
  236 
  237 static int xmp_chown(const char *path, uid_t uid, gid_t gid,
  238              struct fuse_file_info *fi)
  239 {
  240     (void) fi;
  241     int res;
  242 
  243     res = lchown(path, uid, gid);
  244     if (res == -1)
  245         return -errno;
  246 
  247     return 0;
  248 }
  249 
  250 static int xmp_truncate(const char *path, off_t size,
  251             struct fuse_file_info *fi)
  252 {
  253     int res;
  254 
  255     if (fi != NULL)
  256         res = ftruncate(fi->fh, size);
  257     else
  258         res = truncate(path, size);
  259     if (res == -1)
  260         return -errno;
  261 
  262     return 0;
  263 }
  264 
  265 #ifdef HAVE_UTIMENSAT
  266 static int xmp_utimens(const char *path, const struct timespec ts[2],
  267                struct fuse_file_info *fi)
  268 {
  269     (void) fi;
  270     int res;
  271 
  272     /* don't use utime/utimes since they follow symlinks */
  273     res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);
  274     if (res == -1)
  275         return -errno;
  276 
  277     return 0;
  278 }
  279 #endif
  280 
  281 static int xmp_create(const char *path, mode_t mode,
  282               struct fuse_file_info *fi)
  283 {
  284     int res;
  285 
  286     res = open(path, fi->flags, mode);
  287     if (res == -1)
  288         return -errno;
  289 
  290     fi->fh = res;
  291     return 0;
  292 }
  293 
  294 static int xmp_open(const char *path, struct fuse_file_info *fi)
  295 {
  296     int res;
  297 
  298     res = open(path, fi->flags);
  299     if (res == -1)
  300         return -errno;
  301 
  302     fi->fh = res;
  303     return 0;
  304 }
  305 
  306 static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
  307             struct fuse_file_info *fi)
  308 {
  309     int fd;
  310     int res;
  311 
  312     if(fi == NULL)
  313         fd = open(path, O_RDONLY);
  314     else
  315         fd = fi->fh;
  316     
  317     if (fd == -1)
  318         return -errno;
  319 
  320     res = pread(fd, buf, size, offset);
  321     if (res == -1)
  322         res = -errno;
  323 
  324     if(fi == NULL)
  325         close(fd);
  326     return res;
  327 }
  328 
  329 static int xmp_write(const char *path, const char *buf, size_t size,
  330              off_t offset, struct fuse_file_info *fi)
  331 {
  332     int fd;
  333     int res;
  334 
  335     (void) fi;
  336     if(fi == NULL)
  337         fd = open(path, O_WRONLY);
  338     else
  339         fd = fi->fh;
  340     
  341     if (fd == -1)
  342         return -errno;
  343 
  344     res = pwrite(fd, buf, size, offset);
  345     if (res == -1)
  346         res = -errno;
  347 
  348     if(fi == NULL)
  349         close(fd);
  350     return res;
  351 }
  352 
  353 static int xmp_statfs(const char *path, struct statvfs *stbuf)
  354 {
  355     int res;
  356 
  357     res = statvfs(path, stbuf);
  358     if (res == -1)
  359         return -errno;
  360 
  361     return 0;
  362 }
  363 
  364 static int xmp_release(const char *path, struct fuse_file_info *fi)
  365 {
  366     (void) path;
  367     close(fi->fh);
  368     return 0;
  369 }
  370 
  371 static int xmp_fsync(const char *path, int isdatasync,
  372              struct fuse_file_info *fi)
  373 {
  374     /* Just a stub.  This method is optional and can safely be left
  375        unimplemented */
  376 
  377     (void) path;
  378     (void) isdatasync;
  379     (void) fi;
  380     return 0;
  381 }
  382 
  383 #ifdef HAVE_POSIX_FALLOCATE
  384 static int xmp_fallocate(const char *path, int mode,
  385             off_t offset, off_t length, struct fuse_file_info *fi)
  386 {
  387     int fd;
  388     int res;
  389 
  390     (void) fi;
  391 
  392     if (mode)
  393         return -EOPNOTSUPP;
  394 
  395     if(fi == NULL)
  396         fd = open(path, O_WRONLY);
  397     else
  398         fd = fi->fh;
  399     
  400     if (fd == -1)
  401         return -errno;
  402 
  403     res = -posix_fallocate(fd, offset, length);
  404 
  405     if(fi == NULL)
  406         close(fd);
  407     return res;
  408 }
  409 #endif
  410 
  411 #ifdef HAVE_SETXATTR
  412 /* xattr operations are optional and can safely be left unimplemented */
  413 static int xmp_setxattr(const char *path, const char *name, const char *value,
  414             size_t size, int flags)
  415 {
  416     int res = lsetxattr(path, name, value, size, flags);
  417     if (res == -1)
  418         return -errno;
  419     return 0;
  420 }
  421 
  422 static int xmp_getxattr(const char *path, const char *name, char *value,
  423             size_t size)
  424 {
  425     int res = lgetxattr(path, name, value, size);
  426     if (res == -1)
  427         return -errno;
  428     return res;
  429 }
  430 
  431 static int xmp_listxattr(const char *path, char *list, size_t size)
  432 {
  433     int res = llistxattr(path, list, size);
  434     if (res == -1)
  435         return -errno;
  436     return res;
  437 }
  438 
  439 static int xmp_removexattr(const char *path, const char *name)
  440 {
  441     int res = lremovexattr(path, name);
  442     if (res == -1)
  443         return -errno;
  444     return 0;
  445 }
  446 #endif /* HAVE_SETXATTR */
  447 
  448 static struct fuse_operations xmp_oper = {
  449     .init           = xmp_init,
  450     .getattr    = xmp_getattr,
  451     .access     = xmp_access,
  452     .readlink   = xmp_readlink,
  453     .readdir    = xmp_readdir,
  454     .mknod      = xmp_mknod,
  455     .mkdir      = xmp_mkdir,
  456     .symlink    = xmp_symlink,
  457     .unlink     = xmp_unlink,
  458     .rmdir      = xmp_rmdir,
  459     .rename     = xmp_rename,
  460     .link       = xmp_link,
  461     .chmod      = xmp_chmod,
  462     .chown      = xmp_chown,
  463     .truncate   = xmp_truncate,
  464 #ifdef HAVE_UTIMENSAT
  465     .utimens    = xmp_utimens,
  466 #endif
  467     .open       = xmp_open,
  468     .create     = xmp_create,
  469     .read       = xmp_read,
  470     .write      = xmp_write,
  471     .statfs     = xmp_statfs,
  472     .release    = xmp_release,
  473     .fsync      = xmp_fsync,
  474 #ifdef HAVE_POSIX_FALLOCATE
  475     .fallocate  = xmp_fallocate,
  476 #endif
  477 #ifdef HAVE_SETXATTR
  478     .setxattr   = xmp_setxattr,
  479     .getxattr   = xmp_getxattr,
  480     .listxattr  = xmp_listxattr,
  481     .removexattr    = xmp_removexattr,
  482 #endif
  483 };
  484 
  485 int main(int argc, char *argv[])
  486 {
  487     umask(0);
  488     return fuse_main(argc, argv, &xmp_oper, NULL);
  489 }