"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.2.3/example/ioctl.c" (11 May 2018, 4330 Bytes) of package /linux/misc/fuse-3.2.3.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 "ioctl.c": 3.2.0_vs_3.2.1.

    1 /*
    2   FUSE fioc: FUSE ioctl example
    3   Copyright (C) 2008       SUSE Linux Products GmbH
    4   Copyright (C) 2008       Tejun Heo <teheo@suse.de>
    5 
    6   This program can be distributed under the terms of the GNU GPL.
    7   See the file COPYING.
    8 */
    9 
   10 /** @file
   11  * @tableofcontents
   12  *
   13  * This example illustrates how to write a FUSE file system that can
   14  * process (a restricted set of) ioctls. It can be tested with the
   15  * ioctl_client.c program.
   16  *
   17  * Compile with:
   18  *
   19  *     gcc -Wall ioctl.c `pkg-config fuse3 --cflags --libs` -o ioctl
   20  *
   21  * ## Source code ##
   22  * \include ioctl.c
   23  */
   24 
   25 #define FUSE_USE_VERSION 31
   26 
   27 #include <fuse.h>
   28 #include <stdlib.h>
   29 #include <stdio.h>
   30 #include <string.h>
   31 #include <unistd.h>
   32 #include <time.h>
   33 #include <errno.h>
   34 
   35 #include "ioctl.h"
   36 
   37 #define FIOC_NAME   "fioc"
   38 
   39 enum {
   40     FIOC_NONE,
   41     FIOC_ROOT,
   42     FIOC_FILE,
   43 };
   44 
   45 static void *fioc_buf;
   46 static size_t fioc_size;
   47 
   48 static int fioc_resize(size_t new_size)
   49 {
   50     void *new_buf;
   51 
   52     if (new_size == fioc_size)
   53         return 0;
   54 
   55     new_buf = realloc(fioc_buf, new_size);
   56     if (!new_buf && new_size)
   57         return -ENOMEM;
   58 
   59     if (new_size > fioc_size)
   60         memset(new_buf + fioc_size, 0, new_size - fioc_size);
   61 
   62     fioc_buf = new_buf;
   63     fioc_size = new_size;
   64 
   65     return 0;
   66 }
   67 
   68 static int fioc_expand(size_t new_size)
   69 {
   70     if (new_size > fioc_size)
   71         return fioc_resize(new_size);
   72     return 0;
   73 }
   74 
   75 static int fioc_file_type(const char *path)
   76 {
   77     if (strcmp(path, "/") == 0)
   78         return FIOC_ROOT;
   79     if (strcmp(path, "/" FIOC_NAME) == 0)
   80         return FIOC_FILE;
   81     return FIOC_NONE;
   82 }
   83 
   84 static int fioc_getattr(const char *path, struct stat *stbuf,
   85             struct fuse_file_info *fi)
   86 {
   87     (void) fi;
   88     stbuf->st_uid = getuid();
   89     stbuf->st_gid = getgid();
   90     stbuf->st_atime = stbuf->st_mtime = time(NULL);
   91 
   92     switch (fioc_file_type(path)) {
   93     case FIOC_ROOT:
   94         stbuf->st_mode = S_IFDIR | 0755;
   95         stbuf->st_nlink = 2;
   96         break;
   97     case FIOC_FILE:
   98         stbuf->st_mode = S_IFREG | 0644;
   99         stbuf->st_nlink = 1;
  100         stbuf->st_size = fioc_size;
  101         break;
  102     case FIOC_NONE:
  103         return -ENOENT;
  104     }
  105 
  106     return 0;
  107 }
  108 
  109 static int fioc_open(const char *path, struct fuse_file_info *fi)
  110 {
  111     (void) fi;
  112 
  113     if (fioc_file_type(path) != FIOC_NONE)
  114         return 0;
  115     return -ENOENT;
  116 }
  117 
  118 static int fioc_do_read(char *buf, size_t size, off_t offset)
  119 {
  120     if (offset >= fioc_size)
  121         return 0;
  122 
  123     if (size > fioc_size - offset)
  124         size = fioc_size - offset;
  125 
  126     memcpy(buf, fioc_buf + offset, size);
  127 
  128     return size;
  129 }
  130 
  131 static int fioc_read(const char *path, char *buf, size_t size,
  132              off_t offset, struct fuse_file_info *fi)
  133 {
  134     (void) fi;
  135 
  136     if (fioc_file_type(path) != FIOC_FILE)
  137         return -EINVAL;
  138 
  139     return fioc_do_read(buf, size, offset);
  140 }
  141 
  142 static int fioc_do_write(const char *buf, size_t size, off_t offset)
  143 {
  144     if (fioc_expand(offset + size))
  145         return -ENOMEM;
  146 
  147     memcpy(fioc_buf + offset, buf, size);
  148 
  149     return size;
  150 }
  151 
  152 static int fioc_write(const char *path, const char *buf, size_t size,
  153               off_t offset, struct fuse_file_info *fi)
  154 {
  155     (void) fi;
  156 
  157     if (fioc_file_type(path) != FIOC_FILE)
  158         return -EINVAL;
  159 
  160     return fioc_do_write(buf, size, offset);
  161 }
  162 
  163 static int fioc_truncate(const char *path, off_t size,
  164              struct fuse_file_info *fi)
  165 {
  166     (void) fi;
  167     if (fioc_file_type(path) != FIOC_FILE)
  168         return -EINVAL;
  169 
  170     return fioc_resize(size);
  171 }
  172 
  173 static int fioc_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
  174             off_t offset, struct fuse_file_info *fi,
  175             enum fuse_readdir_flags flags)
  176 {
  177     (void) fi;
  178     (void) offset;
  179     (void) flags;
  180 
  181     if (fioc_file_type(path) != FIOC_ROOT)
  182         return -ENOENT;
  183 
  184     filler(buf, ".", NULL, 0, 0);
  185     filler(buf, "..", NULL, 0, 0);
  186     filler(buf, FIOC_NAME, NULL, 0, 0);
  187 
  188     return 0;
  189 }
  190 
  191 static int fioc_ioctl(const char *path, int cmd, void *arg,
  192               struct fuse_file_info *fi, unsigned int flags, void *data)
  193 {
  194     (void) arg;
  195     (void) fi;
  196     (void) flags;
  197 
  198     if (fioc_file_type(path) != FIOC_FILE)
  199         return -EINVAL;
  200 
  201     if (flags & FUSE_IOCTL_COMPAT)
  202         return -ENOSYS;
  203 
  204     switch (cmd) {
  205     case FIOC_GET_SIZE:
  206         *(size_t *)data = fioc_size;
  207         return 0;
  208 
  209     case FIOC_SET_SIZE:
  210         fioc_resize(*(size_t *)data);
  211         return 0;
  212     }
  213 
  214     return -EINVAL;
  215 }
  216 
  217 static struct fuse_operations fioc_oper = {
  218     .getattr    = fioc_getattr,
  219     .readdir    = fioc_readdir,
  220     .truncate   = fioc_truncate,
  221     .open       = fioc_open,
  222     .read       = fioc_read,
  223     .write      = fioc_write,
  224     .ioctl      = fioc_ioctl,
  225 };
  226 
  227 int main(int argc, char *argv[])
  228 {
  229     return fuse_main(argc, argv, &fioc_oper, NULL);
  230 }