cmake: Added code coverage support. check only for C (no C++) support. Check attr...
[rrq/fuse_xattrs.git] / passthrough.c
1 /*
2   fuse_xattrs - Add xattrs support using sidecar files
3
4   Copyright (C) 2016  Felipe Barriga Richards <felipe {at} felipebarriga.cl>
5
6   Based on passthrough.c (libfuse example)
7
8   This program can be distributed under the terms of the GNU GPL.
9   See the file COPYING.
10 */
11
12 #define FUSE_USE_VERSION 30
13
14 /* For pread()/pwrite()/utimensat() */
15 #define _XOPEN_SOURCE 700
16
17 #include <fuse.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <dirent.h>
22 #include <errno.h>
23
24 int xmp_getattr(const char *path, struct stat *stbuf) {
25     int res;
26
27     res = lstat(path, stbuf);
28     if (res == -1)
29         return -errno;
30
31     return 0;
32 }
33
34 int xmp_access(const char *path, int mask) {
35     int res;
36
37     res = access(path, mask);
38     if (res == -1)
39         return -errno;
40
41     return 0;
42 }
43
44 int xmp_readlink(const char *path, char *buf, size_t size) {
45     int res;
46
47     res = readlink(path, buf, size - 1);
48     if (res == -1)
49         return -errno;
50
51     buf[res] = '\0';
52     return 0;
53 }
54
55 int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
56                 off_t offset, struct fuse_file_info *fi)
57 {
58     DIR *dp;
59     struct dirent *de;
60
61     (void) offset;
62     (void) fi;
63
64     dp = opendir(path);
65     if (dp == NULL)
66         return -errno;
67
68     while ((de = readdir(dp)) != NULL) {
69         struct stat st;
70         memset(&st, 0, sizeof(st));
71         st.st_ino = de->d_ino;
72         st.st_mode = de->d_type << 12;
73         if (filler(buf, de->d_name, &st, 0))
74             break;
75     }
76
77     closedir(dp);
78     return 0;
79 }
80
81 int xmp_mknod(const char *path, mode_t mode, dev_t rdev) {
82     int res;
83
84     /* On Linux this could just be 'mknod(path, mode, rdev)' but this
85        is more portable */
86     if (S_ISREG(mode)) {
87         res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode);
88         if (res >= 0)
89             res = close(res);
90     } else if (S_ISFIFO(mode))
91         res = mkfifo(path, mode);
92     else
93         res = mknod(path, mode, rdev);
94     if (res == -1)
95         return -errno;
96
97     return 0;
98 }
99
100 int xmp_mkdir(const char *path, mode_t mode) {
101     int res;
102
103     res = mkdir(path, mode);
104     if (res == -1)
105         return -errno;
106
107     return 0;
108 }
109
110 int xmp_unlink(const char *path) {
111     int res;
112
113     res = unlink(path);
114     if (res == -1)
115         return -errno;
116
117     return 0;
118 }
119
120 int xmp_rmdir(const char *path) {
121     int res;
122
123     res = rmdir(path);
124     if (res == -1)
125         return -errno;
126
127     return 0;
128 }
129
130 int xmp_symlink(const char *from, const char *to) {
131     int res;
132
133     res = symlink(from, to);
134     if (res == -1)
135         return -errno;
136
137     return 0;
138 }
139
140 int xmp_rename(const char *from, const char *to) {
141     int res;
142
143     res = rename(from, to);
144     if (res == -1)
145         return -errno;
146
147     return 0;
148 }
149
150 int xmp_link(const char *from, const char *to) {
151     int res;
152
153     res = link(from, to);
154     if (res == -1)
155         return -errno;
156
157     return 0;
158 }
159
160 int xmp_chmod(const char *path, mode_t mode) {
161     int res;
162
163     res = chmod(path, mode);
164     if (res == -1)
165         return -errno;
166
167     return 0;
168 }
169
170 int xmp_chown(const char *path, uid_t uid, gid_t gid) {
171     int res;
172
173     res = lchown(path, uid, gid);
174     if (res == -1)
175         return -errno;
176
177     return 0;
178 }
179
180 int xmp_truncate(const char *path, off_t size) {
181     int res;
182
183     res = truncate(path, size);
184     if (res == -1)
185         return -errno;
186
187     return 0;
188 }
189
190 #ifdef HAVE_UTIMENSAT
191 int xmp_utimens(const char *path, const struct timespec ts[2],
192 struct fuse_file_info *fi)
193 {
194     (void) fi;
195     int res;
196
197     /* don't use utime/utimes since they follow symlinks */
198     res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);
199     if (res == -1)
200         return -errno;
201
202     return 0;
203 }
204 #endif
205
206 int xmp_open(const char *path, struct fuse_file_info *fi) {
207     int res;
208
209     res = open(path, fi->flags);
210     if (res == -1)
211         return -errno;
212
213     close(res);
214     return 0;
215 }
216
217 int xmp_read(const char *path, char *buf, size_t size, off_t offset,
218              struct fuse_file_info *fi) {
219     int fd;
220     int res;
221
222     (void) fi;
223     fd = open(path, O_RDONLY);
224     if (fd == -1)
225         return -errno;
226
227     res = pread(fd, buf, size, offset);
228     if (res == -1)
229         res = -errno;
230
231     close(fd);
232     return res;
233 }
234
235 int xmp_write(const char *path, const char *buf, size_t size,
236               off_t offset, struct fuse_file_info *fi) {
237     int fd;
238     int res;
239
240     (void) fi;
241     fd = open(path, O_WRONLY);
242     if (fd == -1)
243         return -errno;
244
245     res = pwrite(fd, buf, size, offset);
246     if (res == -1)
247         res = -errno;
248
249     close(fd);
250     return res;
251 }
252
253 int xmp_statfs(const char *path, struct statvfs *stbuf) {
254     int res;
255
256     res = statvfs(path, stbuf);
257     if (res == -1)
258         return -errno;
259
260     return 0;
261 }
262
263 int xmp_release(const char *path, struct fuse_file_info *fi) {
264     /* Just a stub.      This method is optional and can safely be left
265        unimplemented */
266
267     (void) path;
268     (void) fi;
269     return 0;
270 }
271
272 int xmp_fsync(const char *path, int isdatasync,
273               struct fuse_file_info *fi) {
274     /* Just a stub.      This method is optional and can safely be left
275        unimplemented */
276
277     (void) path;
278     (void) isdatasync;
279     (void) fi;
280     return 0;
281 }
282
283 #ifdef HAVE_POSIX_FALLOCATE
284 int xmp_fallocate(const char *path, int mode,
285                   off_t offset, off_t length, struct fuse_file_info *fi)
286 {
287     int fd;
288     int res;
289
290     (void) fi;
291
292     if (mode)
293         return -EOPNOTSUPP;
294
295     fd = open(path, O_WRONLY);
296     if (fd == -1)
297         return -errno;
298
299     res = -posix_fallocate(fd, offset, length);
300
301     close(fd);
302     return res;
303 }
304 #endif
305