libfuse
hello.c
Go to the documentation of this file.
1 /*
2  FUSE: Filesystem in Userspace
3  Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4 
5  This program can be distributed under the terms of the GNU GPLv2.
6  See the file COPYING.
7 */
8 
22 #define FUSE_USE_VERSION 31
23 
24 #include <fuse.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <stddef.h>
30 #include <assert.h>
31 
32 /*
33  * Command line options
34  *
35  * We can't set default values for the char* fields here because
36  * fuse_opt_parse would attempt to free() them when the user specifies
37  * different values on the command line.
38  */
39 static struct options {
40  const char *filename;
41  const char *contents;
42  int show_help;
43 } options;
44 
45 #define OPTION(t, p) \
46  { t, offsetof(struct options, p), 1 }
47 static const struct fuse_opt option_spec[] = {
48  OPTION("--name=%s", filename),
49  OPTION("--contents=%s", contents),
50  OPTION("-h", show_help),
51  OPTION("--help", show_help),
53 };
54 
55 static void *hello_init(struct fuse_conn_info *conn,
56  struct fuse_config *cfg)
57 {
58  (void) conn;
59  cfg->kernel_cache = 1;
60  return NULL;
61 }
62 
63 static int hello_getattr(const char *path, struct stat *stbuf,
64  struct fuse_file_info *fi)
65 {
66  (void) fi;
67  int res = 0;
68 
69  memset(stbuf, 0, sizeof(struct stat));
70  if (strcmp(path, "/") == 0) {
71  stbuf->st_mode = S_IFDIR | 0755;
72  stbuf->st_nlink = 2;
73  } else if (strcmp(path+1, options.filename) == 0) {
74  stbuf->st_mode = S_IFREG | 0444;
75  stbuf->st_nlink = 1;
76  stbuf->st_size = strlen(options.contents);
77  } else
78  res = -ENOENT;
79 
80  return res;
81 }
82 
83 static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
84  off_t offset, struct fuse_file_info *fi,
85  enum fuse_readdir_flags flags)
86 {
87  (void) offset;
88  (void) fi;
89  (void) flags;
90 
91  if (strcmp(path, "/") != 0)
92  return -ENOENT;
93 
94  filler(buf, ".", NULL, 0, 0);
95  filler(buf, "..", NULL, 0, 0);
96  filler(buf, options.filename, NULL, 0, 0);
97 
98  return 0;
99 }
100 
101 static int hello_open(const char *path, struct fuse_file_info *fi)
102 {
103  if (strcmp(path+1, options.filename) != 0)
104  return -ENOENT;
105 
106  if ((fi->flags & O_ACCMODE) != O_RDONLY)
107  return -EACCES;
108 
109  return 0;
110 }
111 
112 static int hello_read(const char *path, char *buf, size_t size, off_t offset,
113  struct fuse_file_info *fi)
114 {
115  size_t len;
116  (void) fi;
117  if(strcmp(path+1, options.filename) != 0)
118  return -ENOENT;
119 
120  len = strlen(options.contents);
121  if (offset < len) {
122  if (offset + size > len)
123  size = len - offset;
124  memcpy(buf, options.contents + offset, size);
125  } else
126  size = 0;
127 
128  return size;
129 }
130 
131 static const struct fuse_operations hello_oper = {
132  .init = hello_init,
133  .getattr = hello_getattr,
134  .readdir = hello_readdir,
135  .open = hello_open,
136  .read = hello_read,
137 };
138 
139 static void show_help(const char *progname)
140 {
141  printf("usage: %s [options] <mountpoint>\n\n", progname);
142  printf("File-system specific options:\n"
143  " --name=<s> Name of the \"hello\" file\n"
144  " (default: \"hello\")\n"
145  " --contents=<s> Contents \"hello\" file\n"
146  " (default \"Hello, World!\\n\")\n"
147  "\n");
148 }
149 
150 int main(int argc, char *argv[])
151 {
152  int ret;
153  struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
154 
155  /* Set defaults -- we have to use strdup so that
156  fuse_opt_parse can free the defaults if other
157  values are specified */
158  options.filename = strdup("hello");
159  options.contents = strdup("Hello World!\n");
160 
161  /* Parse options */
162  if (fuse_opt_parse(&args, &options, option_spec, NULL) == -1)
163  return 1;
164 
165  /* When --help is specified, first print our own file-system
166  specific help text, then signal fuse_main to show
167  additional help (by adding `--help` to the options again)
168  without usage: line (by setting argv[0] to the empty
169  string) */
170  if (options.show_help) {
171  show_help(argv[0]);
172  assert(fuse_opt_add_arg(&args, "--help") == 0);
173  args.argv[0][0] = '\0';
174  }
175 
176  ret = fuse_main(args.argc, args.argv, &hello_oper, NULL);
177  fuse_opt_free_args(&args);
178  return ret;
179 }
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
#define fuse_main(argc, argv, op, private_data)
Definition: fuse.h:913
fuse_readdir_flags
Definition: fuse.h:42
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
Definition: fuse_opt.c:55
void fuse_opt_free_args(struct fuse_args *args)
Definition: fuse_opt.c:34
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
#define FUSE_ARGS_INIT(argc, argv)
Definition: fuse_opt.h:123
#define FUSE_OPT_END
Definition: fuse_opt.h:104
int argc
Definition: fuse_opt.h:111
char ** argv
Definition: fuse_opt.h:114
int kernel_cache
Definition: fuse.h:240
void *(* init)(struct fuse_conn_info *conn, struct fuse_config *cfg)
Definition: fuse.h:616
unsigned long offset
Definition: fuse_opt.h:85