Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/filesystems/fuse/fuse_mnt.c
29271 views
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
19
static char *content;
20
static size_t content_size = 0;
21
static const char test_path[] = "/test";
22
23
static 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
43
static 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
56
static 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
64
static 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
84
static 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
110
static 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
134
static 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
143
int main(int argc, char *argv[])
144
{
145
return fuse_main(argc, argv, &memfd_ops, NULL);
146
}
147
148