nfs-ganesha 1.4

hello_ll.c

Go to the documentation of this file.
00001 /*
00002     FUSE: Filesystem in Userspace
00003     Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
00004 
00005     This program can be distributed under the terms of the GNU GPL.
00006     See the file COPYING.
00007 
00008     gcc -Wall `pkg-config fuse --cflags --libs` hello_ll.c -o hello_ll
00009 */
00010 
00011 #define FUSE_USE_VERSION 26
00012 
00013 #include <ganesha_fuse_ll_wrap.h>
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <errno.h>
00018 #include <fcntl.h>
00019 #include <unistd.h>
00020 #include <assert.h>
00021 
00022 static const char *hello_str = "Hello World!\n";
00023 static const char *hello_name = "hello";
00024 
00025 static int hello_stat(fuse_ino_t ino, struct stat *stbuf)
00026 {
00027   stbuf->st_ino = ino;
00028   switch (ino)
00029     {
00030     case 1:
00031       stbuf->st_mode = S_IFDIR | 0755;
00032       stbuf->st_nlink = 2;
00033       break;
00034 
00035     case 2:
00036       stbuf->st_mode = S_IFREG | 0444;
00037       stbuf->st_nlink = 1;
00038       stbuf->st_size = strlen(hello_str);
00039       break;
00040 
00041     default:
00042       return -1;
00043     }
00044   return 0;
00045 }
00046 
00047 static void hello_ll_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
00048 {
00049   struct stat stbuf;
00050 
00051   (void)fi;
00052 
00053   memset(&stbuf, 0, sizeof(stbuf));
00054   if(hello_stat(ino, &stbuf) == -1)
00055     fuse_reply_err(req, ENOENT);
00056   else
00057     fuse_reply_attr(req, &stbuf, 1.0);
00058 }
00059 
00060 static void hello_ll_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
00061 {
00062   struct fuse_entry_param e;
00063 
00064   if(parent != 1 || strcmp(name, hello_name) != 0)
00065     fuse_reply_err(req, ENOENT);
00066   else
00067     {
00068       memset(&e, 0, sizeof(e));
00069       e.ino = 2;
00070       e.attr_timeout = 1.0;
00071       e.entry_timeout = 1.0;
00072       hello_stat(e.ino, &e.attr);
00073 
00074       fuse_reply_entry(req, &e);
00075     }
00076 }
00077 
00078 struct dirbuf
00079 {
00080   char *p;
00081   size_t size;
00082 };
00083 
00084 static void dirbuf_add(fuse_req_t req, struct dirbuf *b, const char *name, fuse_ino_t ino)
00085 {
00086   struct stat stbuf;
00087   size_t oldsize = b->size;
00088   b->size += fuse_add_direntry(req, NULL, 0, name, NULL, 0);
00089   b->p = (char *)realloc(b->p, b->size);
00090   memset(&stbuf, 0, sizeof(stbuf));
00091   stbuf.st_ino = ino;
00092   fuse_add_direntry(req, b->p + oldsize, b->size - oldsize, name, &stbuf, b->size);
00093 }
00094 
00095 #define min(x, y) ((x) < (y) ? (x) : (y))
00096 
00097 static int reply_buf_limited(fuse_req_t req, const char *buf, size_t bufsize,
00098                              off_t off, size_t maxsize)
00099 {
00100   if(off < bufsize)
00101     return fuse_reply_buf(req, buf + off, min(bufsize - off, maxsize));
00102   else
00103     return fuse_reply_buf(req, NULL, 0);
00104 }
00105 
00106 static void hello_ll_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
00107                              off_t off, struct fuse_file_info *fi)
00108 {
00109   (void)fi;
00110 
00111   if(ino != 1)
00112     fuse_reply_err(req, ENOTDIR);
00113   else
00114     {
00115       struct dirbuf b;
00116 
00117       memset(&b, 0, sizeof(b));
00118       dirbuf_add(req, &b, ".", 1);
00119       dirbuf_add(req, &b, "..", 1);
00120       dirbuf_add(req, &b, hello_name, 2);
00121       reply_buf_limited(req, b.p, b.size, off, size);
00122       free(b.p);
00123     }
00124 }
00125 
00126 static void hello_ll_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
00127 {
00128   if(ino != 2)
00129     fuse_reply_err(req, EISDIR);
00130   else if((fi->flags & 3) != O_RDONLY)
00131     fuse_reply_err(req, EACCES);
00132   else
00133     fuse_reply_open(req, fi);
00134 }
00135 
00136 static void hello_ll_read(fuse_req_t req, fuse_ino_t ino, size_t size,
00137                           off_t off, struct fuse_file_info *fi)
00138 {
00139   (void)fi;
00140 
00141   assert(ino == 2);
00142   reply_buf_limited(req, hello_str, strlen(hello_str), off, size);
00143 }
00144 
00145 static struct fuse_lowlevel_ops hello_ll_oper = {
00146   .lookup = hello_ll_lookup,
00147   .getattr = hello_ll_getattr,
00148   .readdir = hello_ll_readdir,
00149   .open = hello_ll_open,
00150   .read = hello_ll_read,
00151 };
00152 
00153 int main(int argc, char *argv[])
00154 {
00155   struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
00156   struct fuse_chan *ch;
00157   char *mountpoint;
00158   int err = -1;
00159 
00160   if(fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != -1 &&
00161      (ch = fuse_mount(mountpoint, &args)) != NULL)
00162     {
00163       struct fuse_session *se;
00164 
00165       se = fuse_lowlevel_new(&args, &hello_ll_oper, sizeof(hello_ll_oper), NULL);
00166       if(se != NULL)
00167         {
00168           if(fuse_set_signal_handlers(se) != -1)
00169             {
00170               fuse_session_add_chan(se, ch);
00171               err = fuse_session_loop(se);
00172               fuse_remove_signal_handlers(se);
00173               fuse_session_remove_chan(ch);
00174             }
00175           fuse_session_destroy(se);
00176         }
00177       fuse_unmount(mountpoint, ch);
00178     }
00179   fuse_opt_free_args(&args);
00180 
00181   return err ? 1 : 0;
00182 }