Created
September 23, 2019 12:27
-
-
Save syjcnss/8b8cee1bf8ddfe2cbacc24f1375e1351 to your computer and use it in GitHub Desktop.
libfuse hello example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
FUSE: Filesystem in Userspace | |
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> | |
This program can be distributed under the terms of the GNU GPL. | |
See the file COPYING. | |
*/ | |
/** @file | |
* | |
* minimal example filesystem using high-level API | |
* | |
* Compile with: | |
* | |
* gcc -Wall hello.c `pkg-config fuse3 --cflags --libs` -o hello | |
* | |
* ## Source code ## | |
* \include hello.c | |
*/ | |
#define FUSE_USE_VERSION 31 | |
#include <fuse.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <stddef.h> | |
#include <assert.h> | |
/* | |
* Command line options | |
* | |
* We can't set default values for the char* fields here because | |
* fuse_opt_parse would attempt to free() them when the user specifies | |
* different values on the command line. | |
*/ | |
static struct options { | |
const char *filename; | |
const char *contents; | |
int show_help; | |
} options; | |
#define OPTION(t, p) \ | |
{ t, offsetof(struct options, p), 1 } | |
static const struct fuse_opt option_spec[] = { | |
OPTION("--name=%s", filename), | |
OPTION("--contents=%s", contents), | |
OPTION("-h", show_help), | |
OPTION("--help", show_help), | |
FUSE_OPT_END | |
}; | |
static void *hello_init(struct fuse_conn_info *conn) | |
{ | |
return NULL; | |
} | |
static int hello_getattr(const char *path, struct stat *stbuf) | |
{ | |
int res = 0; | |
memset(stbuf, 0, sizeof(struct stat)); | |
if (strcmp(path, "/") == 0) { | |
stbuf->st_mode = S_IFDIR | 0755; | |
stbuf->st_nlink = 2; | |
} else if (strcmp(path+1, options.filename) == 0) { | |
stbuf->st_mode = S_IFREG | 0444; | |
stbuf->st_nlink = 1; | |
stbuf->st_size = strlen(options.contents); | |
} else | |
res = -ENOENT; | |
return res; | |
} | |
static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, | |
off_t offset, struct fuse_file_info *fi) | |
{ | |
(void) offset; | |
(void) fi; | |
if (strcmp(path, "/") != 0) | |
return -ENOENT; | |
filler(buf, ".", NULL, 0); | |
filler(buf, "..", NULL, 0); | |
filler(buf, options.filename, NULL, 0); | |
return 0; | |
} | |
static int hello_open(const char *path, struct fuse_file_info *fi) | |
{ | |
if (strcmp(path+1, options.filename) != 0) | |
return -ENOENT; | |
if ((fi->flags & O_ACCMODE) != O_RDONLY) | |
return -EACCES; | |
return 0; | |
} | |
static int hello_read(const char *path, char *buf, size_t size, off_t offset, | |
struct fuse_file_info *fi) | |
{ | |
size_t len; | |
(void) fi; | |
if(strcmp(path+1, options.filename) != 0) | |
return -ENOENT; | |
len = strlen(options.contents); | |
if (offset < len) { | |
if (offset + size > len) | |
size = len - offset; | |
memcpy(buf, options.contents + offset, size); | |
} else | |
size = 0; | |
return size; | |
} | |
static struct fuse_operations hello_oper = { | |
.init = hello_init, | |
.getattr = hello_getattr, | |
.readdir = hello_readdir, | |
.open = hello_open, | |
.read = hello_read, | |
}; | |
static void show_help(const char *progname) | |
{ | |
printf("usage: %s [options] <mountpoint>\n\n", progname); | |
printf("File-system specific options:\n" | |
" --name=<s> Name of the \"hello\" file\n" | |
" (default: \"hello\")\n" | |
" --contents=<s> Contents \"hello\" file\n" | |
" (default \"Hello, World!\\n\")\n" | |
"\n"); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
int ret; | |
struct fuse_args args = FUSE_ARGS_INIT(argc, argv); | |
/* Set defaults -- we have to use strdup so that | |
fuse_opt_parse can free the defaults if other | |
values are specified */ | |
options.filename = strdup("hello"); | |
options.contents = strdup("Hello World!\n"); | |
/* Parse options */ | |
if (fuse_opt_parse(&args, &options, option_spec, NULL) == -1) | |
return 1; | |
/* When --help is specified, first print our own file-system | |
specific help text, then signal fuse_main to show | |
additional help (by adding `--help` to the options again) | |
without usage: line (by setting argv[0] to the empty | |
string) */ | |
if (options.show_help) { | |
show_help(argv[0]); | |
assert(fuse_opt_add_arg(&args, "--help") == 0); | |
args.argv[0][0] = '\0'; | |
} | |
ret = fuse_main(args.argc, args.argv, &hello_oper, NULL); | |
fuse_opt_free_args(&args); | |
return ret; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment