File Index
Files and directories
Sign in
FILE

fuse_mnt.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/filesystems/fuse/fuse_mnt.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * fusectl test file-system
  4 * Creates a simple FUSE filesystem with a single read-write file (/test)
  5 */
  6
  7#define FUSE_USE_VERSION 26
  8
  9#include <fuse.h>
 10#include <stdio.h>
 11#include <string.h>
 12#include <errno.h>
 13#include <fcntl.h>
 14#include <stdlib.h>
 15#include <unistd.h>
 16
 17#define MAX(a, b) ((a) > (b) ? (a) : (b))
 18
 19static char *content;
 20static size_t content_size = 0;
 21static const char test_path[] = "/test";
 22
 23static int test_getattr(const char *path, struct stat *st)
 24{
 25	memset(st, 0, sizeof(*st));
 26
 27	if (!strcmp(path, "/")) {
 28		st->st_mode = S_IFDIR | 0755;
 29		st->st_nlink = 2;
 30		return 0;
 31	}
 32
 33	if (!strcmp(path, test_path)) {
 34		st->st_mode = S_IFREG | 0664;
 35		st->st_nlink = 1;
 36		st->st_size = content_size;
 37		return 0;
 38	}
 39
 40	return -ENOENT;
 41}
 42
 43static int test_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
 44			off_t offset, struct fuse_file_info *fi)
 45{
 46	if (strcmp(path, "/"))
 47		return -ENOENT;
 48
 49	filler(buf, ".", NULL, 0);
 50	filler(buf, "..", NULL, 0);
 51	filler(buf, test_path + 1, NULL, 0);
 52
 53	return 0;
 54}
 55
 56static int test_open(const char *path, struct fuse_file_info *fi)
 57{
 58	if (strcmp(path, test_path))
 59		return -ENOENT;
 60
 61	return 0;
 62}
 63
 64static int test_read(const char *path, char *buf, size_t size, off_t offset,
 65		     struct fuse_file_info *fi)
 66{
 67	if (strcmp(path, test_path) != 0)
 68		return -ENOENT;
 69
 70	if (!content || content_size == 0)
 71		return 0;
 72
 73	if (offset >= content_size)
 74		return 0;
 75
 76	if (offset + size > content_size)
 77		size = content_size - offset;
 78
 79	memcpy(buf, content + offset, size);
 80
 81	return size;
 82}
 83
 84static int test_write(const char *path, const char *buf, size_t size,
 85		      off_t offset, struct fuse_file_info *fi)
 86{
 87	size_t new_size;
 88
 89	if (strcmp(path, test_path) != 0)
 90		return -ENOENT;
 91
 92	if(offset > content_size)
 93		return -EINVAL;
 94
 95	new_size = MAX(offset + size, content_size);
 96
 97	if (new_size > content_size)
 98		content = realloc(content, new_size);
 99
100	content_size = new_size;
101
102	if (!content)
103		return -ENOMEM;
104
105	memcpy(content + offset, buf, size);
106
107	return size;
108}
109
110static int test_truncate(const char *path, off_t size)
111{
112	if (strcmp(path, test_path) != 0)
113		return -ENOENT;
114
115	if (size == 0) {
116		free(content);
117		content = NULL;
118		content_size = 0;
119		return 0;
120	}
121
122	content = realloc(content, size);
123
124	if (!content)
125		return -ENOMEM;
126
127	if (size > content_size)
128		memset(content + content_size, 0, size - content_size);
129
130	content_size = size;
131	return 0;
132}
133
134static struct fuse_operations memfd_ops = {
135	.getattr = test_getattr,
136	.readdir = test_readdir,
137	.open = test_open,
138	.read = test_read,
139	.write = test_write,
140	.truncate = test_truncate,
141};
142
143int main(int argc, char *argv[])
144{
145	return fuse_main(argc, argv, &memfd_ops, NULL);
146}
~/ Read-only file preview.