Skip to content

Instantly share code, notes, and snippets.

@furandon-pig
Last active December 5, 2020 03:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save furandon-pig/b9aa17f1b85b30dd15b948d588ca275e to your computer and use it in GitHub Desktop.
Save furandon-pig/b9aa17f1b85b30dd15b948d588ca275e to your computer and use it in GitHub Desktop.
broccofsその1(FUSEサンプル)です。
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
Copyright (C) 2020 furandon_pig <furandon.pig@gmail.com>
This program can be distributed under the terms of the GNU GPLv2.
See the file COPYING.
*/
/*
* gcc -g -o brocco brocco.c `pkg-config fuse3 --cflags --libs`
*/
#define FUSE_USE_VERSION 31
#include <fuse.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <assert.h>
static struct options {
const char *filename;
const char *contents;
int show_help;
int count;
int max;
char **messages;
} options;
#define OPTION(t, p) \
{ t, offsetof(struct options, p), 1 }
static const struct fuse_opt option_spec[] = {
FUSE_OPT_END
};
static void *hello_init(struct fuse_conn_info *conn,
struct fuse_config *cfg)
{
(void) conn;
cfg->kernel_cache = 0; // OS側でデータをキャッシュさせない。
return NULL;
}
static int hello_getattr(const char *path, struct stat *stbuf,
struct fuse_file_info *fi)
{
(void) fi;
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,
enum fuse_readdir_flags flags)
{
(void) offset;
(void) fi;
(void) flags;
if (strcmp(path, "/") != 0)
return -ENOENT;
filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0, 0);
filler(buf, options.filename, NULL, 0, 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);
memcpy(buf, options.contents, len);
if (++(options.count) >= options.max) {
options.count = 0;
}
// 参照するデータを切り替える。
options.contents = options.messages[options.count];
return size;
}
static const struct fuse_operations hello_oper = {
.init = hello_init,
.getattr = hello_getattr,
.readdir = hello_readdir,
.open = hello_open,
.read = hello_read,
};
int main(int argc, char *argv[])
{
int ret;
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
// FUSEマウント時に表示させるファイル名を設定。
options.filename = strdup("brocco.txt");
// 「ブロ子の歌」データ。
char *messages[] = {
"ブロっ子\n",
"ブロっ子\n",
"ブロッコリー♪\n",
"(ブロっ子)\n",
NULL
};
// 歌詞データの行数をカウントする。
for (options.max = 0; messages[options.max] != NULL; options.max++)
;
// 歌詞データをstrdup()したうえで設定する。
options.messages = malloc(sizeof(char *) * options.count);
if (options.messages) {
for (int i = 0; i < options.max; i++) {
options.messages[i] = strdup(messages[i]);
}
}
options.count = 0;
options.contents = options.messages[0];
/* Parse options */
if (fuse_opt_parse(&args, &options, option_spec, NULL) == -1)
return 1;
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