1/*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include "fuse_fs.h"
7
8#include <string.h>
9
10#include <new>
11
12#include "Debug.h"
13
14
15int
16fuse_fs_getattr(struct fuse_fs* fs, const char* path, struct stat* buf)
17{
18	if (fs->ops.getattr == NULL)
19		return ENOSYS;
20	return fs->ops.getattr(path, buf);
21}
22
23
24int
25fuse_fs_fgetattr(struct fuse_fs* fs, const char* path, struct stat* buf,
26	struct fuse_file_info* fi)
27{
28	if (fs->ops.fgetattr == NULL)
29		return ENOSYS;
30	return fs->ops.fgetattr(path, buf, fi);
31}
32
33
34int
35fuse_fs_rename(struct fuse_fs* fs, const char* oldpath, const char* newpath)
36{
37	if (fs->ops.rename == NULL)
38		return ENOSYS;
39	return fs->ops.rename(oldpath, newpath);
40}
41
42
43int
44fuse_fs_unlink(struct fuse_fs* fs, const char* path)
45{
46	if (fs->ops.unlink == NULL)
47		return ENOSYS;
48	return fs->ops.unlink(path);
49}
50
51
52int
53fuse_fs_rmdir(struct fuse_fs* fs, const char* path)
54{
55	if (fs->ops.rmdir == NULL)
56		return ENOSYS;
57	return fs->ops.rmdir(path);
58}
59
60
61int
62fuse_fs_symlink(struct fuse_fs* fs, const char* linkname, const char* path)
63{
64	if (fs->ops.symlink == NULL)
65		return ENOSYS;
66	return fs->ops.symlink(linkname, path);
67}
68
69
70int
71fuse_fs_link(struct fuse_fs* fs, const char* oldpath, const char* newpath)
72{
73	if (fs->ops.link == NULL)
74		return ENOSYS;
75	return fs->ops.link(oldpath, newpath);
76}
77
78
79int
80fuse_fs_release(struct fuse_fs* fs,	 const char* path,
81	struct fuse_file_info* fi)
82{
83	if (fs->ops.release == NULL)
84		return 0;
85	return fs->ops.release(path, fi);
86}
87
88
89int
90fuse_fs_open(struct fuse_fs* fs, const char* path, struct fuse_file_info* fi)
91{
92	if (fs->ops.open == NULL)
93		return 0;
94	return fs->ops.open(path, fi);
95}
96
97
98int
99fuse_fs_read(struct fuse_fs* fs, const char* path, char *buf, size_t size,
100	off_t off, struct fuse_file_info* fi)
101{
102	if (fs->ops.read == NULL)
103		return ENOSYS;
104	return fs->ops.read(path, buf, size, off, fi);
105}
106
107
108int
109fuse_fs_write(struct fuse_fs* fs, const char* path, const char* buf,
110	size_t size, off_t off, struct fuse_file_info* fi)
111{
112	if (fs->ops.write == NULL)
113		return ENOSYS;
114	return fs->ops.write(path, buf, size, off, fi);
115}
116
117
118int
119fuse_fs_fsync(struct fuse_fs* fs, const char* path, int datasync,
120	struct fuse_file_info* fi)
121{
122	if (fs->ops.fsync == NULL)
123		return ENOSYS;
124	return fs->ops.fsync(path, datasync, fi);
125}
126
127
128int
129fuse_fs_flush(struct fuse_fs* fs, const char* path, struct fuse_file_info* fi)
130{
131	if (fs->ops.flush == NULL)
132		return ENOSYS;
133	return fs->ops.flush(path, fi);
134}
135
136
137int
138fuse_fs_statfs(struct fuse_fs* fs, const char* path, struct statvfs* buf)
139{
140	if (fs->ops.statfs == NULL)
141		return 0;
142	return fs->ops.statfs(path, buf);
143}
144
145
146int
147fuse_fs_opendir(struct fuse_fs* fs, const char* path, struct fuse_file_info* fi)
148{
149	if (fs->ops.opendir == NULL)
150		return 0;
151	return fs->ops.opendir(path, fi);
152}
153
154
155int
156fuse_fs_readdir(struct fuse_fs* fs, const char* path, void* buf,
157	fuse_fill_dir_t filler, off_t off, struct fuse_file_info* fi)
158{
159	if (fs->ops.readdir == NULL)
160		return ENOSYS;
161	return fs->ops.readdir(path, buf, filler, off, fi);
162}
163
164
165int
166fuse_fs_fsyncdir(struct fuse_fs* fs, const char* path, int datasync,
167	struct fuse_file_info* fi)
168{
169	if (fs->ops.fsyncdir == NULL)
170		return ENOSYS;
171	return fs->ops.fsyncdir(path, datasync, fi);
172}
173
174
175int
176fuse_fs_releasedir(struct fuse_fs* fs, const char* path,
177	struct fuse_file_info* fi)
178{
179	if (fs->ops.releasedir == NULL)
180		return 0;
181	return fs->ops.releasedir(path, fi);
182}
183
184
185int
186fuse_fs_create(struct fuse_fs* fs, const char* path, mode_t mode,
187	struct fuse_file_info* fi)
188{
189	if (fs->ops.create == NULL)
190		return ENOSYS;
191	return fs->ops.create(path, mode, fi);
192}
193
194
195int
196fuse_fs_lock(struct fuse_fs* fs, const char* path, struct fuse_file_info* fi,
197	int cmd, struct flock* lock)
198{
199	if (fs->ops.lock == NULL)
200		return ENOSYS;
201	return fs->ops.lock(path, fi, cmd, lock);
202}
203
204
205int
206fuse_fs_chmod(struct fuse_fs* fs, const char* path, mode_t mode)
207{
208	if (fs->ops.chmod == NULL)
209		return ENOSYS;
210	return fs->ops.chmod(path, mode);
211}
212
213
214int
215fuse_fs_chown(struct fuse_fs* fs, const char* path, uid_t uid, gid_t gid)
216{
217	if (fs->ops.chown == NULL)
218		return ENOSYS;
219	return fs->ops.chown(path, uid, gid);
220}
221
222
223int
224fuse_fs_truncate(struct fuse_fs* fs, const char* path, off_t size)
225{
226	if (fs->ops.truncate == NULL)
227		return ENOSYS;
228	return fs->ops.truncate(path, size);
229}
230
231
232int
233fuse_fs_ftruncate(struct fuse_fs* fs, const char* path, off_t size,
234	struct fuse_file_info* fi)
235{
236	if (fs->ops.ftruncate == NULL)
237		return ENOSYS;
238	return fs->ops.ftruncate(path, size, fi);
239}
240
241
242int
243fuse_fs_utimens(struct fuse_fs* fs, const char* path,
244	const struct timespec tv[2])
245{
246	if (fs->ops.utimens != NULL)
247		return fs->ops.utimens(path, tv);
248
249	if (fs->ops.utime != NULL) {
250		utimbuf timeBuffer = {
251			tv[0].tv_sec,	// access time
252			tv[1].tv_sec	// modification time
253		};
254		return fs->ops.utime(path, &timeBuffer);
255	}
256
257	return ENOSYS;
258}
259
260
261int
262fuse_fs_access(struct fuse_fs* fs, const char* path, int mask)
263{
264	if (fs->ops.access == NULL)
265		return ENOSYS;
266	return fs->ops.access(path, mask);
267}
268
269
270int
271fuse_fs_readlink(struct fuse_fs* fs, const char* path, char* buf, size_t len)
272{
273	if (fs->ops.readlink == NULL)
274		return ENOSYS;
275	return fs->ops.readlink(path, buf, len);
276}
277
278
279int
280fuse_fs_mknod(struct fuse_fs* fs, const char* path, mode_t mode, dev_t rdev)
281{
282	if (fs->ops.mknod == NULL)
283		return ENOSYS;
284	return fs->ops.mknod(path, mode, rdev);
285}
286
287
288int
289fuse_fs_mkdir(struct fuse_fs* fs, const char* path, mode_t mode)
290{
291	if (fs->ops.mkdir == NULL)
292		return ENOSYS;
293	return fs->ops.mkdir(path, mode);
294}
295
296
297int
298fuse_fs_setxattr(struct fuse_fs* fs, const char* path, const char* name,
299	const char* value, size_t size, int flags)
300{
301	if (fs->ops.setxattr == NULL)
302		return ENOSYS;
303	return fs->ops.setxattr(path, name, value, size, flags);
304}
305
306
307int
308fuse_fs_getxattr(struct fuse_fs* fs, const char* path, const char* name,
309	char* value, size_t size)
310{
311	if (fs->ops.getxattr == NULL)
312		return ENOSYS;
313	return fs->ops.getxattr(path, name, value, size);
314}
315
316
317int
318fuse_fs_listxattr(struct fuse_fs* fs, const char* path, char* list, size_t size)
319{
320	if (fs->ops.listxattr == NULL)
321		return ENOSYS;
322	return fs->ops.listxattr(path, list, size);
323}
324
325
326int
327fuse_fs_removexattr(struct fuse_fs* fs, const char* path, const char* name)
328{
329	if (fs->ops.removexattr == NULL)
330		return ENOSYS;
331	return fs->ops.removexattr(path, name);
332}
333
334
335int
336fuse_fs_bmap(struct fuse_fs* fs, const char* path, size_t blocksize,
337	uint64_t* idx)
338{
339	if (fs->ops.bmap == NULL)
340		return ENOSYS;
341	return fs->ops.bmap(path, blocksize, idx);
342}
343
344
345int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg,
346	struct fuse_file_info *fi, unsigned int flags, void *data)
347{
348	if (fs->ops.ioctl == NULL)
349		return ENOSYS;
350
351	return fs->ops.ioctl(path, cmd, arg, fi, flags, data);
352}
353
354
355void
356fuse_fs_init(struct fuse_fs* fs, struct fuse_conn_info* conn)
357{
358	if (fs->ops.init == NULL)
359		return;
360	fs->ops.init(conn);
361}
362
363
364void
365fuse_fs_destroy(struct fuse_fs* fs)
366{
367	if (fs->ops.destroy != NULL)
368		fs->ops.destroy(fs->userData);
369
370	delete fs;
371}
372
373
374struct fuse_fs*
375fuse_fs_new(const struct fuse_operations* ops, size_t opSize, void* userData)
376{
377	if (sizeof(fuse_operations) < opSize) {
378		ERROR(("fuse_fs_new(): Client FS built with newer library version!\n"));
379		return NULL;
380	}
381
382	fuse_fs* fs = new(std::nothrow) fuse_fs;
383	if (fs == NULL)
384		return NULL;
385
386	memset(&fs->ops, 0, sizeof(fuse_operations));
387	memcpy(&fs->ops, ops, opSize);
388
389	fs->userData = userData;
390
391	return fs;
392}
393
394