Replace utils/mount.fuse "sh" script with a "C" program
[fuse.git] / example / fusexmp.c
blobb086235c2e17da41c93b87d43cc895187eeb36f4
1 /*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2006 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 #include <config.h>
15 #ifdef linux
16 /* For pread()/pwrite() */
17 #define _XOPEN_SOURCE 500
18 #endif
20 #include <fuse.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <dirent.h>
26 #include <errno.h>
27 #include <sys/time.h>
28 #ifdef HAVE_SETXATTR
29 #include <sys/xattr.h>
30 #endif
32 static int xmp_getattr(const char *path, struct stat *stbuf)
34 int res;
36 res = lstat(path, stbuf);
37 if (res == -1)
38 return -errno;
40 return 0;
43 static int xmp_access(const char *path, int mask)
45 int res;
47 res = access(path, mask);
48 if (res == -1)
49 return -errno;
51 return 0;
54 static int xmp_readlink(const char *path, char *buf, size_t size)
56 int res;
58 res = readlink(path, buf, size - 1);
59 if (res == -1)
60 return -errno;
62 buf[res] = '\0';
63 return 0;
67 static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
68 off_t offset, struct fuse_file_info *fi)
70 DIR *dp;
71 struct dirent *de;
73 (void) offset;
74 (void) fi;
76 dp = opendir(path);
77 if (dp == NULL)
78 return -errno;
80 while ((de = readdir(dp)) != NULL) {
81 struct stat st;
82 memset(&st, 0, sizeof(st));
83 st.st_ino = de->d_ino;
84 st.st_mode = de->d_type << 12;
85 if (filler(buf, de->d_name, &st, 0))
86 break;
89 closedir(dp);
90 return 0;
93 static int xmp_mknod(const char *path, mode_t mode, dev_t rdev)
95 int res;
97 /* On Linux this could just be 'mknod(path, mode, rdev)' but this
98 is more portable */
99 if (S_ISREG(mode)) {
100 res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode);
101 if (res >= 0)
102 res = close(res);
103 } else if (S_ISFIFO(mode))
104 res = mkfifo(path, mode);
105 else
106 res = mknod(path, mode, rdev);
107 if (res == -1)
108 return -errno;
110 return 0;
113 static int xmp_mkdir(const char *path, mode_t mode)
115 int res;
117 res = mkdir(path, mode);
118 if (res == -1)
119 return -errno;
121 return 0;
124 static int xmp_unlink(const char *path)
126 int res;
128 res = unlink(path);
129 if (res == -1)
130 return -errno;
132 return 0;
135 static int xmp_rmdir(const char *path)
137 int res;
139 res = rmdir(path);
140 if (res == -1)
141 return -errno;
143 return 0;
146 static int xmp_symlink(const char *from, const char *to)
148 int res;
150 res = symlink(from, to);
151 if (res == -1)
152 return -errno;
154 return 0;
157 static int xmp_rename(const char *from, const char *to)
159 int res;
161 res = rename(from, to);
162 if (res == -1)
163 return -errno;
165 return 0;
168 static int xmp_link(const char *from, const char *to)
170 int res;
172 res = link(from, to);
173 if (res == -1)
174 return -errno;
176 return 0;
179 static int xmp_chmod(const char *path, mode_t mode)
181 int res;
183 res = chmod(path, mode);
184 if (res == -1)
185 return -errno;
187 return 0;
190 static int xmp_chown(const char *path, uid_t uid, gid_t gid)
192 int res;
194 res = lchown(path, uid, gid);
195 if (res == -1)
196 return -errno;
198 return 0;
201 static int xmp_truncate(const char *path, off_t size)
203 int res;
205 res = truncate(path, size);
206 if (res == -1)
207 return -errno;
209 return 0;
212 static int xmp_utimens(const char *path, const struct timespec ts[2])
214 int res;
215 struct timeval tv[2];
217 tv[0].tv_sec = ts[0].tv_sec;
218 tv[0].tv_usec = ts[0].tv_nsec / 1000;
219 tv[1].tv_sec = ts[1].tv_sec;
220 tv[1].tv_usec = ts[1].tv_nsec / 1000;
222 res = utimes(path, tv);
223 if (res == -1)
224 return -errno;
226 return 0;
229 static int xmp_open(const char *path, struct fuse_file_info *fi)
231 int res;
233 res = open(path, fi->flags);
234 if (res == -1)
235 return -errno;
237 close(res);
238 return 0;
241 static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
242 struct fuse_file_info *fi)
244 int fd;
245 int res;
247 (void) fi;
248 fd = open(path, O_RDONLY);
249 if (fd == -1)
250 return -errno;
252 res = pread(fd, buf, size, offset);
253 if (res == -1)
254 res = -errno;
256 close(fd);
257 return res;
260 static int xmp_write(const char *path, const char *buf, size_t size,
261 off_t offset, struct fuse_file_info *fi)
263 int fd;
264 int res;
266 (void) fi;
267 fd = open(path, O_WRONLY);
268 if (fd == -1)
269 return -errno;
271 res = pwrite(fd, buf, size, offset);
272 if (res == -1)
273 res = -errno;
275 close(fd);
276 return res;
279 static int xmp_statfs(const char *path, struct statvfs *stbuf)
281 int res;
283 res = statvfs(path, stbuf);
284 if (res == -1)
285 return -errno;
287 return 0;
290 static int xmp_release(const char *path, struct fuse_file_info *fi)
292 /* Just a stub. This method is optional and can safely be left
293 unimplemented */
295 (void) path;
296 (void) fi;
297 return 0;
300 static int xmp_fsync(const char *path, int isdatasync,
301 struct fuse_file_info *fi)
303 /* Just a stub. This method is optional and can safely be left
304 unimplemented */
306 (void) path;
307 (void) isdatasync;
308 (void) fi;
309 return 0;
312 #ifdef HAVE_SETXATTR
313 /* xattr operations are optional and can safely be left unimplemented */
314 static int xmp_setxattr(const char *path, const char *name, const char *value,
315 size_t size, int flags)
317 int res = lsetxattr(path, name, value, size, flags);
318 if (res == -1)
319 return -errno;
320 return 0;
323 static int xmp_getxattr(const char *path, const char *name, char *value,
324 size_t size)
326 int res = lgetxattr(path, name, value, size);
327 if (res == -1)
328 return -errno;
329 return res;
332 static int xmp_listxattr(const char *path, char *list, size_t size)
334 int res = llistxattr(path, list, size);
335 if (res == -1)
336 return -errno;
337 return res;
340 static int xmp_removexattr(const char *path, const char *name)
342 int res = lremovexattr(path, name);
343 if (res == -1)
344 return -errno;
345 return 0;
347 #endif /* HAVE_SETXATTR */
349 static struct fuse_operations xmp_oper = {
350 .getattr = xmp_getattr,
351 .access = xmp_access,
352 .readlink = xmp_readlink,
353 .readdir = xmp_readdir,
354 .mknod = xmp_mknod,
355 .mkdir = xmp_mkdir,
356 .symlink = xmp_symlink,
357 .unlink = xmp_unlink,
358 .rmdir = xmp_rmdir,
359 .rename = xmp_rename,
360 .link = xmp_link,
361 .chmod = xmp_chmod,
362 .chown = xmp_chown,
363 .truncate = xmp_truncate,
364 .utimens = xmp_utimens,
365 .open = xmp_open,
366 .read = xmp_read,
367 .write = xmp_write,
368 .statfs = xmp_statfs,
369 .release = xmp_release,
370 .fsync = xmp_fsync,
371 #ifdef HAVE_SETXATTR
372 .setxattr = xmp_setxattr,
373 .getxattr = xmp_getxattr,
374 .listxattr = xmp_listxattr,
375 .removexattr= xmp_removexattr,
376 #endif
379 int main(int argc, char *argv[])
381 umask(0);
382 return fuse_main(argc, argv, &xmp_oper, NULL);