remove <utime.h> include from <fuse.h>
[fuse.git] / example / fusexmp.c
blob42a813432f445cab80b85d14ce245650491ea3ca
1 /*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4 Copyright (C) 2011 Sebastian Pipping <sebastian@pipping.org>
6 This program can be distributed under the terms of the GNU GPL.
7 See the file COPYING.
9 gcc -Wall fusexmp.c `pkg-config fuse --cflags --libs` -o fusexmp
12 #define FUSE_USE_VERSION 30
14 #ifdef HAVE_CONFIG_H
15 #include <config.h>
16 #endif
18 #ifdef linux
19 /* For pread()/pwrite()/utimensat() */
20 #define _XOPEN_SOURCE 700
21 #endif
23 #include <fuse.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/stat.h>
29 #include <dirent.h>
30 #include <errno.h>
31 #include <sys/time.h>
32 #ifdef HAVE_SETXATTR
33 #include <sys/xattr.h>
34 #endif
36 static int xmp_getattr(const char *path, struct stat *stbuf)
38 int res;
40 res = lstat(path, stbuf);
41 if (res == -1)
42 return -errno;
44 return 0;
47 static int xmp_access(const char *path, int mask)
49 int res;
51 res = access(path, mask);
52 if (res == -1)
53 return -errno;
55 return 0;
58 static int xmp_readlink(const char *path, char *buf, size_t size)
60 int res;
62 res = readlink(path, buf, size - 1);
63 if (res == -1)
64 return -errno;
66 buf[res] = '\0';
67 return 0;
71 static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
72 off_t offset, struct fuse_file_info *fi)
74 DIR *dp;
75 struct dirent *de;
77 (void) offset;
78 (void) fi;
80 dp = opendir(path);
81 if (dp == NULL)
82 return -errno;
84 while ((de = readdir(dp)) != NULL) {
85 struct stat st;
86 memset(&st, 0, sizeof(st));
87 st.st_ino = de->d_ino;
88 st.st_mode = de->d_type << 12;
89 if (filler(buf, de->d_name, &st, 0))
90 break;
93 closedir(dp);
94 return 0;
97 static int xmp_mknod(const char *path, mode_t mode, dev_t rdev)
99 int res;
101 /* On Linux this could just be 'mknod(path, mode, rdev)' but this
102 is more portable */
103 if (S_ISREG(mode)) {
104 res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode);
105 if (res >= 0)
106 res = close(res);
107 } else if (S_ISFIFO(mode))
108 res = mkfifo(path, mode);
109 else
110 res = mknod(path, mode, rdev);
111 if (res == -1)
112 return -errno;
114 return 0;
117 static int xmp_mkdir(const char *path, mode_t mode)
119 int res;
121 res = mkdir(path, mode);
122 if (res == -1)
123 return -errno;
125 return 0;
128 static int xmp_unlink(const char *path)
130 int res;
132 res = unlink(path);
133 if (res == -1)
134 return -errno;
136 return 0;
139 static int xmp_rmdir(const char *path)
141 int res;
143 res = rmdir(path);
144 if (res == -1)
145 return -errno;
147 return 0;
150 static int xmp_symlink(const char *from, const char *to)
152 int res;
154 res = symlink(from, to);
155 if (res == -1)
156 return -errno;
158 return 0;
161 static int xmp_rename(const char *from, const char *to)
163 int res;
165 res = rename(from, to);
166 if (res == -1)
167 return -errno;
169 return 0;
172 static int xmp_link(const char *from, const char *to)
174 int res;
176 res = link(from, to);
177 if (res == -1)
178 return -errno;
180 return 0;
183 static int xmp_chmod(const char *path, mode_t mode)
185 int res;
187 res = chmod(path, mode);
188 if (res == -1)
189 return -errno;
191 return 0;
194 static int xmp_chown(const char *path, uid_t uid, gid_t gid)
196 int res;
198 res = lchown(path, uid, gid);
199 if (res == -1)
200 return -errno;
202 return 0;
205 static int xmp_truncate(const char *path, off_t size)
207 int res;
209 res = truncate(path, size);
210 if (res == -1)
211 return -errno;
213 return 0;
216 #ifdef HAVE_UTIMENSAT
217 static int xmp_utimens(const char *path, const struct timespec ts[2])
219 int res;
221 /* don't use utime/utimes since they follow symlinks */
222 res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);
223 if (res == -1)
224 return -errno;
226 return 0;
228 #endif
230 static int xmp_open(const char *path, struct fuse_file_info *fi)
232 int res;
234 res = open(path, fi->flags);
235 if (res == -1)
236 return -errno;
238 close(res);
239 return 0;
242 static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
243 struct fuse_file_info *fi)
245 int fd;
246 int res;
248 (void) fi;
249 fd = open(path, O_RDONLY);
250 if (fd == -1)
251 return -errno;
253 res = pread(fd, buf, size, offset);
254 if (res == -1)
255 res = -errno;
257 close(fd);
258 return res;
261 static int xmp_write(const char *path, const char *buf, size_t size,
262 off_t offset, struct fuse_file_info *fi)
264 int fd;
265 int res;
267 (void) fi;
268 fd = open(path, O_WRONLY);
269 if (fd == -1)
270 return -errno;
272 res = pwrite(fd, buf, size, offset);
273 if (res == -1)
274 res = -errno;
276 close(fd);
277 return res;
280 static int xmp_statfs(const char *path, struct statvfs *stbuf)
282 int res;
284 res = statvfs(path, stbuf);
285 if (res == -1)
286 return -errno;
288 return 0;
291 static int xmp_release(const char *path, struct fuse_file_info *fi)
293 /* Just a stub. This method is optional and can safely be left
294 unimplemented */
296 (void) path;
297 (void) fi;
298 return 0;
301 static int xmp_fsync(const char *path, int isdatasync,
302 struct fuse_file_info *fi)
304 /* Just a stub. This method is optional and can safely be left
305 unimplemented */
307 (void) path;
308 (void) isdatasync;
309 (void) fi;
310 return 0;
313 #ifdef HAVE_POSIX_FALLOCATE
314 static int xmp_fallocate(const char *path, int mode,
315 off_t offset, off_t length, struct fuse_file_info *fi)
317 int fd;
318 int res;
320 (void) fi;
322 if (mode)
323 return -EOPNOTSUPP;
325 fd = open(path, O_WRONLY);
326 if (fd == -1)
327 return -errno;
329 res = -posix_fallocate(fd, offset, length);
331 close(fd);
332 return res;
334 #endif
336 #ifdef HAVE_SETXATTR
337 /* xattr operations are optional and can safely be left unimplemented */
338 static int xmp_setxattr(const char *path, const char *name, const char *value,
339 size_t size, int flags)
341 int res = lsetxattr(path, name, value, size, flags);
342 if (res == -1)
343 return -errno;
344 return 0;
347 static int xmp_getxattr(const char *path, const char *name, char *value,
348 size_t size)
350 int res = lgetxattr(path, name, value, size);
351 if (res == -1)
352 return -errno;
353 return res;
356 static int xmp_listxattr(const char *path, char *list, size_t size)
358 int res = llistxattr(path, list, size);
359 if (res == -1)
360 return -errno;
361 return res;
364 static int xmp_removexattr(const char *path, const char *name)
366 int res = lremovexattr(path, name);
367 if (res == -1)
368 return -errno;
369 return 0;
371 #endif /* HAVE_SETXATTR */
373 static struct fuse_operations xmp_oper = {
374 .getattr = xmp_getattr,
375 .access = xmp_access,
376 .readlink = xmp_readlink,
377 .readdir = xmp_readdir,
378 .mknod = xmp_mknod,
379 .mkdir = xmp_mkdir,
380 .symlink = xmp_symlink,
381 .unlink = xmp_unlink,
382 .rmdir = xmp_rmdir,
383 .rename = xmp_rename,
384 .link = xmp_link,
385 .chmod = xmp_chmod,
386 .chown = xmp_chown,
387 .truncate = xmp_truncate,
388 #ifdef HAVE_UTIMENSAT
389 .utimens = xmp_utimens,
390 #endif
391 .open = xmp_open,
392 .read = xmp_read,
393 .write = xmp_write,
394 .statfs = xmp_statfs,
395 .release = xmp_release,
396 .fsync = xmp_fsync,
397 #ifdef HAVE_POSIX_FALLOCATE
398 .fallocate = xmp_fallocate,
399 #endif
400 #ifdef HAVE_SETXATTR
401 .setxattr = xmp_setxattr,
402 .getxattr = xmp_getxattr,
403 .listxattr = xmp_listxattr,
404 .removexattr = xmp_removexattr,
405 #endif
408 int main(int argc, char *argv[])
410 umask(0);
411 return fuse_main(argc, argv, &xmp_oper, NULL);