1*9e564957SAndroid Build Coastguard Worker /*
2*9e564957SAndroid Build Coastguard Worker fuse subdir module: offset paths with a base directory
3*9e564957SAndroid Build Coastguard Worker Copyright (C) 2007 Miklos Szeredi <[email protected]>
4*9e564957SAndroid Build Coastguard Worker
5*9e564957SAndroid Build Coastguard Worker This program can be distributed under the terms of the GNU LGPLv2.
6*9e564957SAndroid Build Coastguard Worker See the file COPYING.LIB
7*9e564957SAndroid Build Coastguard Worker */
8*9e564957SAndroid Build Coastguard Worker
9*9e564957SAndroid Build Coastguard Worker #include <fuse_config.h>
10*9e564957SAndroid Build Coastguard Worker
11*9e564957SAndroid Build Coastguard Worker #include <fuse.h>
12*9e564957SAndroid Build Coastguard Worker #include <stdio.h>
13*9e564957SAndroid Build Coastguard Worker #include <stdlib.h>
14*9e564957SAndroid Build Coastguard Worker #include <stddef.h>
15*9e564957SAndroid Build Coastguard Worker #include <string.h>
16*9e564957SAndroid Build Coastguard Worker #include <errno.h>
17*9e564957SAndroid Build Coastguard Worker
18*9e564957SAndroid Build Coastguard Worker struct subdir {
19*9e564957SAndroid Build Coastguard Worker char *base;
20*9e564957SAndroid Build Coastguard Worker size_t baselen;
21*9e564957SAndroid Build Coastguard Worker int rellinks;
22*9e564957SAndroid Build Coastguard Worker struct fuse_fs *next;
23*9e564957SAndroid Build Coastguard Worker };
24*9e564957SAndroid Build Coastguard Worker
subdir_get(void)25*9e564957SAndroid Build Coastguard Worker static struct subdir *subdir_get(void)
26*9e564957SAndroid Build Coastguard Worker {
27*9e564957SAndroid Build Coastguard Worker return fuse_get_context()->private_data;
28*9e564957SAndroid Build Coastguard Worker }
29*9e564957SAndroid Build Coastguard Worker
subdir_addpath(struct subdir * d,const char * path,char ** newpathp)30*9e564957SAndroid Build Coastguard Worker static int subdir_addpath(struct subdir *d, const char *path, char **newpathp)
31*9e564957SAndroid Build Coastguard Worker {
32*9e564957SAndroid Build Coastguard Worker char *newpath = NULL;
33*9e564957SAndroid Build Coastguard Worker
34*9e564957SAndroid Build Coastguard Worker if (path != NULL) {
35*9e564957SAndroid Build Coastguard Worker unsigned newlen = d->baselen + strlen(path);
36*9e564957SAndroid Build Coastguard Worker
37*9e564957SAndroid Build Coastguard Worker newpath = malloc(newlen + 2);
38*9e564957SAndroid Build Coastguard Worker if (!newpath)
39*9e564957SAndroid Build Coastguard Worker return -ENOMEM;
40*9e564957SAndroid Build Coastguard Worker
41*9e564957SAndroid Build Coastguard Worker if (path[0] == '/')
42*9e564957SAndroid Build Coastguard Worker path++;
43*9e564957SAndroid Build Coastguard Worker strcpy(newpath, d->base);
44*9e564957SAndroid Build Coastguard Worker strcpy(newpath + d->baselen, path);
45*9e564957SAndroid Build Coastguard Worker if (!newpath[0])
46*9e564957SAndroid Build Coastguard Worker strcpy(newpath, ".");
47*9e564957SAndroid Build Coastguard Worker }
48*9e564957SAndroid Build Coastguard Worker *newpathp = newpath;
49*9e564957SAndroid Build Coastguard Worker
50*9e564957SAndroid Build Coastguard Worker return 0;
51*9e564957SAndroid Build Coastguard Worker }
52*9e564957SAndroid Build Coastguard Worker
subdir_getattr(const char * path,struct stat * stbuf,struct fuse_file_info * fi)53*9e564957SAndroid Build Coastguard Worker static int subdir_getattr(const char *path, struct stat *stbuf,
54*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
55*9e564957SAndroid Build Coastguard Worker {
56*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
57*9e564957SAndroid Build Coastguard Worker char *newpath;
58*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
59*9e564957SAndroid Build Coastguard Worker if (!err) {
60*9e564957SAndroid Build Coastguard Worker err = fuse_fs_getattr(d->next, newpath, stbuf, fi);
61*9e564957SAndroid Build Coastguard Worker free(newpath);
62*9e564957SAndroid Build Coastguard Worker }
63*9e564957SAndroid Build Coastguard Worker return err;
64*9e564957SAndroid Build Coastguard Worker }
65*9e564957SAndroid Build Coastguard Worker
subdir_access(const char * path,int mask)66*9e564957SAndroid Build Coastguard Worker static int subdir_access(const char *path, int mask)
67*9e564957SAndroid Build Coastguard Worker {
68*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
69*9e564957SAndroid Build Coastguard Worker char *newpath;
70*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
71*9e564957SAndroid Build Coastguard Worker if (!err) {
72*9e564957SAndroid Build Coastguard Worker err = fuse_fs_access(d->next, newpath, mask);
73*9e564957SAndroid Build Coastguard Worker free(newpath);
74*9e564957SAndroid Build Coastguard Worker }
75*9e564957SAndroid Build Coastguard Worker return err;
76*9e564957SAndroid Build Coastguard Worker }
77*9e564957SAndroid Build Coastguard Worker
78*9e564957SAndroid Build Coastguard Worker
count_components(const char * p)79*9e564957SAndroid Build Coastguard Worker static int count_components(const char *p)
80*9e564957SAndroid Build Coastguard Worker {
81*9e564957SAndroid Build Coastguard Worker int ctr;
82*9e564957SAndroid Build Coastguard Worker
83*9e564957SAndroid Build Coastguard Worker for (; *p == '/'; p++);
84*9e564957SAndroid Build Coastguard Worker for (ctr = 0; *p; ctr++) {
85*9e564957SAndroid Build Coastguard Worker for (; *p && *p != '/'; p++);
86*9e564957SAndroid Build Coastguard Worker for (; *p == '/'; p++);
87*9e564957SAndroid Build Coastguard Worker }
88*9e564957SAndroid Build Coastguard Worker return ctr;
89*9e564957SAndroid Build Coastguard Worker }
90*9e564957SAndroid Build Coastguard Worker
strip_common(const char ** sp,const char ** tp)91*9e564957SAndroid Build Coastguard Worker static void strip_common(const char **sp, const char **tp)
92*9e564957SAndroid Build Coastguard Worker {
93*9e564957SAndroid Build Coastguard Worker const char *s = *sp;
94*9e564957SAndroid Build Coastguard Worker const char *t = *tp;
95*9e564957SAndroid Build Coastguard Worker do {
96*9e564957SAndroid Build Coastguard Worker for (; *s == '/'; s++);
97*9e564957SAndroid Build Coastguard Worker for (; *t == '/'; t++);
98*9e564957SAndroid Build Coastguard Worker *tp = t;
99*9e564957SAndroid Build Coastguard Worker *sp = s;
100*9e564957SAndroid Build Coastguard Worker for (; *s == *t && *s && *s != '/'; s++, t++);
101*9e564957SAndroid Build Coastguard Worker } while ((*s == *t && *s) || (!*s && *t == '/') || (*s == '/' && !*t));
102*9e564957SAndroid Build Coastguard Worker }
103*9e564957SAndroid Build Coastguard Worker
transform_symlink(struct subdir * d,const char * path,char * buf,size_t size)104*9e564957SAndroid Build Coastguard Worker static void transform_symlink(struct subdir *d, const char *path,
105*9e564957SAndroid Build Coastguard Worker char *buf, size_t size)
106*9e564957SAndroid Build Coastguard Worker {
107*9e564957SAndroid Build Coastguard Worker const char *l = buf;
108*9e564957SAndroid Build Coastguard Worker size_t llen;
109*9e564957SAndroid Build Coastguard Worker char *s;
110*9e564957SAndroid Build Coastguard Worker int dotdots;
111*9e564957SAndroid Build Coastguard Worker int i;
112*9e564957SAndroid Build Coastguard Worker
113*9e564957SAndroid Build Coastguard Worker if (l[0] != '/' || d->base[0] != '/')
114*9e564957SAndroid Build Coastguard Worker return;
115*9e564957SAndroid Build Coastguard Worker
116*9e564957SAndroid Build Coastguard Worker strip_common(&l, &path);
117*9e564957SAndroid Build Coastguard Worker if (l - buf < (long) d->baselen)
118*9e564957SAndroid Build Coastguard Worker return;
119*9e564957SAndroid Build Coastguard Worker
120*9e564957SAndroid Build Coastguard Worker dotdots = count_components(path);
121*9e564957SAndroid Build Coastguard Worker if (!dotdots)
122*9e564957SAndroid Build Coastguard Worker return;
123*9e564957SAndroid Build Coastguard Worker dotdots--;
124*9e564957SAndroid Build Coastguard Worker
125*9e564957SAndroid Build Coastguard Worker llen = strlen(l);
126*9e564957SAndroid Build Coastguard Worker if (dotdots * 3 + llen + 2 > size)
127*9e564957SAndroid Build Coastguard Worker return;
128*9e564957SAndroid Build Coastguard Worker
129*9e564957SAndroid Build Coastguard Worker s = buf + dotdots * 3;
130*9e564957SAndroid Build Coastguard Worker if (llen)
131*9e564957SAndroid Build Coastguard Worker memmove(s, l, llen + 1);
132*9e564957SAndroid Build Coastguard Worker else if (!dotdots)
133*9e564957SAndroid Build Coastguard Worker strcpy(s, ".");
134*9e564957SAndroid Build Coastguard Worker else
135*9e564957SAndroid Build Coastguard Worker *s = '\0';
136*9e564957SAndroid Build Coastguard Worker
137*9e564957SAndroid Build Coastguard Worker for (s = buf, i = 0; i < dotdots; i++, s += 3)
138*9e564957SAndroid Build Coastguard Worker memcpy(s, "../", 3);
139*9e564957SAndroid Build Coastguard Worker }
140*9e564957SAndroid Build Coastguard Worker
141*9e564957SAndroid Build Coastguard Worker
subdir_readlink(const char * path,char * buf,size_t size)142*9e564957SAndroid Build Coastguard Worker static int subdir_readlink(const char *path, char *buf, size_t size)
143*9e564957SAndroid Build Coastguard Worker {
144*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
145*9e564957SAndroid Build Coastguard Worker char *newpath;
146*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
147*9e564957SAndroid Build Coastguard Worker if (!err) {
148*9e564957SAndroid Build Coastguard Worker err = fuse_fs_readlink(d->next, newpath, buf, size);
149*9e564957SAndroid Build Coastguard Worker if (!err && d->rellinks)
150*9e564957SAndroid Build Coastguard Worker transform_symlink(d, newpath, buf, size);
151*9e564957SAndroid Build Coastguard Worker free(newpath);
152*9e564957SAndroid Build Coastguard Worker }
153*9e564957SAndroid Build Coastguard Worker return err;
154*9e564957SAndroid Build Coastguard Worker }
155*9e564957SAndroid Build Coastguard Worker
subdir_opendir(const char * path,struct fuse_file_info * fi)156*9e564957SAndroid Build Coastguard Worker static int subdir_opendir(const char *path, struct fuse_file_info *fi)
157*9e564957SAndroid Build Coastguard Worker {
158*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
159*9e564957SAndroid Build Coastguard Worker char *newpath;
160*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
161*9e564957SAndroid Build Coastguard Worker if (!err) {
162*9e564957SAndroid Build Coastguard Worker err = fuse_fs_opendir(d->next, newpath, fi);
163*9e564957SAndroid Build Coastguard Worker free(newpath);
164*9e564957SAndroid Build Coastguard Worker }
165*9e564957SAndroid Build Coastguard Worker return err;
166*9e564957SAndroid Build Coastguard Worker }
167*9e564957SAndroid Build Coastguard Worker
subdir_readdir(const char * path,void * buf,fuse_fill_dir_t filler,off_t offset,struct fuse_file_info * fi,enum fuse_readdir_flags flags)168*9e564957SAndroid Build Coastguard Worker static int subdir_readdir(const char *path, void *buf,
169*9e564957SAndroid Build Coastguard Worker fuse_fill_dir_t filler, off_t offset,
170*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi,
171*9e564957SAndroid Build Coastguard Worker enum fuse_readdir_flags flags)
172*9e564957SAndroid Build Coastguard Worker {
173*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
174*9e564957SAndroid Build Coastguard Worker char *newpath;
175*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
176*9e564957SAndroid Build Coastguard Worker if (!err) {
177*9e564957SAndroid Build Coastguard Worker err = fuse_fs_readdir(d->next, newpath, buf, filler, offset,
178*9e564957SAndroid Build Coastguard Worker fi, flags);
179*9e564957SAndroid Build Coastguard Worker free(newpath);
180*9e564957SAndroid Build Coastguard Worker }
181*9e564957SAndroid Build Coastguard Worker return err;
182*9e564957SAndroid Build Coastguard Worker }
183*9e564957SAndroid Build Coastguard Worker
subdir_releasedir(const char * path,struct fuse_file_info * fi)184*9e564957SAndroid Build Coastguard Worker static int subdir_releasedir(const char *path, struct fuse_file_info *fi)
185*9e564957SAndroid Build Coastguard Worker {
186*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
187*9e564957SAndroid Build Coastguard Worker char *newpath;
188*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
189*9e564957SAndroid Build Coastguard Worker if (!err) {
190*9e564957SAndroid Build Coastguard Worker err = fuse_fs_releasedir(d->next, newpath, fi);
191*9e564957SAndroid Build Coastguard Worker free(newpath);
192*9e564957SAndroid Build Coastguard Worker }
193*9e564957SAndroid Build Coastguard Worker return err;
194*9e564957SAndroid Build Coastguard Worker }
195*9e564957SAndroid Build Coastguard Worker
subdir_mknod(const char * path,mode_t mode,dev_t rdev)196*9e564957SAndroid Build Coastguard Worker static int subdir_mknod(const char *path, mode_t mode, dev_t rdev)
197*9e564957SAndroid Build Coastguard Worker {
198*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
199*9e564957SAndroid Build Coastguard Worker char *newpath;
200*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
201*9e564957SAndroid Build Coastguard Worker if (!err) {
202*9e564957SAndroid Build Coastguard Worker err = fuse_fs_mknod(d->next, newpath, mode, rdev);
203*9e564957SAndroid Build Coastguard Worker free(newpath);
204*9e564957SAndroid Build Coastguard Worker }
205*9e564957SAndroid Build Coastguard Worker return err;
206*9e564957SAndroid Build Coastguard Worker }
207*9e564957SAndroid Build Coastguard Worker
subdir_mkdir(const char * path,mode_t mode)208*9e564957SAndroid Build Coastguard Worker static int subdir_mkdir(const char *path, mode_t mode)
209*9e564957SAndroid Build Coastguard Worker {
210*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
211*9e564957SAndroid Build Coastguard Worker char *newpath;
212*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
213*9e564957SAndroid Build Coastguard Worker if (!err) {
214*9e564957SAndroid Build Coastguard Worker err = fuse_fs_mkdir(d->next, newpath, mode);
215*9e564957SAndroid Build Coastguard Worker free(newpath);
216*9e564957SAndroid Build Coastguard Worker }
217*9e564957SAndroid Build Coastguard Worker return err;
218*9e564957SAndroid Build Coastguard Worker }
219*9e564957SAndroid Build Coastguard Worker
subdir_unlink(const char * path)220*9e564957SAndroid Build Coastguard Worker static int subdir_unlink(const char *path)
221*9e564957SAndroid Build Coastguard Worker {
222*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
223*9e564957SAndroid Build Coastguard Worker char *newpath;
224*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
225*9e564957SAndroid Build Coastguard Worker if (!err) {
226*9e564957SAndroid Build Coastguard Worker err = fuse_fs_unlink(d->next, newpath);
227*9e564957SAndroid Build Coastguard Worker free(newpath);
228*9e564957SAndroid Build Coastguard Worker }
229*9e564957SAndroid Build Coastguard Worker return err;
230*9e564957SAndroid Build Coastguard Worker }
231*9e564957SAndroid Build Coastguard Worker
subdir_rmdir(const char * path)232*9e564957SAndroid Build Coastguard Worker static int subdir_rmdir(const char *path)
233*9e564957SAndroid Build Coastguard Worker {
234*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
235*9e564957SAndroid Build Coastguard Worker char *newpath;
236*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
237*9e564957SAndroid Build Coastguard Worker if (!err) {
238*9e564957SAndroid Build Coastguard Worker err = fuse_fs_rmdir(d->next, newpath);
239*9e564957SAndroid Build Coastguard Worker free(newpath);
240*9e564957SAndroid Build Coastguard Worker }
241*9e564957SAndroid Build Coastguard Worker return err;
242*9e564957SAndroid Build Coastguard Worker }
243*9e564957SAndroid Build Coastguard Worker
subdir_symlink(const char * from,const char * path)244*9e564957SAndroid Build Coastguard Worker static int subdir_symlink(const char *from, const char *path)
245*9e564957SAndroid Build Coastguard Worker {
246*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
247*9e564957SAndroid Build Coastguard Worker char *newpath;
248*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
249*9e564957SAndroid Build Coastguard Worker if (!err) {
250*9e564957SAndroid Build Coastguard Worker err = fuse_fs_symlink(d->next, from, newpath);
251*9e564957SAndroid Build Coastguard Worker free(newpath);
252*9e564957SAndroid Build Coastguard Worker }
253*9e564957SAndroid Build Coastguard Worker return err;
254*9e564957SAndroid Build Coastguard Worker }
255*9e564957SAndroid Build Coastguard Worker
subdir_rename(const char * from,const char * to,unsigned int flags)256*9e564957SAndroid Build Coastguard Worker static int subdir_rename(const char *from, const char *to, unsigned int flags)
257*9e564957SAndroid Build Coastguard Worker {
258*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
259*9e564957SAndroid Build Coastguard Worker char *newfrom;
260*9e564957SAndroid Build Coastguard Worker char *newto;
261*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, from, &newfrom);
262*9e564957SAndroid Build Coastguard Worker if (!err) {
263*9e564957SAndroid Build Coastguard Worker err = subdir_addpath(d, to, &newto);
264*9e564957SAndroid Build Coastguard Worker if (!err) {
265*9e564957SAndroid Build Coastguard Worker err = fuse_fs_rename(d->next, newfrom, newto, flags);
266*9e564957SAndroid Build Coastguard Worker free(newto);
267*9e564957SAndroid Build Coastguard Worker }
268*9e564957SAndroid Build Coastguard Worker free(newfrom);
269*9e564957SAndroid Build Coastguard Worker }
270*9e564957SAndroid Build Coastguard Worker return err;
271*9e564957SAndroid Build Coastguard Worker }
272*9e564957SAndroid Build Coastguard Worker
subdir_link(const char * from,const char * to)273*9e564957SAndroid Build Coastguard Worker static int subdir_link(const char *from, const char *to)
274*9e564957SAndroid Build Coastguard Worker {
275*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
276*9e564957SAndroid Build Coastguard Worker char *newfrom;
277*9e564957SAndroid Build Coastguard Worker char *newto;
278*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, from, &newfrom);
279*9e564957SAndroid Build Coastguard Worker if (!err) {
280*9e564957SAndroid Build Coastguard Worker err = subdir_addpath(d, to, &newto);
281*9e564957SAndroid Build Coastguard Worker if (!err) {
282*9e564957SAndroid Build Coastguard Worker err = fuse_fs_link(d->next, newfrom, newto);
283*9e564957SAndroid Build Coastguard Worker free(newto);
284*9e564957SAndroid Build Coastguard Worker }
285*9e564957SAndroid Build Coastguard Worker free(newfrom);
286*9e564957SAndroid Build Coastguard Worker }
287*9e564957SAndroid Build Coastguard Worker return err;
288*9e564957SAndroid Build Coastguard Worker }
289*9e564957SAndroid Build Coastguard Worker
subdir_chmod(const char * path,mode_t mode,struct fuse_file_info * fi)290*9e564957SAndroid Build Coastguard Worker static int subdir_chmod(const char *path, mode_t mode,
291*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
292*9e564957SAndroid Build Coastguard Worker {
293*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
294*9e564957SAndroid Build Coastguard Worker char *newpath;
295*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
296*9e564957SAndroid Build Coastguard Worker if (!err) {
297*9e564957SAndroid Build Coastguard Worker err = fuse_fs_chmod(d->next, newpath, mode, fi);
298*9e564957SAndroid Build Coastguard Worker free(newpath);
299*9e564957SAndroid Build Coastguard Worker }
300*9e564957SAndroid Build Coastguard Worker return err;
301*9e564957SAndroid Build Coastguard Worker }
302*9e564957SAndroid Build Coastguard Worker
subdir_chown(const char * path,uid_t uid,gid_t gid,struct fuse_file_info * fi)303*9e564957SAndroid Build Coastguard Worker static int subdir_chown(const char *path, uid_t uid, gid_t gid,
304*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
305*9e564957SAndroid Build Coastguard Worker {
306*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
307*9e564957SAndroid Build Coastguard Worker char *newpath;
308*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
309*9e564957SAndroid Build Coastguard Worker if (!err) {
310*9e564957SAndroid Build Coastguard Worker err = fuse_fs_chown(d->next, newpath, uid, gid, fi);
311*9e564957SAndroid Build Coastguard Worker free(newpath);
312*9e564957SAndroid Build Coastguard Worker }
313*9e564957SAndroid Build Coastguard Worker return err;
314*9e564957SAndroid Build Coastguard Worker }
315*9e564957SAndroid Build Coastguard Worker
subdir_truncate(const char * path,off_t size,struct fuse_file_info * fi)316*9e564957SAndroid Build Coastguard Worker static int subdir_truncate(const char *path, off_t size,
317*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
318*9e564957SAndroid Build Coastguard Worker {
319*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
320*9e564957SAndroid Build Coastguard Worker char *newpath;
321*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
322*9e564957SAndroid Build Coastguard Worker if (!err) {
323*9e564957SAndroid Build Coastguard Worker err = fuse_fs_truncate(d->next, newpath, size, fi);
324*9e564957SAndroid Build Coastguard Worker free(newpath);
325*9e564957SAndroid Build Coastguard Worker }
326*9e564957SAndroid Build Coastguard Worker return err;
327*9e564957SAndroid Build Coastguard Worker }
328*9e564957SAndroid Build Coastguard Worker
subdir_utimens(const char * path,const struct timespec ts[2],struct fuse_file_info * fi)329*9e564957SAndroid Build Coastguard Worker static int subdir_utimens(const char *path, const struct timespec ts[2],
330*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
331*9e564957SAndroid Build Coastguard Worker {
332*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
333*9e564957SAndroid Build Coastguard Worker char *newpath;
334*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
335*9e564957SAndroid Build Coastguard Worker if (!err) {
336*9e564957SAndroid Build Coastguard Worker err = fuse_fs_utimens(d->next, newpath, ts, fi);
337*9e564957SAndroid Build Coastguard Worker free(newpath);
338*9e564957SAndroid Build Coastguard Worker }
339*9e564957SAndroid Build Coastguard Worker return err;
340*9e564957SAndroid Build Coastguard Worker }
341*9e564957SAndroid Build Coastguard Worker
subdir_create(const char * path,mode_t mode,struct fuse_file_info * fi)342*9e564957SAndroid Build Coastguard Worker static int subdir_create(const char *path, mode_t mode,
343*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
344*9e564957SAndroid Build Coastguard Worker {
345*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
346*9e564957SAndroid Build Coastguard Worker char *newpath;
347*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
348*9e564957SAndroid Build Coastguard Worker if (!err) {
349*9e564957SAndroid Build Coastguard Worker err = fuse_fs_create(d->next, newpath, mode, fi);
350*9e564957SAndroid Build Coastguard Worker free(newpath);
351*9e564957SAndroid Build Coastguard Worker }
352*9e564957SAndroid Build Coastguard Worker return err;
353*9e564957SAndroid Build Coastguard Worker }
354*9e564957SAndroid Build Coastguard Worker
subdir_open(const char * path,struct fuse_file_info * fi)355*9e564957SAndroid Build Coastguard Worker static int subdir_open(const char *path, struct fuse_file_info *fi)
356*9e564957SAndroid Build Coastguard Worker {
357*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
358*9e564957SAndroid Build Coastguard Worker char *newpath;
359*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
360*9e564957SAndroid Build Coastguard Worker if (!err) {
361*9e564957SAndroid Build Coastguard Worker err = fuse_fs_open(d->next, newpath, fi);
362*9e564957SAndroid Build Coastguard Worker free(newpath);
363*9e564957SAndroid Build Coastguard Worker }
364*9e564957SAndroid Build Coastguard Worker return err;
365*9e564957SAndroid Build Coastguard Worker }
366*9e564957SAndroid Build Coastguard Worker
subdir_read_buf(const char * path,struct fuse_bufvec ** bufp,size_t size,off_t offset,struct fuse_file_info * fi)367*9e564957SAndroid Build Coastguard Worker static int subdir_read_buf(const char *path, struct fuse_bufvec **bufp,
368*9e564957SAndroid Build Coastguard Worker size_t size, off_t offset, struct fuse_file_info *fi)
369*9e564957SAndroid Build Coastguard Worker {
370*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
371*9e564957SAndroid Build Coastguard Worker char *newpath;
372*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
373*9e564957SAndroid Build Coastguard Worker if (!err) {
374*9e564957SAndroid Build Coastguard Worker err = fuse_fs_read_buf(d->next, newpath, bufp, size, offset, fi);
375*9e564957SAndroid Build Coastguard Worker free(newpath);
376*9e564957SAndroid Build Coastguard Worker }
377*9e564957SAndroid Build Coastguard Worker return err;
378*9e564957SAndroid Build Coastguard Worker }
379*9e564957SAndroid Build Coastguard Worker
subdir_write_buf(const char * path,struct fuse_bufvec * buf,off_t offset,struct fuse_file_info * fi)380*9e564957SAndroid Build Coastguard Worker static int subdir_write_buf(const char *path, struct fuse_bufvec *buf,
381*9e564957SAndroid Build Coastguard Worker off_t offset, struct fuse_file_info *fi)
382*9e564957SAndroid Build Coastguard Worker {
383*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
384*9e564957SAndroid Build Coastguard Worker char *newpath;
385*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
386*9e564957SAndroid Build Coastguard Worker if (!err) {
387*9e564957SAndroid Build Coastguard Worker err = fuse_fs_write_buf(d->next, newpath, buf, offset, fi);
388*9e564957SAndroid Build Coastguard Worker free(newpath);
389*9e564957SAndroid Build Coastguard Worker }
390*9e564957SAndroid Build Coastguard Worker return err;
391*9e564957SAndroid Build Coastguard Worker }
392*9e564957SAndroid Build Coastguard Worker
subdir_statfs(const char * path,struct statvfs * stbuf)393*9e564957SAndroid Build Coastguard Worker static int subdir_statfs(const char *path, struct statvfs *stbuf)
394*9e564957SAndroid Build Coastguard Worker {
395*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
396*9e564957SAndroid Build Coastguard Worker char *newpath;
397*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
398*9e564957SAndroid Build Coastguard Worker if (!err) {
399*9e564957SAndroid Build Coastguard Worker err = fuse_fs_statfs(d->next, newpath, stbuf);
400*9e564957SAndroid Build Coastguard Worker free(newpath);
401*9e564957SAndroid Build Coastguard Worker }
402*9e564957SAndroid Build Coastguard Worker return err;
403*9e564957SAndroid Build Coastguard Worker }
404*9e564957SAndroid Build Coastguard Worker
subdir_flush(const char * path,struct fuse_file_info * fi)405*9e564957SAndroid Build Coastguard Worker static int subdir_flush(const char *path, struct fuse_file_info *fi)
406*9e564957SAndroid Build Coastguard Worker {
407*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
408*9e564957SAndroid Build Coastguard Worker char *newpath;
409*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
410*9e564957SAndroid Build Coastguard Worker if (!err) {
411*9e564957SAndroid Build Coastguard Worker err = fuse_fs_flush(d->next, newpath, fi);
412*9e564957SAndroid Build Coastguard Worker free(newpath);
413*9e564957SAndroid Build Coastguard Worker }
414*9e564957SAndroid Build Coastguard Worker return err;
415*9e564957SAndroid Build Coastguard Worker }
416*9e564957SAndroid Build Coastguard Worker
subdir_release(const char * path,struct fuse_file_info * fi)417*9e564957SAndroid Build Coastguard Worker static int subdir_release(const char *path, struct fuse_file_info *fi)
418*9e564957SAndroid Build Coastguard Worker {
419*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
420*9e564957SAndroid Build Coastguard Worker char *newpath;
421*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
422*9e564957SAndroid Build Coastguard Worker if (!err) {
423*9e564957SAndroid Build Coastguard Worker err = fuse_fs_release(d->next, newpath, fi);
424*9e564957SAndroid Build Coastguard Worker free(newpath);
425*9e564957SAndroid Build Coastguard Worker }
426*9e564957SAndroid Build Coastguard Worker return err;
427*9e564957SAndroid Build Coastguard Worker }
428*9e564957SAndroid Build Coastguard Worker
subdir_fsync(const char * path,int isdatasync,struct fuse_file_info * fi)429*9e564957SAndroid Build Coastguard Worker static int subdir_fsync(const char *path, int isdatasync,
430*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
431*9e564957SAndroid Build Coastguard Worker {
432*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
433*9e564957SAndroid Build Coastguard Worker char *newpath;
434*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
435*9e564957SAndroid Build Coastguard Worker if (!err) {
436*9e564957SAndroid Build Coastguard Worker err = fuse_fs_fsync(d->next, newpath, isdatasync, fi);
437*9e564957SAndroid Build Coastguard Worker free(newpath);
438*9e564957SAndroid Build Coastguard Worker }
439*9e564957SAndroid Build Coastguard Worker return err;
440*9e564957SAndroid Build Coastguard Worker }
441*9e564957SAndroid Build Coastguard Worker
subdir_fsyncdir(const char * path,int isdatasync,struct fuse_file_info * fi)442*9e564957SAndroid Build Coastguard Worker static int subdir_fsyncdir(const char *path, int isdatasync,
443*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
444*9e564957SAndroid Build Coastguard Worker {
445*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
446*9e564957SAndroid Build Coastguard Worker char *newpath;
447*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
448*9e564957SAndroid Build Coastguard Worker if (!err) {
449*9e564957SAndroid Build Coastguard Worker err = fuse_fs_fsyncdir(d->next, newpath, isdatasync, fi);
450*9e564957SAndroid Build Coastguard Worker free(newpath);
451*9e564957SAndroid Build Coastguard Worker }
452*9e564957SAndroid Build Coastguard Worker return err;
453*9e564957SAndroid Build Coastguard Worker }
454*9e564957SAndroid Build Coastguard Worker
subdir_setxattr(const char * path,const char * name,const char * value,size_t size,int flags)455*9e564957SAndroid Build Coastguard Worker static int subdir_setxattr(const char *path, const char *name,
456*9e564957SAndroid Build Coastguard Worker const char *value, size_t size, int flags)
457*9e564957SAndroid Build Coastguard Worker {
458*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
459*9e564957SAndroid Build Coastguard Worker char *newpath;
460*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
461*9e564957SAndroid Build Coastguard Worker if (!err) {
462*9e564957SAndroid Build Coastguard Worker err = fuse_fs_setxattr(d->next, newpath, name, value, size,
463*9e564957SAndroid Build Coastguard Worker flags);
464*9e564957SAndroid Build Coastguard Worker free(newpath);
465*9e564957SAndroid Build Coastguard Worker }
466*9e564957SAndroid Build Coastguard Worker return err;
467*9e564957SAndroid Build Coastguard Worker }
468*9e564957SAndroid Build Coastguard Worker
subdir_getxattr(const char * path,const char * name,char * value,size_t size)469*9e564957SAndroid Build Coastguard Worker static int subdir_getxattr(const char *path, const char *name, char *value,
470*9e564957SAndroid Build Coastguard Worker size_t size)
471*9e564957SAndroid Build Coastguard Worker {
472*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
473*9e564957SAndroid Build Coastguard Worker char *newpath;
474*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
475*9e564957SAndroid Build Coastguard Worker if (!err) {
476*9e564957SAndroid Build Coastguard Worker err = fuse_fs_getxattr(d->next, newpath, name, value, size);
477*9e564957SAndroid Build Coastguard Worker free(newpath);
478*9e564957SAndroid Build Coastguard Worker }
479*9e564957SAndroid Build Coastguard Worker return err;
480*9e564957SAndroid Build Coastguard Worker }
481*9e564957SAndroid Build Coastguard Worker
subdir_listxattr(const char * path,char * list,size_t size)482*9e564957SAndroid Build Coastguard Worker static int subdir_listxattr(const char *path, char *list, size_t size)
483*9e564957SAndroid Build Coastguard Worker {
484*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
485*9e564957SAndroid Build Coastguard Worker char *newpath;
486*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
487*9e564957SAndroid Build Coastguard Worker if (!err) {
488*9e564957SAndroid Build Coastguard Worker err = fuse_fs_listxattr(d->next, newpath, list, size);
489*9e564957SAndroid Build Coastguard Worker free(newpath);
490*9e564957SAndroid Build Coastguard Worker }
491*9e564957SAndroid Build Coastguard Worker return err;
492*9e564957SAndroid Build Coastguard Worker }
493*9e564957SAndroid Build Coastguard Worker
subdir_removexattr(const char * path,const char * name)494*9e564957SAndroid Build Coastguard Worker static int subdir_removexattr(const char *path, const char *name)
495*9e564957SAndroid Build Coastguard Worker {
496*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
497*9e564957SAndroid Build Coastguard Worker char *newpath;
498*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
499*9e564957SAndroid Build Coastguard Worker if (!err) {
500*9e564957SAndroid Build Coastguard Worker err = fuse_fs_removexattr(d->next, newpath, name);
501*9e564957SAndroid Build Coastguard Worker free(newpath);
502*9e564957SAndroid Build Coastguard Worker }
503*9e564957SAndroid Build Coastguard Worker return err;
504*9e564957SAndroid Build Coastguard Worker }
505*9e564957SAndroid Build Coastguard Worker
subdir_lock(const char * path,struct fuse_file_info * fi,int cmd,struct flock * lock)506*9e564957SAndroid Build Coastguard Worker static int subdir_lock(const char *path, struct fuse_file_info *fi, int cmd,
507*9e564957SAndroid Build Coastguard Worker struct flock *lock)
508*9e564957SAndroid Build Coastguard Worker {
509*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
510*9e564957SAndroid Build Coastguard Worker char *newpath;
511*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
512*9e564957SAndroid Build Coastguard Worker if (!err) {
513*9e564957SAndroid Build Coastguard Worker err = fuse_fs_lock(d->next, newpath, fi, cmd, lock);
514*9e564957SAndroid Build Coastguard Worker free(newpath);
515*9e564957SAndroid Build Coastguard Worker }
516*9e564957SAndroid Build Coastguard Worker return err;
517*9e564957SAndroid Build Coastguard Worker }
518*9e564957SAndroid Build Coastguard Worker
subdir_flock(const char * path,struct fuse_file_info * fi,int op)519*9e564957SAndroid Build Coastguard Worker static int subdir_flock(const char *path, struct fuse_file_info *fi, int op)
520*9e564957SAndroid Build Coastguard Worker {
521*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
522*9e564957SAndroid Build Coastguard Worker char *newpath;
523*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
524*9e564957SAndroid Build Coastguard Worker if (!err) {
525*9e564957SAndroid Build Coastguard Worker err = fuse_fs_flock(d->next, newpath, fi, op);
526*9e564957SAndroid Build Coastguard Worker free(newpath);
527*9e564957SAndroid Build Coastguard Worker }
528*9e564957SAndroid Build Coastguard Worker return err;
529*9e564957SAndroid Build Coastguard Worker }
530*9e564957SAndroid Build Coastguard Worker
subdir_bmap(const char * path,size_t blocksize,uint64_t * idx)531*9e564957SAndroid Build Coastguard Worker static int subdir_bmap(const char *path, size_t blocksize, uint64_t *idx)
532*9e564957SAndroid Build Coastguard Worker {
533*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
534*9e564957SAndroid Build Coastguard Worker char *newpath;
535*9e564957SAndroid Build Coastguard Worker int err = subdir_addpath(d, path, &newpath);
536*9e564957SAndroid Build Coastguard Worker if (!err) {
537*9e564957SAndroid Build Coastguard Worker err = fuse_fs_bmap(d->next, newpath, blocksize, idx);
538*9e564957SAndroid Build Coastguard Worker free(newpath);
539*9e564957SAndroid Build Coastguard Worker }
540*9e564957SAndroid Build Coastguard Worker return err;
541*9e564957SAndroid Build Coastguard Worker }
542*9e564957SAndroid Build Coastguard Worker
subdir_lseek(const char * path,off_t off,int whence,struct fuse_file_info * fi)543*9e564957SAndroid Build Coastguard Worker static off_t subdir_lseek(const char *path, off_t off, int whence,
544*9e564957SAndroid Build Coastguard Worker struct fuse_file_info *fi)
545*9e564957SAndroid Build Coastguard Worker {
546*9e564957SAndroid Build Coastguard Worker struct subdir *ic = subdir_get();
547*9e564957SAndroid Build Coastguard Worker char *newpath;
548*9e564957SAndroid Build Coastguard Worker int res = subdir_addpath(ic, path, &newpath);
549*9e564957SAndroid Build Coastguard Worker if (!res) {
550*9e564957SAndroid Build Coastguard Worker res = fuse_fs_lseek(ic->next, newpath, off, whence, fi);
551*9e564957SAndroid Build Coastguard Worker free(newpath);
552*9e564957SAndroid Build Coastguard Worker }
553*9e564957SAndroid Build Coastguard Worker return res;
554*9e564957SAndroid Build Coastguard Worker }
555*9e564957SAndroid Build Coastguard Worker
subdir_init(struct fuse_conn_info * conn,struct fuse_config * cfg)556*9e564957SAndroid Build Coastguard Worker static void *subdir_init(struct fuse_conn_info *conn,
557*9e564957SAndroid Build Coastguard Worker struct fuse_config *cfg)
558*9e564957SAndroid Build Coastguard Worker {
559*9e564957SAndroid Build Coastguard Worker struct subdir *d = subdir_get();
560*9e564957SAndroid Build Coastguard Worker fuse_fs_init(d->next, conn, cfg);
561*9e564957SAndroid Build Coastguard Worker /* Don't touch cfg->nullpath_ok, we can work with
562*9e564957SAndroid Build Coastguard Worker either */
563*9e564957SAndroid Build Coastguard Worker return d;
564*9e564957SAndroid Build Coastguard Worker }
565*9e564957SAndroid Build Coastguard Worker
subdir_destroy(void * data)566*9e564957SAndroid Build Coastguard Worker static void subdir_destroy(void *data)
567*9e564957SAndroid Build Coastguard Worker {
568*9e564957SAndroid Build Coastguard Worker struct subdir *d = data;
569*9e564957SAndroid Build Coastguard Worker fuse_fs_destroy(d->next);
570*9e564957SAndroid Build Coastguard Worker free(d->base);
571*9e564957SAndroid Build Coastguard Worker free(d);
572*9e564957SAndroid Build Coastguard Worker }
573*9e564957SAndroid Build Coastguard Worker
574*9e564957SAndroid Build Coastguard Worker static const struct fuse_operations subdir_oper = {
575*9e564957SAndroid Build Coastguard Worker .destroy = subdir_destroy,
576*9e564957SAndroid Build Coastguard Worker .init = subdir_init,
577*9e564957SAndroid Build Coastguard Worker .getattr = subdir_getattr,
578*9e564957SAndroid Build Coastguard Worker .access = subdir_access,
579*9e564957SAndroid Build Coastguard Worker .readlink = subdir_readlink,
580*9e564957SAndroid Build Coastguard Worker .opendir = subdir_opendir,
581*9e564957SAndroid Build Coastguard Worker .readdir = subdir_readdir,
582*9e564957SAndroid Build Coastguard Worker .releasedir = subdir_releasedir,
583*9e564957SAndroid Build Coastguard Worker .mknod = subdir_mknod,
584*9e564957SAndroid Build Coastguard Worker .mkdir = subdir_mkdir,
585*9e564957SAndroid Build Coastguard Worker .symlink = subdir_symlink,
586*9e564957SAndroid Build Coastguard Worker .unlink = subdir_unlink,
587*9e564957SAndroid Build Coastguard Worker .rmdir = subdir_rmdir,
588*9e564957SAndroid Build Coastguard Worker .rename = subdir_rename,
589*9e564957SAndroid Build Coastguard Worker .link = subdir_link,
590*9e564957SAndroid Build Coastguard Worker .chmod = subdir_chmod,
591*9e564957SAndroid Build Coastguard Worker .chown = subdir_chown,
592*9e564957SAndroid Build Coastguard Worker .truncate = subdir_truncate,
593*9e564957SAndroid Build Coastguard Worker .utimens = subdir_utimens,
594*9e564957SAndroid Build Coastguard Worker .create = subdir_create,
595*9e564957SAndroid Build Coastguard Worker .open = subdir_open,
596*9e564957SAndroid Build Coastguard Worker .read_buf = subdir_read_buf,
597*9e564957SAndroid Build Coastguard Worker .write_buf = subdir_write_buf,
598*9e564957SAndroid Build Coastguard Worker .statfs = subdir_statfs,
599*9e564957SAndroid Build Coastguard Worker .flush = subdir_flush,
600*9e564957SAndroid Build Coastguard Worker .release = subdir_release,
601*9e564957SAndroid Build Coastguard Worker .fsync = subdir_fsync,
602*9e564957SAndroid Build Coastguard Worker .fsyncdir = subdir_fsyncdir,
603*9e564957SAndroid Build Coastguard Worker .setxattr = subdir_setxattr,
604*9e564957SAndroid Build Coastguard Worker .getxattr = subdir_getxattr,
605*9e564957SAndroid Build Coastguard Worker .listxattr = subdir_listxattr,
606*9e564957SAndroid Build Coastguard Worker .removexattr = subdir_removexattr,
607*9e564957SAndroid Build Coastguard Worker .lock = subdir_lock,
608*9e564957SAndroid Build Coastguard Worker .flock = subdir_flock,
609*9e564957SAndroid Build Coastguard Worker .bmap = subdir_bmap,
610*9e564957SAndroid Build Coastguard Worker .lseek = subdir_lseek,
611*9e564957SAndroid Build Coastguard Worker };
612*9e564957SAndroid Build Coastguard Worker
613*9e564957SAndroid Build Coastguard Worker static const struct fuse_opt subdir_opts[] = {
614*9e564957SAndroid Build Coastguard Worker FUSE_OPT_KEY("-h", 0),
615*9e564957SAndroid Build Coastguard Worker FUSE_OPT_KEY("--help", 0),
616*9e564957SAndroid Build Coastguard Worker { "subdir=%s", offsetof(struct subdir, base), 0 },
617*9e564957SAndroid Build Coastguard Worker { "rellinks", offsetof(struct subdir, rellinks), 1 },
618*9e564957SAndroid Build Coastguard Worker { "norellinks", offsetof(struct subdir, rellinks), 0 },
619*9e564957SAndroid Build Coastguard Worker FUSE_OPT_END
620*9e564957SAndroid Build Coastguard Worker };
621*9e564957SAndroid Build Coastguard Worker
subdir_help(void)622*9e564957SAndroid Build Coastguard Worker static void subdir_help(void)
623*9e564957SAndroid Build Coastguard Worker {
624*9e564957SAndroid Build Coastguard Worker printf(
625*9e564957SAndroid Build Coastguard Worker " -o subdir=DIR prepend this directory to all paths (mandatory)\n"
626*9e564957SAndroid Build Coastguard Worker " -o [no]rellinks transform absolute symlinks to relative\n");
627*9e564957SAndroid Build Coastguard Worker }
628*9e564957SAndroid Build Coastguard Worker
subdir_opt_proc(void * data,const char * arg,int key,struct fuse_args * outargs)629*9e564957SAndroid Build Coastguard Worker static int subdir_opt_proc(void *data, const char *arg, int key,
630*9e564957SAndroid Build Coastguard Worker struct fuse_args *outargs)
631*9e564957SAndroid Build Coastguard Worker {
632*9e564957SAndroid Build Coastguard Worker (void) data; (void) arg; (void) outargs;
633*9e564957SAndroid Build Coastguard Worker
634*9e564957SAndroid Build Coastguard Worker if (!key) {
635*9e564957SAndroid Build Coastguard Worker subdir_help();
636*9e564957SAndroid Build Coastguard Worker return -1;
637*9e564957SAndroid Build Coastguard Worker }
638*9e564957SAndroid Build Coastguard Worker
639*9e564957SAndroid Build Coastguard Worker return 1;
640*9e564957SAndroid Build Coastguard Worker }
641*9e564957SAndroid Build Coastguard Worker
subdir_new(struct fuse_args * args,struct fuse_fs * next[])642*9e564957SAndroid Build Coastguard Worker static struct fuse_fs *subdir_new(struct fuse_args *args,
643*9e564957SAndroid Build Coastguard Worker struct fuse_fs *next[])
644*9e564957SAndroid Build Coastguard Worker {
645*9e564957SAndroid Build Coastguard Worker struct fuse_fs *fs;
646*9e564957SAndroid Build Coastguard Worker struct subdir *d;
647*9e564957SAndroid Build Coastguard Worker
648*9e564957SAndroid Build Coastguard Worker d = calloc(1, sizeof(struct subdir));
649*9e564957SAndroid Build Coastguard Worker if (d == NULL) {
650*9e564957SAndroid Build Coastguard Worker fuse_log(FUSE_LOG_ERR, "fuse-subdir: memory allocation failed\n");
651*9e564957SAndroid Build Coastguard Worker return NULL;
652*9e564957SAndroid Build Coastguard Worker }
653*9e564957SAndroid Build Coastguard Worker
654*9e564957SAndroid Build Coastguard Worker if (fuse_opt_parse(args, d, subdir_opts, subdir_opt_proc) == -1)
655*9e564957SAndroid Build Coastguard Worker goto out_free;
656*9e564957SAndroid Build Coastguard Worker
657*9e564957SAndroid Build Coastguard Worker if (!next[0] || next[1]) {
658*9e564957SAndroid Build Coastguard Worker fuse_log(FUSE_LOG_ERR, "fuse-subdir: exactly one next filesystem required\n");
659*9e564957SAndroid Build Coastguard Worker goto out_free;
660*9e564957SAndroid Build Coastguard Worker }
661*9e564957SAndroid Build Coastguard Worker
662*9e564957SAndroid Build Coastguard Worker if (!d->base) {
663*9e564957SAndroid Build Coastguard Worker fuse_log(FUSE_LOG_ERR, "fuse-subdir: missing 'subdir' option\n");
664*9e564957SAndroid Build Coastguard Worker goto out_free;
665*9e564957SAndroid Build Coastguard Worker }
666*9e564957SAndroid Build Coastguard Worker
667*9e564957SAndroid Build Coastguard Worker if (d->base[0] && d->base[strlen(d->base)-1] != '/') {
668*9e564957SAndroid Build Coastguard Worker char *tmp = realloc(d->base, strlen(d->base) + 2);
669*9e564957SAndroid Build Coastguard Worker if (!tmp) {
670*9e564957SAndroid Build Coastguard Worker fuse_log(FUSE_LOG_ERR, "fuse-subdir: memory allocation failed\n");
671*9e564957SAndroid Build Coastguard Worker goto out_free;
672*9e564957SAndroid Build Coastguard Worker }
673*9e564957SAndroid Build Coastguard Worker d->base = tmp;
674*9e564957SAndroid Build Coastguard Worker strcat(d->base, "/");
675*9e564957SAndroid Build Coastguard Worker }
676*9e564957SAndroid Build Coastguard Worker d->baselen = strlen(d->base);
677*9e564957SAndroid Build Coastguard Worker d->next = next[0];
678*9e564957SAndroid Build Coastguard Worker fs = fuse_fs_new(&subdir_oper, sizeof(subdir_oper), d);
679*9e564957SAndroid Build Coastguard Worker if (!fs)
680*9e564957SAndroid Build Coastguard Worker goto out_free;
681*9e564957SAndroid Build Coastguard Worker return fs;
682*9e564957SAndroid Build Coastguard Worker
683*9e564957SAndroid Build Coastguard Worker out_free:
684*9e564957SAndroid Build Coastguard Worker free(d->base);
685*9e564957SAndroid Build Coastguard Worker free(d);
686*9e564957SAndroid Build Coastguard Worker return NULL;
687*9e564957SAndroid Build Coastguard Worker }
688*9e564957SAndroid Build Coastguard Worker
689*9e564957SAndroid Build Coastguard Worker FUSE_REGISTER_MODULE(subdir, subdir_new);
690