*** empty log message ***
[fuse.git] / example / fusexmp.c
blob8df474c0730a54c8617387dcb89f1900fb4d0cca
1 /*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
8 gcc -Wall `pkg-config fuse --cflags --libs` fusexmp.c -o fusexmp
9 */
11 #define FUSE_USE_VERSION 26
13 #ifdef HAVE_CONFIG_H
14 #include <config.h>
15 #endif
17 #ifdef linux
18 /* For pread()/pwrite() */
19 #define _XOPEN_SOURCE 500
20 #endif
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
34 static int xmp_getattr(const char *path, struct stat *stbuf)
36 int res;
38 res = lstat(path, stbuf);
39 if (res == -1)
40 return -errno;
42 return 0;
45 static int xmp_access(const char *path, int mask)
47 int res;
49 res = access(path, mask);
50 if (res == -1)
51 return -errno;
53 return 0;
56 static int xmp_readlink(const char *path, char *buf, size_t size)
58 int res;
60 res = readlink(path, buf, size - 1);
61 if (res == -1)
62 return -errno;
64 buf[res] = '\0';
65 return 0;
69 static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
70 off_t offset, struct fuse_file_info *fi)
72 DIR *dp;
73 struct dirent *de;
75 (void) offset;
76 (void) fi;
78 dp = opendir(path);
79 if (dp == NULL)
80 return -errno;
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;
91 closedir(dp);
92 return 0;
95 static int xmp_mknod(const char *path, mode_t mode, dev_t rdev)
97 int res;
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;
112 return 0;
115 static int xmp_mkdir(const char *path, mode_t mode)
117 int res;
119 res = mkdir(path, mode);
120 if (res == -1)
121 return -errno;
123 return 0;
126 static int xmp_unlink(const char *path)
128 int res;
130 res = unlink(path);
131 if (res == -1)
132 return -errno;
134 return 0;
137 static int xmp_rmdir(const char *path)
139 int res;
141 res = rmdir(path);
142 if (res == -1)
143 return -errno;
145 return 0;
148 static int xmp_symlink(const char *from, const char *to)
150 int res;
152 res = symlink(from, to);
153 if (res == -1)
154 return -errno;
156 return 0;
159 static int xmp_rename(const char *from, const char *to)
161 int res;
163 res = rename(from, to);
164 if (res == -1)
165 return -errno;
167 return 0;
170 static int xmp_link(const char *from, const char *to)
172 int res;
174 res = link(from, to);
175 if (res == -1)
176 return -errno;
178 return 0;
181 static int xmp_chmod(const char *path, mode_t mode)
183 int res;
185 res = chmod(path, mode);
186 if (res == -1)
187 return -errno;
189 return 0;
192 static int xmp_chown(const char *path, uid_t uid, gid_t gid)
194 int res;
196 res = lchown(path, uid, gid);
197 if (res == -1)
198 return -errno;
200 return 0;
203 static int xmp_truncate(const char *path, off_t size)
205 int res;
207 res = truncate(path, size);
208 if (res == -1)
209 return -errno;
211 return 0;
214 static int xmp_utimens(const char *path, const struct timespec ts[2])
216 int res;
217 struct timeval tv[2];
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;
224 res = utimes(path, tv);
225 if (res == -1)
226 return -errno;
228 return 0;
231 static int xmp_open(const char *path, struct fuse_file_info *fi)
233 int res;
235 res = open(path, fi->flags);
236 if (res == -1)
237 return -errno;
239 close(res);
240 return 0;
243 static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
244 struct fuse_file_info *fi)
246 int fd;
247 int res;
249 (void) fi;
250 fd = open(path, O_RDONLY);
251 if (fd == -1)
252 return -errno;
254 res = pread(fd, buf, size, offset);
255 if (res == -1)
256 res = -errno;
258 close(fd);
259 return res;
262 static int xmp_write(const char *path, const char *buf, size_t size,
263 off_t offset, struct fuse_file_info *fi)
265 int fd;
266 int res;
268 (void) fi;
269 fd = open(path, O_WRONLY);
270 if (fd == -1)
271 return -errno;
273 res = pwrite(fd, buf, size, offset);
274 if (res == -1)
275 res = -errno;
277 close(fd);
278 return res;
281 static int xmp_statfs(const char *path, struct statvfs *stbuf)
283 int res;
285 res = statvfs(path, stbuf);
286 if (res == -1)
287 return -errno;
289 return 0;
292 static int xmp_release(const char *path, struct fuse_file_info *fi)
294 /* Just a stub. This method is optional and can safely be left
295 unimplemented */
297 (void) path;
298 (void) fi;
299 return 0;
302 static int xmp_fsync(const char *path, int isdatasync,
303 struct fuse_file_info *fi)
305 /* Just a stub. This method is optional and can safely be left
306 unimplemented */
308 (void) path;
309 (void) isdatasync;
310 (void) fi;
311 return 0;
314 #ifdef HAVE_SETXATTR
315 /* xattr operations are optional and can safely be left unimplemented */
316 static int xmp_setxattr(const char *path, const char *name, const char *value,
317 size_t size, int flags)
319 int res = lsetxattr(path, name, value, size, flags);
320 if (res == -1)
321 return -errno;
322 return 0;
325 static int xmp_getxattr(const char *path, const char *name, char *value,
326 size_t size)
328 int res = lgetxattr(path, name, value, size);
329 if (res == -1)
330 return -errno;
331 return res;
334 static int xmp_listxattr(const char *path, char *list, size_t size)
336 int res = llistxattr(path, list, size);
337 if (res == -1)
338 return -errno;
339 return res;
342 static int xmp_removexattr(const char *path, const char *name)
344 int res = lremovexattr(path, name);
345 if (res == -1)
346 return -errno;
347 return 0;
349 #endif /* HAVE_SETXATTR */
351 static 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
381 int main(int argc, char *argv[])
383 umask(0);
384 return fuse_main(argc, argv, &xmp_oper, NULL);