blob: d4edbc9ae42fa262496a449032880808f9ffd754 [file] [log] [blame]
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7
8 gcc -Wall `pkg-config fuse --cflags --libs` fusexmp.c -o fusexmp
9*/
10
11#define FUSE_USE_VERSION 26
12
13#ifdef HAVE_CONFIG_H
14#include <config.h>
15#endif
16
17#ifdef linux
18/* For pread()/pwrite() */
19#define _XOPEN_SOURCE 500
20#endif
21
22#include <fuse.h>
23#include <stdio.h>
24#include <string.h>
25#include <unistd.h>
26#include <fcntl.h>
27#include <dirent.h>
28#include <errno.h>
29#include <sys/time.h>
30#ifdef HAVE_SETXATTR
31#include <sys/xattr.h>
32#endif
33
34static int xmp_getattr(const char *path, struct stat *stbuf)
35{
36 int res;
37
38 res = lstat(path, stbuf);
39 if (res == -1)
40 return -errno;
41
42 return 0;
43}
44
45static int xmp_access(const char *path, int mask)
46{
47 int res;
48
49 res = access(path, mask);
50 if (res == -1)
51 return -errno;
52
53 return 0;
54}
55
56static int xmp_readlink(const char *path, char *buf, size_t size)
57{
58 int res;
59
60 res = readlink(path, buf, size - 1);
61 if (res == -1)
62 return -errno;
63
64 buf[res] = '\0';
65 return 0;
66}
67
68
69static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
70 off64_t offset, struct fuse_file_info *fi)
71{
72 DIR *dp;
73 struct dirent *de;
74
75 (void) offset;
76 (void) fi;
77
78 dp = opendir(path);
79 if (dp == NULL)
80 return -errno;
81
82 while ((de = readdir(dp)) != NULL) {
83 struct stat st;
84 memset(&st, 0, sizeof(st));
85 st.st_ino = de->d_ino;
86 st.st_mode = de->d_type << 12;
87 if (filler(buf, de->d_name, &st, 0))
88 break;
89 }
90
91 closedir(dp);
92 return 0;
93}
94
95static int xmp_mknod(const char *path, mode_t mode, dev_t rdev)
96{
97 int res;
98
99 /* On Linux this could just be 'mknod(path, mode, rdev)' but this
100 is more portable */
101 if (S_ISREG(mode)) {
102 res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode);
103 if (res >= 0)
104 res = close(res);
105 } else if (S_ISFIFO(mode))
106 res = mkfifo(path, mode);
107 else
108 res = mknod(path, mode, rdev);
109 if (res == -1)
110 return -errno;
111
112 return 0;
113}
114
115static int xmp_mkdir(const char *path, mode_t mode)
116{
117 int res;
118
119 res = mkdir(path, mode);
120 if (res == -1)
121 return -errno;
122
123 return 0;
124}
125
126static int xmp_unlink(const char *path)
127{
128 int res;
129
130 res = unlink(path);
131 if (res == -1)
132 return -errno;
133
134 return 0;
135}
136
137static int xmp_rmdir(const char *path)
138{
139 int res;
140
141 res = rmdir(path);
142 if (res == -1)
143 return -errno;
144
145 return 0;
146}
147
148static int xmp_symlink(const char *from, const char *to)
149{
150 int res;
151
152 res = symlink(from, to);
153 if (res == -1)
154 return -errno;
155
156 return 0;
157}
158
159static int xmp_rename(const char *from, const char *to)
160{
161 int res;
162
163 res = rename(from, to);
164 if (res == -1)
165 return -errno;
166
167 return 0;
168}
169
170static int xmp_link(const char *from, const char *to)
171{
172 int res;
173
174 res = link(from, to);
175 if (res == -1)
176 return -errno;
177
178 return 0;
179}
180
181static int xmp_chmod(const char *path, mode_t mode)
182{
183 int res;
184
185 res = chmod(path, mode);
186 if (res == -1)
187 return -errno;
188
189 return 0;
190}
191
192static int xmp_chown(const char *path, uid_t uid, gid_t gid)
193{
194 int res;
195
196 res = lchown(path, uid, gid);
197 if (res == -1)
198 return -errno;
199
200 return 0;
201}
202
203static int xmp_truncate(const char *path, off64_t size)
204{
205 int res;
206
207 res = truncate(path, size);
208 if (res == -1)
209 return -errno;
210
211 return 0;
212}
213
214static int xmp_utimens(const char *path, const struct timespec ts[2])
215{
216 int res;
217 struct timeval tv[2];
218
219 tv[0].tv_sec = ts[0].tv_sec;
220 tv[0].tv_usec = ts[0].tv_nsec / 1000;
221 tv[1].tv_sec = ts[1].tv_sec;
222 tv[1].tv_usec = ts[1].tv_nsec / 1000;
223
224 res = utimes(path, tv);
225 if (res == -1)
226 return -errno;
227
228 return 0;
229}
230
231static int xmp_open(const char *path, struct fuse_file_info *fi)
232{
233 int res;
234
235 res = open(path, fi->flags);
236 if (res == -1)
237 return -errno;
238
239 close(res);
240 return 0;
241}
242
243static int xmp_read(const char *path, char *buf, size_t size, off64_t offset,
244 struct fuse_file_info *fi)
245{
246 int fd;
247 int res;
248
249 (void) fi;
250 fd = open(path, O_RDONLY);
251 if (fd == -1)
252 return -errno;
253
254 res = pread(fd, buf, size, offset);
255 if (res == -1)
256 res = -errno;
257
258 close(fd);
259 return res;
260}
261
262static int xmp_write(const char *path, const char *buf, size_t size,
263 off64_t offset, struct fuse_file_info *fi)
264{
265 int fd;
266 int res;
267
268 (void) fi;
269 fd = open(path, O_WRONLY);
270 if (fd == -1)
271 return -errno;
272
273 res = pwrite(fd, buf, size, offset);
274 if (res == -1)
275 res = -errno;
276
277 close(fd);
278 return res;
279}
280
281static int xmp_statfs(const char *path, struct statvfs *stbuf)
282{
283 int res;
284
285 //res = statvfs(path, stbuf);
286 if (res == -1)
287 return -errno;
288
289 return 0;
290}
291
292static int xmp_release(const char *path, struct fuse_file_info *fi)
293{
294 /* Just a stub. This method is optional and can safely be left
295 unimplemented */
296
297 (void) path;
298 (void) fi;
299 return 0;
300}
301
302static int xmp_fsync(const char *path, int isdatasync,
303 struct fuse_file_info *fi)
304{
305 /* Just a stub. This method is optional and can safely be left
306 unimplemented */
307
308 (void) path;
309 (void) isdatasync;
310 (void) fi;
311 return 0;
312}
313
314#ifdef HAVE_SETXATTR
315/* xattr operations are optional and can safely be left unimplemented */
316static int xmp_setxattr(const char *path, const char *name, const char *value,
317 size_t size, int flags)
318{
319 int res = lsetxattr(path, name, value, size, flags);
320 if (res == -1)
321 return -errno;
322 return 0;
323}
324
325static int xmp_getxattr(const char *path, const char *name, char *value,
326 size_t size)
327{
328 int res = lgetxattr(path, name, value, size);
329 if (res == -1)
330 return -errno;
331 return res;
332}
333
334static int xmp_listxattr(const char *path, char *list, size_t size)
335{
336 int res = llistxattr(path, list, size);
337 if (res == -1)
338 return -errno;
339 return res;
340}
341
342static int xmp_removexattr(const char *path, const char *name)
343{
344 int res = lremovexattr(path, name);
345 if (res == -1)
346 return -errno;
347 return 0;
348}
349#endif /* HAVE_SETXATTR */
350
351static struct fuse_operations xmp_oper = {
352 .getattr = xmp_getattr,
353 .access = xmp_access,
354 .readlink = xmp_readlink,
355 .readdir = xmp_readdir,
356 .mknod = xmp_mknod,
357 .mkdir = xmp_mkdir,
358 .symlink = xmp_symlink,
359 .unlink = xmp_unlink,
360 .rmdir = xmp_rmdir,
361 .rename = xmp_rename,
362 .link = xmp_link,
363 .chmod = xmp_chmod,
364 .chown = xmp_chown,
365 .truncate = xmp_truncate,
366 .utimens = xmp_utimens,
367 .open = xmp_open,
368 .read = xmp_read,
369 .write = xmp_write,
370 .statfs = xmp_statfs,
371 .release = xmp_release,
372 .fsync = xmp_fsync,
373#ifdef HAVE_SETXATTR
374 .setxattr = xmp_setxattr,
375 .getxattr = xmp_getxattr,
376 .listxattr = xmp_listxattr,
377 .removexattr = xmp_removexattr,
378#endif
379};
380
381int main(int argc, char *argv[])
382{
383 umask(0);
384 return fuse_main(argc, argv, &xmp_oper, NULL);
385}