-
Notifications
You must be signed in to change notification settings - Fork 4
/
fuse-test.cpp
290 lines (225 loc) · 8.83 KB
/
fuse-test.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#include <map>
#include <string>
#include <iostream>
using namespace std;
extern "C" {
#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
typedef map<int, unsigned char> FileContents;
typedef map<string, FileContents> FileMap;
static FileMap files;
/** Prüft, ob eine Datei breits existiert */
static bool file_exists(string filename) {
bool b = files.find(filename) != files.end();
cout << "file_exists: " << filename << ": " << b << endl;
return b;
}
/** Konvertiert einen String in eine map mit einzelnen bytes */
FileContents to_map(string data) {
FileContents data_map;
int i = 0;
for (string::iterator it = data.begin(); it < data.end(); ++it)
data_map[i++] = *it;
return data_map;
}
/** Entfernt einen potenziell vorhandenen / am Anfang */
static string strip_leading_slash(string filename) {
bool starts_with_slash = false;
if( filename.size() > 0 )
if( filename[0] == '/' )
starts_with_slash = true;
return starts_with_slash ? filename.substr(1, string::npos) : filename;
}
/** Liefert Dateiattribute zurück */
static int ramfs_getattr(const char* path, struct stat* stbuf) {
string filename = path;
string stripped_slash = strip_leading_slash(filename);
int res = 0;
memset(stbuf, 0, sizeof(struct stat));
stbuf->st_uid = getuid();
stbuf->st_gid = getgid();
stbuf->st_atime = stbuf->st_mtime = stbuf->st_ctime = time(NULL);
if(filename == "/") { //Attribute des Wurzelverzeichnisses
cout << "ramfs_getattr("<<filename<<"): Returning attributes for /" << endl;
stbuf->st_mode = S_IFDIR | 0777;
stbuf->st_nlink = 2;
} else if(file_exists(stripped_slash)) { //Eine existierende Datei wird gelesen
cout << "ramfs_getattr("<<stripped_slash<<"): Returning attributes" << endl;
stbuf->st_mode = S_IFREG | 0777;
stbuf->st_nlink = 1;
stbuf->st_size = files[stripped_slash].size();
} else { //Datei nicht vorhanden
cout << "ramfs_getattr("<<stripped_slash<<"): not found" << endl;
res = -ENOENT;
}
return res;
}
/** Liest den Inhalt eines Verzeichnisses aus */
static int ramfs_readdir(const char* path, void* buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info* fi) {
//Dateisystem kennt keine Unterverzeichnisse
if(strcmp(path, "/") != 0) {
cout << "ramfs_readdir("<<path<<"): Only / allowed" << endl;
return -ENOENT;
}
//Diese Dateien müssen immer existieren
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
//Füge alle Dateien hinzu
for (FileMap::iterator it = files.begin(); it != files.end(); it++)
filler(buf, it->first.c_str(), NULL, 0);
return 0;
}
/** "Öffnet" eine Datei */
static int ramfs_open(const char* path, struct fuse_file_info* fi) {
string filename = strip_leading_slash(path);
//Datei nicht vorhanden
if( !file_exists(filename) ) {
cout << "ramfs_readdir("<<filename<<"): Not found" << endl;
return -ENOENT;
}
return 0;
}
/* Liest (Teile einer) Datei */
static int ramfs_read(const char* path, char* buf, size_t size, off_t offset,
struct fuse_file_info* fi) {
string filename = strip_leading_slash(path);
//Datei nicht vorhanden
if( !file_exists(filename) ) {
cout << "ramfs_read("<<filename<<"): Not found" << endl;
return -ENOENT;
}
//Datei existiert. Lese in Puffer
FileContents &file = files[filename];
size_t len = file.size();
//Prüfe, wieviele Bytes ab welchem Offset gelesen werden können
if (offset < len) {
if (offset + size > len) {
cout << "ramfs_read("<<filename<<"): offset("<<offset<<
") + size("<<size<<") > len("<<len<<"), setting to " << len - offset << endl;
size = len - offset;
}
cout << "ramfs_read("<<filename<<"): Reading "<< size << " bytes"<<endl;
for(size_t i = 0; i < size; ++i)
buf[i] = file[offset + i];
} else { //Offset war groesser als die max. Groesse der Datei
return -EINVAL;
}
return size;
}
/** Schreibt Daten in eine (offene) Datei */
int ramfs_write(const char* path, const char* data, size_t size, off_t offset, struct fuse_file_info*) {
string filename = strip_leading_slash(path);
//Datei nicht vorhanden
if( !file_exists(filename) ) {
cout << "ramfs_write("<<filename<<"): Not found" << endl;
return -ENOENT;
}
//Datei existiert. Schreibe in Puffer
cout << "ramfs_write("<<filename<<"): Writing "<< size << " bytes startting with offset "<< offset<<endl;
FileContents &file = files[filename];
for(size_t i = 0; i < size; ++i)
file[offset + i] = data[i];
return size;
}
/** Löscht eine Datei */
int ramfs_unlink(const char *pathname) {
files.erase( strip_leading_slash(pathname) );
return 0;
}
/** Erzeugt ein neues Dateisystemelement */
int ramfs_create(const char* path, mode_t mode, struct fuse_file_info *) {
string filename = strip_leading_slash(path);
//Datei bereits vorhanden
if( file_exists(filename) ) {
cout << "ramfs_create("<<filename<<"): Already exists" << endl;
return -EEXIST;
}
//Es wird versucht, etwas anderes als eine normale Datei anzulegen
if( (mode & S_IFREG) == 0) {
cout << "ramfs_create("<<filename<<"): Only files may be created" << endl;
return -EINVAL;
}
cout << "ramfs_create("<<filename<<"): Creating empty file" << endl;
files[filename] = to_map("");
return 0;
}
int ramfs_fgetattr(const char* path, struct stat* stbuf, struct fuse_file_info *) {
cout << "ramfs_fgetattr("<<path<<"): Delegating to ramfs_getattr" << endl;
return ramfs_getattr(path, stbuf);
}
int ramfs_opendir(const char* path, struct fuse_file_info *) {
cout << "ramfs_opendir("<<path<<"): access granted" << endl;
return 0;
}
int ramfs_access(const char* path, int) {
cout << "ramfs_access("<<path<<") access granted" << endl;
return 0;
}
int ramfs_truncate(const char* path, off_t length) {
string filename = strip_leading_slash(path);
//Datei nicht vorhanden
if( !file_exists(filename) ) {
cout << "ramfs_truncate("<<filename<<"): Not found" << endl;
return -ENOENT;
}
FileContents &file = files[filename];
if ( file.size() > length ) {
cout << "ramfs_truncate("<<filename<<"): Truncating current size ("<<file.size()<<") to ("<<length<<")" << endl;
file.erase( file.find(length) , file.end() );
} else if ( file.size() < length ) {
cout << "ramfs_truncate("<<filename<<"): Enlarging current size ("<<file.size()<<") to ("<<length<<")" << endl;
for(int i = file.size(); i < length; ++i)
file[i] = '\0';
}
return -EINVAL;
}
int ramfs_mknod(const char* path, mode_t mode, dev_t dev) { cout << "ramfs_mknod not implemented" << endl; return -EINVAL; }
int ramfs_mkdir(const char *, mode_t) { cout << "ramfs_mkdir not implemented" << endl; return -EINVAL;}
int ramfs_rmdir(const char *) { cout << "ramfs_rmdir not implemented" << endl; return -EINVAL; }
int ramfs_symlink(const char *, const char *) { cout << "ramfs_symlink not implemented" << endl; return -EINVAL; }
int ramfs_rename(const char *, const char *) { cout << "ramfs_rename not implemented" << endl; return -EINVAL; }
int ramfs_link(const char *, const char *) { cout << "ramfs_link not implemented" << endl; return -EINVAL; }
int ramfs_chmod(const char *, mode_t) { cout << "ramfs_chmod not implemented" << endl; return -EINVAL; }
int ramfs_chown(const char *, uid_t, gid_t) { cout << "ramfs_chown not implemented" << endl; return -EINVAL; }
int ramfs_utime(const char *, struct utimbuf *) { cout << "ramfs_utime not implemented" << endl; return -EINVAL; }
int ramfs_utimens(const char *, const struct timespec tv[2]) { cout << "ramfs_utimens not implemented" << endl; return -EINVAL; }
int ramfs_bmap(const char *, size_t blocksize, uint64_t *idx) { cout << "ramfs_bmap not implemented" << endl; return -EINVAL; }
int ramfs_setxattr(const char *, const char *, const char *, size_t, int) { cout << "ramfs_setxattr not implemented" << endl; return -EINVAL; }
//Enthält die Funktionspointer auf die implementierten Operationen
static struct fuse_operations ramfs_oper;
int main(int argc, char** argv) {
//Zuweisen der einzelnen Funktionspointer
ramfs_oper.getattr = ramfs_getattr;
ramfs_oper.readdir = ramfs_readdir;
ramfs_oper.open = ramfs_open;
ramfs_oper.read = ramfs_read;
ramfs_oper.mknod = ramfs_mknod;
ramfs_oper.write = ramfs_write;
ramfs_oper.unlink = ramfs_unlink;
ramfs_oper.setxattr = ramfs_setxattr;
ramfs_oper.mkdir = ramfs_mkdir;
ramfs_oper.rmdir = ramfs_rmdir;
ramfs_oper.symlink = ramfs_symlink;
ramfs_oper.rename = ramfs_rename;
ramfs_oper.link = ramfs_link;
ramfs_oper.chmod = ramfs_chmod;
ramfs_oper.chown = ramfs_chown;
ramfs_oper.truncate = ramfs_truncate;
ramfs_oper.utime = ramfs_utime;
ramfs_oper.opendir = ramfs_opendir;
ramfs_oper.access = ramfs_access;
ramfs_oper.create = ramfs_create;
ramfs_oper.fgetattr = ramfs_fgetattr;
ramfs_oper.utimens = ramfs_utimens;
ramfs_oper.bmap = ramfs_bmap;
//Starten des Dateisystems
return fuse_main(argc, argv, &ramfs_oper, NULL);
}
}