16881f68fSopenharmony_ci/* 26881f68fSopenharmony_ci FUSE: Filesystem in Userspace 36881f68fSopenharmony_ci Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> 46881f68fSopenharmony_ci 56881f68fSopenharmony_ci This program can be distributed under the terms of the GNU GPLv2. 66881f68fSopenharmony_ci See the file COPYING. 76881f68fSopenharmony_ci*/ 86881f68fSopenharmony_ci 96881f68fSopenharmony_ci/** @file 106881f68fSopenharmony_ci * 116881f68fSopenharmony_ci * minimal example filesystem using high-level API 126881f68fSopenharmony_ci * 136881f68fSopenharmony_ci * Compile with: 146881f68fSopenharmony_ci * 156881f68fSopenharmony_ci * gcc -Wall hello.c `pkg-config fuse3 --cflags --libs` -o hello 166881f68fSopenharmony_ci * 176881f68fSopenharmony_ci * ## Source code ## 186881f68fSopenharmony_ci * \include hello.c 196881f68fSopenharmony_ci */ 206881f68fSopenharmony_ci 216881f68fSopenharmony_ci 226881f68fSopenharmony_ci#define FUSE_USE_VERSION 31 236881f68fSopenharmony_ci 246881f68fSopenharmony_ci#include <fuse.h> 256881f68fSopenharmony_ci#include <stdio.h> 266881f68fSopenharmony_ci#include <string.h> 276881f68fSopenharmony_ci#include <errno.h> 286881f68fSopenharmony_ci#include <fcntl.h> 296881f68fSopenharmony_ci#include <stddef.h> 306881f68fSopenharmony_ci#include <assert.h> 316881f68fSopenharmony_ci 326881f68fSopenharmony_ci/* 336881f68fSopenharmony_ci * Command line options 346881f68fSopenharmony_ci * 356881f68fSopenharmony_ci * We can't set default values for the char* fields here because 366881f68fSopenharmony_ci * fuse_opt_parse would attempt to free() them when the user specifies 376881f68fSopenharmony_ci * different values on the command line. 386881f68fSopenharmony_ci */ 396881f68fSopenharmony_cistatic struct options { 406881f68fSopenharmony_ci const char *filename; 416881f68fSopenharmony_ci const char *contents; 426881f68fSopenharmony_ci int show_help; 436881f68fSopenharmony_ci} options; 446881f68fSopenharmony_ci 456881f68fSopenharmony_ci#define OPTION(t, p) \ 466881f68fSopenharmony_ci { t, offsetof(struct options, p), 1 } 476881f68fSopenharmony_cistatic const struct fuse_opt option_spec[] = { 486881f68fSopenharmony_ci OPTION("--name=%s", filename), 496881f68fSopenharmony_ci OPTION("--contents=%s", contents), 506881f68fSopenharmony_ci OPTION("-h", show_help), 516881f68fSopenharmony_ci OPTION("--help", show_help), 526881f68fSopenharmony_ci FUSE_OPT_END 536881f68fSopenharmony_ci}; 546881f68fSopenharmony_ci 556881f68fSopenharmony_cistatic void *hello_init(struct fuse_conn_info *conn, 566881f68fSopenharmony_ci struct fuse_config *cfg) 576881f68fSopenharmony_ci{ 586881f68fSopenharmony_ci (void) conn; 596881f68fSopenharmony_ci cfg->kernel_cache = 1; 606881f68fSopenharmony_ci return NULL; 616881f68fSopenharmony_ci} 626881f68fSopenharmony_ci 636881f68fSopenharmony_cistatic int hello_getattr(const char *path, struct stat *stbuf, 646881f68fSopenharmony_ci struct fuse_file_info *fi) 656881f68fSopenharmony_ci{ 666881f68fSopenharmony_ci (void) fi; 676881f68fSopenharmony_ci int res = 0; 686881f68fSopenharmony_ci 696881f68fSopenharmony_ci memset(stbuf, 0, sizeof(struct stat)); 706881f68fSopenharmony_ci if (strcmp(path, "/") == 0) { 716881f68fSopenharmony_ci stbuf->st_mode = S_IFDIR | 0755; 726881f68fSopenharmony_ci stbuf->st_nlink = 2; 736881f68fSopenharmony_ci } else if (strcmp(path+1, options.filename) == 0) { 746881f68fSopenharmony_ci stbuf->st_mode = S_IFREG | 0444; 756881f68fSopenharmony_ci stbuf->st_nlink = 1; 766881f68fSopenharmony_ci stbuf->st_size = strlen(options.contents); 776881f68fSopenharmony_ci } else 786881f68fSopenharmony_ci res = -ENOENT; 796881f68fSopenharmony_ci 806881f68fSopenharmony_ci return res; 816881f68fSopenharmony_ci} 826881f68fSopenharmony_ci 836881f68fSopenharmony_cistatic int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, 846881f68fSopenharmony_ci off_t offset, struct fuse_file_info *fi, 856881f68fSopenharmony_ci enum fuse_readdir_flags flags) 866881f68fSopenharmony_ci{ 876881f68fSopenharmony_ci (void) offset; 886881f68fSopenharmony_ci (void) fi; 896881f68fSopenharmony_ci (void) flags; 906881f68fSopenharmony_ci 916881f68fSopenharmony_ci if (strcmp(path, "/") != 0) 926881f68fSopenharmony_ci return -ENOENT; 936881f68fSopenharmony_ci 946881f68fSopenharmony_ci filler(buf, ".", NULL, 0, 0); 956881f68fSopenharmony_ci filler(buf, "..", NULL, 0, 0); 966881f68fSopenharmony_ci filler(buf, options.filename, NULL, 0, 0); 976881f68fSopenharmony_ci 986881f68fSopenharmony_ci return 0; 996881f68fSopenharmony_ci} 1006881f68fSopenharmony_ci 1016881f68fSopenharmony_cistatic int hello_open(const char *path, struct fuse_file_info *fi) 1026881f68fSopenharmony_ci{ 1036881f68fSopenharmony_ci if (strcmp(path+1, options.filename) != 0) 1046881f68fSopenharmony_ci return -ENOENT; 1056881f68fSopenharmony_ci 1066881f68fSopenharmony_ci if ((fi->flags & O_ACCMODE) != O_RDONLY) 1076881f68fSopenharmony_ci return -EACCES; 1086881f68fSopenharmony_ci 1096881f68fSopenharmony_ci return 0; 1106881f68fSopenharmony_ci} 1116881f68fSopenharmony_ci 1126881f68fSopenharmony_cistatic int hello_read(const char *path, char *buf, size_t size, off_t offset, 1136881f68fSopenharmony_ci struct fuse_file_info *fi) 1146881f68fSopenharmony_ci{ 1156881f68fSopenharmony_ci size_t len; 1166881f68fSopenharmony_ci (void) fi; 1176881f68fSopenharmony_ci if(strcmp(path+1, options.filename) != 0) 1186881f68fSopenharmony_ci return -ENOENT; 1196881f68fSopenharmony_ci 1206881f68fSopenharmony_ci len = strlen(options.contents); 1216881f68fSopenharmony_ci if (offset < len) { 1226881f68fSopenharmony_ci if (offset + size > len) 1236881f68fSopenharmony_ci size = len - offset; 1246881f68fSopenharmony_ci memcpy(buf, options.contents + offset, size); 1256881f68fSopenharmony_ci } else 1266881f68fSopenharmony_ci size = 0; 1276881f68fSopenharmony_ci 1286881f68fSopenharmony_ci return size; 1296881f68fSopenharmony_ci} 1306881f68fSopenharmony_ci 1316881f68fSopenharmony_cistatic const struct fuse_operations hello_oper = { 1326881f68fSopenharmony_ci .init = hello_init, 1336881f68fSopenharmony_ci .getattr = hello_getattr, 1346881f68fSopenharmony_ci .readdir = hello_readdir, 1356881f68fSopenharmony_ci .open = hello_open, 1366881f68fSopenharmony_ci .read = hello_read, 1376881f68fSopenharmony_ci}; 1386881f68fSopenharmony_ci 1396881f68fSopenharmony_cistatic void show_help(const char *progname) 1406881f68fSopenharmony_ci{ 1416881f68fSopenharmony_ci printf("usage: %s [options] <mountpoint>\n\n", progname); 1426881f68fSopenharmony_ci printf("File-system specific options:\n" 1436881f68fSopenharmony_ci " --name=<s> Name of the \"hello\" file\n" 1446881f68fSopenharmony_ci " (default: \"hello\")\n" 1456881f68fSopenharmony_ci " --contents=<s> Contents \"hello\" file\n" 1466881f68fSopenharmony_ci " (default \"Hello, World!\\n\")\n" 1476881f68fSopenharmony_ci "\n"); 1486881f68fSopenharmony_ci} 1496881f68fSopenharmony_ci 1506881f68fSopenharmony_ciint main(int argc, char *argv[]) 1516881f68fSopenharmony_ci{ 1526881f68fSopenharmony_ci int ret; 1536881f68fSopenharmony_ci struct fuse_args args = FUSE_ARGS_INIT(argc, argv); 1546881f68fSopenharmony_ci 1556881f68fSopenharmony_ci /* Set defaults -- we have to use strdup so that 1566881f68fSopenharmony_ci fuse_opt_parse can free the defaults if other 1576881f68fSopenharmony_ci values are specified */ 1586881f68fSopenharmony_ci options.filename = strdup("hello"); 1596881f68fSopenharmony_ci options.contents = strdup("Hello World!\n"); 1606881f68fSopenharmony_ci 1616881f68fSopenharmony_ci /* Parse options */ 1626881f68fSopenharmony_ci if (fuse_opt_parse(&args, &options, option_spec, NULL) == -1) 1636881f68fSopenharmony_ci return 1; 1646881f68fSopenharmony_ci 1656881f68fSopenharmony_ci /* When --help is specified, first print our own file-system 1666881f68fSopenharmony_ci specific help text, then signal fuse_main to show 1676881f68fSopenharmony_ci additional help (by adding `--help` to the options again) 1686881f68fSopenharmony_ci without usage: line (by setting argv[0] to the empty 1696881f68fSopenharmony_ci string) */ 1706881f68fSopenharmony_ci if (options.show_help) { 1716881f68fSopenharmony_ci show_help(argv[0]); 1726881f68fSopenharmony_ci assert(fuse_opt_add_arg(&args, "--help") == 0); 1736881f68fSopenharmony_ci args.argv[0][0] = '\0'; 1746881f68fSopenharmony_ci } 1756881f68fSopenharmony_ci 1766881f68fSopenharmony_ci ret = fuse_main(args.argc, args.argv, &hello_oper, NULL); 1776881f68fSopenharmony_ci fuse_opt_free_args(&args); 1786881f68fSopenharmony_ci return ret; 1796881f68fSopenharmony_ci} 180