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
21#define FUSE_USE_VERSION 31
22
23#include <fuse.h>
24#include <stdio.h>
25#include <string.h>
26#include <errno.h>
27#include <fcntl.h>
28#include <stddef.h>
29#include <assert.h>
30
31/*
32 * Command line options
33 *
34 * We can't set default values for the char* fields here because
35 * fuse_opt_parse would attempt to free() them when the user specifies
36 * different values on the command line.
37 */
38static struct options {
39 const char *filename;
40 const char *contents;
41 int show_help;
42} options;
43
44#define OPTION(t, p) { t, offsetof(struct options, p), 1 }
45static const struct fuse_opt option_spec[] = {
46 OPTION("--name=%s", filename), OPTION("--contents=%s", contents),
47 OPTION("-h", show_help), OPTION("--help", show_help), FUSE_OPT_END
48};
49
50static void *hello_init(struct fuse_conn_info *conn, struct fuse_config *cfg)
51{
52 (void)conn;
53 cfg->kernel_cache = 1;
54
55 /* Test setting flags the old way */
57 conn->want &= ~FUSE_CAP_ASYNC_READ;
58
59 return NULL;
60}
61
62static int hello_getattr(const char *path, struct stat *stbuf,
63 struct fuse_file_info *fi)
64{
65 (void)fi;
66 int res = 0;
67
68 memset(stbuf, 0, sizeof(struct stat));
69 if (strcmp(path, "/") == 0) {
70 stbuf->st_mode = S_IFDIR | 0755;
71 stbuf->st_nlink = 2;
72 } else if (strcmp(path + 1, options.filename) == 0) {
73 stbuf->st_mode = S_IFREG | 0444;
74 stbuf->st_nlink = 1;
75 stbuf->st_size = strlen(options.contents);
76 } else
77 res = -ENOENT;
78
79 return res;
80}
81
82static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
83 off_t offset, struct fuse_file_info *fi,
84 enum fuse_readdir_flags flags)
85{
86 (void)offset;
87 (void)fi;
88 (void)flags;
89
90 if (strcmp(path, "/") != 0)
91 return -ENOENT;
92
93 filler(buf, ".", NULL, 0, FUSE_FILL_DIR_DEFAULTS);
94 filler(buf, "..", NULL, 0, FUSE_FILL_DIR_DEFAULTS);
95 filler(buf, options.filename, NULL, 0, FUSE_FILL_DIR_DEFAULTS);
96
97 return 0;
98}
99
100static int hello_open(const char *path, struct fuse_file_info *fi)
101{
102 if (strcmp(path + 1, options.filename) != 0)
103 return -ENOENT;
104
105 if ((fi->flags & O_ACCMODE) != O_RDONLY)
106 return -EACCES;
107
108 return 0;
109}
110
111static int hello_read(const char *path, char *buf, size_t size, off_t offset,
112 struct fuse_file_info *fi)
113{
114 size_t len;
115 (void)fi;
116 if (strcmp(path + 1, options.filename) != 0)
117 return -ENOENT;
118
119 len = strlen(options.contents);
120 if (offset < len) {
121 if (offset + size > len)
122 size = len - offset;
123 memcpy(buf, options.contents + offset, size);
124 } else
125 size = 0;
126
127 return size;
128}
129
130static const struct fuse_operations hello_oper = {
131 .init = hello_init,
132 .getattr = hello_getattr,
133 .readdir = hello_readdir,
134 .open = hello_open,
135 .read = hello_read,
136};
137
138static void show_help(const char *progname)
139{
140 printf("usage: %s [options] <mountpoint>\n\n", progname);
141 printf("File-system specific options:\n"
142 " --name=<s> Name of the \"hello\" file\n"
143 " (default: \"hello\")\n"
144 " --contents=<s> Contents \"hello\" file\n"
145 " (default \"Hello, World!\\n\")\n"
146 "\n");
147}
148
149int main(int argc, char *argv[])
150{
151 int ret;
152 struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
153
154 /* Set defaults -- we have to use strdup so that
155 * fuse_opt_parse can free the defaults if other
156 * values are specified
157 */
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 */
171 if (options.show_help) {
172 show_help(argv[0]);
173 assert(fuse_opt_add_arg(&args, "--help") == 0);
174 args.argv[0][0] = '\0';
175 }
176
177 ret = fuse_main(args.argc, args.argv, &hello_oper, NULL);
178 fuse_opt_free_args(&args);
179 return ret;
180}
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:87
@ FUSE_FILL_DIR_DEFAULTS
Definition fuse.h:68
fuse_readdir_flags
Definition fuse.h:42
#define FUSE_CAP_ASYNC_READ
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
char ** argv
Definition fuse_opt.h:114
int32_t kernel_cache
Definition fuse.h:245
void *(* init)(struct fuse_conn_info *conn, struct fuse_config *cfg)
Definition fuse.h:641
unsigned long offset
Definition fuse_opt.h:85