Blame


1 5551e51d 2006-07-23 devnull /*
2 5551e51d 2006-07-23 devnull * 9P to FUSE translator. Acts as FUSE server, 9P client.
3 5551e51d 2006-07-23 devnull * Mounts 9P servers via FUSE kernel module.
4 5551e51d 2006-07-23 devnull *
5 5551e51d 2006-07-23 devnull * There are four procs in this threaded program
6 5551e51d 2006-07-23 devnull * (ignoring the one that runs main and then exits).
7 5551e51d 2006-07-23 devnull * The first proc reads FUSE requests from /dev/fuse.
8 5551e51d 2006-07-23 devnull * It sends the requests over a channel to a second proc,
9 5551e51d 2006-07-23 devnull * which serves the requests. Each request runs in a
10 5551e51d 2006-07-23 devnull * thread in that second proc. Those threads do write
11 5551e51d 2006-07-23 devnull * FUSE replies, which in theory might block, but in practice don't.
12 5551e51d 2006-07-23 devnull * The 9P interactions are handled by lib9pclient, which
13 5551e51d 2006-07-23 devnull * allocates two more procs, one for reading and one for
14 5551e51d 2006-07-23 devnull * writing the 9P connection. Thus the many threads in the
15 5551e51d 2006-07-23 devnull * request proc can do 9P interactions without blocking.
16 5551e51d 2006-07-23 devnull */
17 fa325e9b 2020-01-10 cross
18 05f50fe6 2006-07-23 devnull #define _GNU_SOURCE 1 /* for O_DIRECTORY on Linux */
19 5551e51d 2006-07-23 devnull #include "a.h"
20 5551e51d 2006-07-23 devnull
21 05f50fe6 2006-07-23 devnull /* GNUisms */
22 05f50fe6 2006-07-23 devnull #ifndef O_DIRECTORY
23 05f50fe6 2006-07-23 devnull #define O_DIRECTORY 0
24 05f50fe6 2006-07-23 devnull #endif
25 83ab7d88 2007-11-27 rsc
26 05f50fe6 2006-07-23 devnull #ifndef O_LARGEFILE
27 7dc6d244 2008-06-19 rsc # define O_LARGEFILE 0
28 05f50fe6 2006-07-23 devnull #endif
29 83ab7d88 2007-11-27 rsc
30 7dc6d244 2008-06-19 rsc /*
31 7dc6d244 2008-06-19 rsc * Work around glibc's broken <bits/fcntl.h> which defines
32 7dc6d244 2008-06-19 rsc * O_LARGEFILE to 0 on 64 bit architectures. But, on those same
33 7dc6d244 2008-06-19 rsc * architectures, linux _forces_ O_LARGEFILE (which is always
34 7dc6d244 2008-06-19 rsc * 0100000 in the kernel) at each file open. FUSE is all too
35 7dc6d244 2008-06-19 rsc * happy to pass the flag onto us, where we'd have no idea what
36 7dc6d244 2008-06-19 rsc * to do with it if we trusted glibc.
37 9bcee1f0 2014-12-02 rsc *
38 9bcee1f0 2014-12-02 rsc * On ARM however, the O_LARGEFILE is set correctly.
39 7dc6d244 2008-06-19 rsc */
40 9bcee1f0 2014-12-02 rsc
41 9bcee1f0 2014-12-02 rsc #if defined(__linux__) && !defined(__arm__)
42 7dc6d244 2008-06-19 rsc # undef O_LARGEFILE
43 7dc6d244 2008-06-19 rsc # define O_LARGEFILE 0100000
44 7dc6d244 2008-06-19 rsc #endif
45 7dc6d244 2008-06-19 rsc
46 83ab7d88 2007-11-27 rsc #ifndef O_CLOEXEC
47 83ab7d88 2007-11-27 rsc # if defined(__linux__)
48 83ab7d88 2007-11-27 rsc # define O_CLOEXEC 02000000 /* Sigh */
49 83ab7d88 2007-11-27 rsc # else
50 83ab7d88 2007-11-27 rsc # define O_CLOEXEC 0
51 83ab7d88 2007-11-27 rsc # endif
52 9c15a456 2006-07-27 devnull #endif
53 05f50fe6 2006-07-23 devnull
54 93f9789c 2020-01-13 rsc #ifndef FMODE_EXEC
55 93f9789c 2020-01-13 rsc # if defined(__linux__)
56 93f9789c 2020-01-13 rsc # define FMODE_EXEC 040
57 93f9789c 2020-01-13 rsc # else
58 93f9789c 2020-01-13 rsc # define FMODE_EXEC 0
59 93f9789c 2020-01-13 rsc # endif
60 93f9789c 2020-01-13 rsc #endif
61 93f9789c 2020-01-13 rsc
62 5551e51d 2006-07-23 devnull int debug;
63 5551e51d 2006-07-23 devnull char *argv0;
64 9ec386fe 2007-06-21 devnull char *aname = "";
65 5551e51d 2006-07-23 devnull void fusedispatch(void*);
66 5551e51d 2006-07-23 devnull Channel *fusechan;
67 5551e51d 2006-07-23 devnull
68 5551e51d 2006-07-23 devnull enum
69 5551e51d 2006-07-23 devnull {
70 5551e51d 2006-07-23 devnull STACK = 8192
71 5551e51d 2006-07-23 devnull };
72 5551e51d 2006-07-23 devnull
73 5551e51d 2006-07-23 devnull /*
74 5551e51d 2006-07-23 devnull * The number of seconds that the kernel can cache
75 5551e51d 2006-07-23 devnull * returned file attributes. FUSE's default is 1.0.
76 5551e51d 2006-07-23 devnull * I haven't experimented with using 0.
77 5551e51d 2006-07-23 devnull */
78 5551e51d 2006-07-23 devnull double attrtimeout = 1.0;
79 5551e51d 2006-07-23 devnull
80 5551e51d 2006-07-23 devnull /*
81 5551e51d 2006-07-23 devnull * The number of seconds that the kernel can cache
82 5551e51d 2006-07-23 devnull * the returned entry nodeids returned by lookup.
83 5551e51d 2006-07-23 devnull * I haven't experimented with other values.
84 5551e51d 2006-07-23 devnull */
85 5551e51d 2006-07-23 devnull double entrytimeout = 1.0;
86 5551e51d 2006-07-23 devnull
87 5551e51d 2006-07-23 devnull CFsys *fsys;
88 5551e51d 2006-07-23 devnull CFid *fsysroot;
89 9ec386fe 2007-06-21 devnull void init9p(char*, char*);
90 5551e51d 2006-07-23 devnull
91 5551e51d 2006-07-23 devnull void
92 5551e51d 2006-07-23 devnull usage(void)
93 5551e51d 2006-07-23 devnull {
94 9ec386fe 2007-06-21 devnull fprint(2, "usage: 9pfuse [-D] [-A attrtimeout] [-a aname] address mtpt\n");
95 5551e51d 2006-07-23 devnull exit(1);
96 5551e51d 2006-07-23 devnull }
97 5551e51d 2006-07-23 devnull
98 5551e51d 2006-07-23 devnull void fusereader(void*);
99 e63025d0 2008-04-17 rsc void watchfd(void*);
100 5551e51d 2006-07-23 devnull
101 5551e51d 2006-07-23 devnull void
102 5551e51d 2006-07-23 devnull threadmain(int argc, char **argv)
103 5551e51d 2006-07-23 devnull {
104 5551e51d 2006-07-23 devnull ARGBEGIN{
105 5551e51d 2006-07-23 devnull case 'D':
106 5551e51d 2006-07-23 devnull chatty9pclient++;
107 5551e51d 2006-07-23 devnull debug++;
108 5551e51d 2006-07-23 devnull break;
109 9ec386fe 2007-06-21 devnull case 'A':
110 5551e51d 2006-07-23 devnull attrtimeout = atof(EARGF(usage()));
111 9ec386fe 2007-06-21 devnull break;
112 9ec386fe 2007-06-21 devnull case 'a':
113 9ec386fe 2007-06-21 devnull aname = EARGF(usage());
114 5551e51d 2006-07-23 devnull break;
115 5551e51d 2006-07-23 devnull default:
116 5551e51d 2006-07-23 devnull usage();
117 5551e51d 2006-07-23 devnull }ARGEND
118 5551e51d 2006-07-23 devnull
119 5551e51d 2006-07-23 devnull if(argc != 2)
120 5551e51d 2006-07-23 devnull usage();
121 5551e51d 2006-07-23 devnull
122 5551e51d 2006-07-23 devnull quotefmtinstall();
123 5551e51d 2006-07-23 devnull fmtinstall('F', fcallfmt);
124 5551e51d 2006-07-23 devnull fmtinstall('M', dirmodefmt);
125 5551e51d 2006-07-23 devnull fmtinstall('G', fusefmt);
126 5551e51d 2006-07-23 devnull
127 a695bc7d 2006-07-23 devnull setsid(); /* won't be able to use console, but can't be interrupted */
128 a695bc7d 2006-07-23 devnull
129 9ec386fe 2007-06-21 devnull init9p(argv[0], aname);
130 5551e51d 2006-07-23 devnull initfuse(argv[1]);
131 5551e51d 2006-07-23 devnull
132 5551e51d 2006-07-23 devnull fusechan = chancreate(sizeof(void*), 0);
133 5551e51d 2006-07-23 devnull proccreate(fusedispatch, nil, STACK);
134 5551e51d 2006-07-23 devnull sendp(fusechan, nil); /* sync */
135 5551e51d 2006-07-23 devnull
136 5551e51d 2006-07-23 devnull proccreate(fusereader, nil, STACK);
137 a83ccf38 2006-07-27 devnull /*
138 a83ccf38 2006-07-27 devnull * Now that we're serving FUSE, we can wait
139 a83ccf38 2006-07-27 devnull * for the mount to finish and exit back to the user.
140 a83ccf38 2006-07-27 devnull */
141 a83ccf38 2006-07-27 devnull waitfuse();
142 5551e51d 2006-07-23 devnull threadexits(0);
143 5551e51d 2006-07-23 devnull }
144 5551e51d 2006-07-23 devnull
145 5551e51d 2006-07-23 devnull void
146 5551e51d 2006-07-23 devnull fusereader(void *v)
147 5551e51d 2006-07-23 devnull {
148 5551e51d 2006-07-23 devnull FuseMsg *m;
149 5551e51d 2006-07-23 devnull
150 5551e51d 2006-07-23 devnull while((m = readfusemsg()) != nil)
151 5551e51d 2006-07-23 devnull sendp(fusechan, m);
152 5551e51d 2006-07-23 devnull
153 5551e51d 2006-07-23 devnull fusemtpt = nil; /* no need to unmount */
154 5551e51d 2006-07-23 devnull threadexitsall(0);
155 5551e51d 2006-07-23 devnull }
156 5551e51d 2006-07-23 devnull
157 5551e51d 2006-07-23 devnull void
158 9ec386fe 2007-06-21 devnull init9p(char *addr, char *spec)
159 5551e51d 2006-07-23 devnull {
160 5551e51d 2006-07-23 devnull int fd;
161 5551e51d 2006-07-23 devnull
162 e63025d0 2008-04-17 rsc if(strcmp(addr, "-") == 0)
163 e63025d0 2008-04-17 rsc fd = 0;
164 e63025d0 2008-04-17 rsc else
165 e63025d0 2008-04-17 rsc if((fd = dial(netmkaddr(addr, "tcp", "564"), nil, nil, nil)) < 0)
166 e63025d0 2008-04-17 rsc sysfatal("dial %s: %r", addr);
167 e63025d0 2008-04-17 rsc proccreate(watchfd, (void*)(uintptr)fd, STACK);
168 9ec386fe 2007-06-21 devnull if((fsys = fsmount(fd, spec)) == nil)
169 5551e51d 2006-07-23 devnull sysfatal("fsmount: %r");
170 5551e51d 2006-07-23 devnull fsysroot = fsroot(fsys);
171 5551e51d 2006-07-23 devnull }
172 5551e51d 2006-07-23 devnull
173 5551e51d 2006-07-23 devnull /*
174 5551e51d 2006-07-23 devnull * FUSE uses nodeids to refer to active "struct inodes"
175 5551e51d 2006-07-23 devnull * (9P's unopened fids). FUSE uses fhs to refer to active
176 fa325e9b 2020-01-10 cross * "struct fuse_files" (9P's opened fids). The choice of
177 5551e51d 2006-07-23 devnull * numbers is up to us except that nodeid 1 is the root directory.
178 fa325e9b 2020-01-10 cross * We use the same number space for both and call the
179 5551e51d 2006-07-23 devnull * bookkeeping structure a FuseFid.
180 5551e51d 2006-07-23 devnull *
181 fa325e9b 2020-01-10 cross * FUSE requires nodeids to have associated generation
182 fa325e9b 2020-01-10 cross * numbers. If we reuse a nodeid, we have to bump the
183 5551e51d 2006-07-23 devnull * generation number to guarantee that the nodeid,gen
184 5551e51d 2006-07-23 devnull * combination is never reused.
185 fa325e9b 2020-01-10 cross *
186 5551e51d 2006-07-23 devnull * There are also inode numbers returned in directory reads
187 5551e51d 2006-07-23 devnull * and file attributes, but these do NOT need to match the nodeids.
188 5551e51d 2006-07-23 devnull * We use a combination of qid.path and qid.type as the inode
189 5551e51d 2006-07-23 devnull * number.
190 5551e51d 2006-07-23 devnull */
191 5551e51d 2006-07-23 devnull /*
192 5551e51d 2006-07-23 devnull * TO DO: reference count the fids.
193 5551e51d 2006-07-23 devnull */
194 5551e51d 2006-07-23 devnull typedef struct Fusefid Fusefid;
195 5551e51d 2006-07-23 devnull struct Fusefid
196 5551e51d 2006-07-23 devnull {
197 5551e51d 2006-07-23 devnull Fusefid *next;
198 5551e51d 2006-07-23 devnull CFid *fid;
199 5551e51d 2006-07-23 devnull int ref;
200 5551e51d 2006-07-23 devnull int id;
201 5551e51d 2006-07-23 devnull int gen;
202 5551e51d 2006-07-23 devnull int isnodeid;
203 fa325e9b 2020-01-10 cross
204 5551e51d 2006-07-23 devnull /* directory read state */
205 5551e51d 2006-07-23 devnull Dir *d0;
206 5551e51d 2006-07-23 devnull Dir *d;
207 5551e51d 2006-07-23 devnull int nd;
208 5551e51d 2006-07-23 devnull int off;
209 5551e51d 2006-07-23 devnull };
210 5551e51d 2006-07-23 devnull
211 5551e51d 2006-07-23 devnull Fusefid **fusefid;
212 5551e51d 2006-07-23 devnull int nfusefid;
213 5551e51d 2006-07-23 devnull Fusefid *freefusefidlist;
214 5551e51d 2006-07-23 devnull
215 5551e51d 2006-07-23 devnull Fusefid*
216 5551e51d 2006-07-23 devnull allocfusefid(void)
217 5551e51d 2006-07-23 devnull {
218 5551e51d 2006-07-23 devnull Fusefid *f;
219 fa325e9b 2020-01-10 cross
220 5551e51d 2006-07-23 devnull if((f = freefusefidlist) == nil){
221 5551e51d 2006-07-23 devnull f = emalloc(sizeof *f);
222 5551e51d 2006-07-23 devnull fusefid = erealloc(fusefid, (nfusefid+1)*sizeof *fusefid);
223 5551e51d 2006-07-23 devnull f->id = nfusefid;
224 5551e51d 2006-07-23 devnull fusefid[f->id] = f;
225 5551e51d 2006-07-23 devnull nfusefid++;
226 5551e51d 2006-07-23 devnull }else
227 5551e51d 2006-07-23 devnull freefusefidlist = f->next;
228 5551e51d 2006-07-23 devnull f->next = nil;
229 5551e51d 2006-07-23 devnull f->ref = 1;
230 5551e51d 2006-07-23 devnull f->isnodeid = -1;
231 5551e51d 2006-07-23 devnull return f;
232 5551e51d 2006-07-23 devnull }
233 5551e51d 2006-07-23 devnull
234 5551e51d 2006-07-23 devnull void
235 5551e51d 2006-07-23 devnull freefusefid(Fusefid *f)
236 5551e51d 2006-07-23 devnull {
237 5551e51d 2006-07-23 devnull if(--f->ref > 0)
238 5551e51d 2006-07-23 devnull return;
239 5551e51d 2006-07-23 devnull assert(f->ref == 0);
240 5551e51d 2006-07-23 devnull if(f->fid)
241 5551e51d 2006-07-23 devnull fsclose(f->fid);
242 5551e51d 2006-07-23 devnull if(f->d0)
243 5551e51d 2006-07-23 devnull free(f->d0);
244 5551e51d 2006-07-23 devnull f->off = 0;
245 5551e51d 2006-07-23 devnull f->d0 = nil;
246 5551e51d 2006-07-23 devnull f->fid = nil;
247 5551e51d 2006-07-23 devnull f->d = nil;
248 5551e51d 2006-07-23 devnull f->nd = 0;
249 5551e51d 2006-07-23 devnull f->next = freefusefidlist;
250 5551e51d 2006-07-23 devnull f->isnodeid = -1;
251 5551e51d 2006-07-23 devnull freefusefidlist = f;
252 5551e51d 2006-07-23 devnull }
253 5551e51d 2006-07-23 devnull
254 5551e51d 2006-07-23 devnull uvlong
255 5551e51d 2006-07-23 devnull _alloc(CFid *fid, int isnodeid)
256 5551e51d 2006-07-23 devnull {
257 5551e51d 2006-07-23 devnull Fusefid *ff;
258 fa325e9b 2020-01-10 cross
259 5551e51d 2006-07-23 devnull ff = allocfusefid();
260 5551e51d 2006-07-23 devnull ff->fid = fid;
261 5551e51d 2006-07-23 devnull ff->isnodeid = isnodeid;
262 5551e51d 2006-07-23 devnull ff->gen++;
263 5551e51d 2006-07-23 devnull return ff->id+2; /* skip 0 and 1 */
264 5551e51d 2006-07-23 devnull }
265 5551e51d 2006-07-23 devnull
266 5551e51d 2006-07-23 devnull uvlong
267 5551e51d 2006-07-23 devnull allocfh(CFid *fid)
268 5551e51d 2006-07-23 devnull {
269 5551e51d 2006-07-23 devnull return _alloc(fid, 0);
270 5551e51d 2006-07-23 devnull }
271 d4ccb0a9 2012-09-11 rsc
272 5551e51d 2006-07-23 devnull uvlong
273 5551e51d 2006-07-23 devnull allocnodeid(CFid *fid)
274 5551e51d 2006-07-23 devnull {
275 5551e51d 2006-07-23 devnull return _alloc(fid, 1);
276 5551e51d 2006-07-23 devnull }
277 5551e51d 2006-07-23 devnull
278 5551e51d 2006-07-23 devnull Fusefid*
279 5551e51d 2006-07-23 devnull lookupfusefid(uvlong id, int isnodeid)
280 5551e51d 2006-07-23 devnull {
281 5551e51d 2006-07-23 devnull Fusefid *ff;
282 5551e51d 2006-07-23 devnull if(id < 2 || id >= nfusefid+2)
283 5551e51d 2006-07-23 devnull return nil;
284 5551e51d 2006-07-23 devnull ff = fusefid[(int)id-2];
285 5551e51d 2006-07-23 devnull if(ff->isnodeid != isnodeid)
286 5551e51d 2006-07-23 devnull return nil;
287 5551e51d 2006-07-23 devnull return ff;
288 5551e51d 2006-07-23 devnull }
289 5551e51d 2006-07-23 devnull
290 5551e51d 2006-07-23 devnull CFid*
291 5551e51d 2006-07-23 devnull _lookupcfid(uvlong id, int isnodeid)
292 5551e51d 2006-07-23 devnull {
293 5551e51d 2006-07-23 devnull Fusefid *ff;
294 fa325e9b 2020-01-10 cross
295 5551e51d 2006-07-23 devnull if((ff = lookupfusefid(id, isnodeid)) == nil)
296 5551e51d 2006-07-23 devnull return nil;
297 5551e51d 2006-07-23 devnull return ff->fid;
298 5551e51d 2006-07-23 devnull }
299 5551e51d 2006-07-23 devnull
300 5551e51d 2006-07-23 devnull CFid*
301 5551e51d 2006-07-23 devnull fh2fid(uvlong fh)
302 5551e51d 2006-07-23 devnull {
303 5551e51d 2006-07-23 devnull return _lookupcfid(fh, 0);
304 5551e51d 2006-07-23 devnull }
305 5551e51d 2006-07-23 devnull
306 5551e51d 2006-07-23 devnull CFid*
307 5551e51d 2006-07-23 devnull nodeid2fid(uvlong nodeid)
308 5551e51d 2006-07-23 devnull {
309 5551e51d 2006-07-23 devnull if(nodeid == 1)
310 5551e51d 2006-07-23 devnull return fsysroot;
311 5551e51d 2006-07-23 devnull return _lookupcfid(nodeid, 1);
312 5551e51d 2006-07-23 devnull }
313 5551e51d 2006-07-23 devnull
314 5551e51d 2006-07-23 devnull uvlong
315 5551e51d 2006-07-23 devnull qid2inode(Qid q)
316 5551e51d 2006-07-23 devnull {
317 5551e51d 2006-07-23 devnull return q.path | ((uvlong)q.type<<56);
318 5551e51d 2006-07-23 devnull }
319 5551e51d 2006-07-23 devnull
320 5551e51d 2006-07-23 devnull void
321 5551e51d 2006-07-23 devnull dir2attr(Dir *d, struct fuse_attr *attr)
322 5551e51d 2006-07-23 devnull {
323 5551e51d 2006-07-23 devnull attr->ino = qid2inode(d->qid);
324 5551e51d 2006-07-23 devnull attr->size = d->length;
325 5551e51d 2006-07-23 devnull attr->blocks = (d->length+8191)/8192;
326 5551e51d 2006-07-23 devnull attr->atime = d->atime;
327 5551e51d 2006-07-23 devnull attr->mtime = d->mtime;
328 5551e51d 2006-07-23 devnull attr->ctime = d->mtime; /* not right */
329 5551e51d 2006-07-23 devnull attr->atimensec = 0;
330 5551e51d 2006-07-23 devnull attr->mtimensec = 0;
331 5551e51d 2006-07-23 devnull attr->ctimensec = 0;
332 5551e51d 2006-07-23 devnull attr->mode = d->mode&0777;
333 5551e51d 2006-07-23 devnull if(d->mode&DMDIR)
334 5551e51d 2006-07-23 devnull attr->mode |= S_IFDIR;
335 d07db89b 2008-07-04 rsc else if(d->mode&DMSYMLINK)
336 d07db89b 2008-07-04 rsc attr->mode |= S_IFLNK;
337 5551e51d 2006-07-23 devnull else
338 5551e51d 2006-07-23 devnull attr->mode |= S_IFREG;
339 5551e51d 2006-07-23 devnull attr->nlink = 1; /* works for directories! - see FUSE FAQ */
340 5551e51d 2006-07-23 devnull attr->uid = getuid();
341 5551e51d 2006-07-23 devnull attr->gid = getgid();
342 5551e51d 2006-07-23 devnull attr->rdev = 0;
343 5551e51d 2006-07-23 devnull }
344 5551e51d 2006-07-23 devnull
345 5551e51d 2006-07-23 devnull void
346 5551e51d 2006-07-23 devnull f2timeout(double f, __u64 *s, __u32 *ns)
347 5551e51d 2006-07-23 devnull {
348 5551e51d 2006-07-23 devnull *s = f;
349 5551e51d 2006-07-23 devnull *ns = (f - (int)f)*1e9;
350 5551e51d 2006-07-23 devnull }
351 5551e51d 2006-07-23 devnull
352 5551e51d 2006-07-23 devnull void
353 5551e51d 2006-07-23 devnull dir2attrout(Dir *d, struct fuse_attr_out *out)
354 5551e51d 2006-07-23 devnull {
355 5551e51d 2006-07-23 devnull f2timeout(attrtimeout, &out->attr_valid, &out->attr_valid_nsec);
356 5551e51d 2006-07-23 devnull dir2attr(d, &out->attr);
357 5551e51d 2006-07-23 devnull }
358 5551e51d 2006-07-23 devnull
359 5551e51d 2006-07-23 devnull /*
360 5551e51d 2006-07-23 devnull * Lookup. Walk to the name given as the argument.
361 5551e51d 2006-07-23 devnull * The response is a fuse_entry_out giving full stat info.
362 5551e51d 2006-07-23 devnull */
363 5551e51d 2006-07-23 devnull void
364 5551e51d 2006-07-23 devnull fuselookup(FuseMsg *m)
365 5551e51d 2006-07-23 devnull {
366 5551e51d 2006-07-23 devnull char *name;
367 5551e51d 2006-07-23 devnull Fusefid *ff;
368 5551e51d 2006-07-23 devnull CFid *fid, *newfid;
369 5551e51d 2006-07-23 devnull Dir *d;
370 5551e51d 2006-07-23 devnull struct fuse_entry_out out;
371 fa325e9b 2020-01-10 cross
372 5551e51d 2006-07-23 devnull name = m->tx;
373 5551e51d 2006-07-23 devnull if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
374 5551e51d 2006-07-23 devnull replyfuseerrno(m, ESTALE);
375 5551e51d 2006-07-23 devnull return;
376 5551e51d 2006-07-23 devnull }
377 5551e51d 2006-07-23 devnull if(strchr(name, '/')){
378 5551e51d 2006-07-23 devnull replyfuseerrno(m, ENOENT);
379 5551e51d 2006-07-23 devnull return;
380 5551e51d 2006-07-23 devnull }
381 5551e51d 2006-07-23 devnull if((newfid = fswalk(fid, name)) == nil){
382 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
383 5551e51d 2006-07-23 devnull return;
384 5551e51d 2006-07-23 devnull }
385 5551e51d 2006-07-23 devnull if((d = fsdirfstat(newfid)) == nil){
386 5551e51d 2006-07-23 devnull fsclose(newfid);
387 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
388 5551e51d 2006-07-23 devnull return;
389 5551e51d 2006-07-23 devnull }
390 5551e51d 2006-07-23 devnull out.nodeid = allocnodeid(newfid);
391 5551e51d 2006-07-23 devnull ff = lookupfusefid(out.nodeid, 1);
392 5551e51d 2006-07-23 devnull out.generation = ff->gen;
393 5551e51d 2006-07-23 devnull f2timeout(attrtimeout, &out.attr_valid, &out.attr_valid_nsec);
394 5551e51d 2006-07-23 devnull f2timeout(entrytimeout, &out.entry_valid, &out.entry_valid_nsec);
395 5551e51d 2006-07-23 devnull dir2attr(d, &out.attr);
396 5551e51d 2006-07-23 devnull free(d);
397 5551e51d 2006-07-23 devnull replyfuse(m, &out, sizeof out);
398 5551e51d 2006-07-23 devnull }
399 5551e51d 2006-07-23 devnull
400 5551e51d 2006-07-23 devnull /*
401 5551e51d 2006-07-23 devnull * Forget. Reference-counted clunk for nodeids.
402 5551e51d 2006-07-23 devnull * Does not send a reply.
403 fa325e9b 2020-01-10 cross * Each lookup response gives the kernel an additional reference
404 5551e51d 2006-07-23 devnull * to the returned nodeid. Forget says "drop this many references
405 5551e51d 2006-07-23 devnull * to this nodeid". Our fuselookup, when presented with the same query,
406 5551e51d 2006-07-23 devnull * does not return the same results (it allocates a new nodeid for each
407 5551e51d 2006-07-23 devnull * call), but if that ever changes, fuseforget already handles the ref
408 5551e51d 2006-07-23 devnull * counts properly.
409 5551e51d 2006-07-23 devnull */
410 5551e51d 2006-07-23 devnull void
411 5551e51d 2006-07-23 devnull fuseforget(FuseMsg *m)
412 5551e51d 2006-07-23 devnull {
413 5551e51d 2006-07-23 devnull struct fuse_forget_in *in;
414 5551e51d 2006-07-23 devnull Fusefid *ff;
415 5551e51d 2006-07-23 devnull
416 5551e51d 2006-07-23 devnull in = m->tx;
417 5551e51d 2006-07-23 devnull if((ff = lookupfusefid(m->hdr->nodeid, 1)) == nil)
418 5551e51d 2006-07-23 devnull return;
419 5551e51d 2006-07-23 devnull if(ff->ref > in->nlookup){
420 5551e51d 2006-07-23 devnull ff->ref -= in->nlookup;
421 5551e51d 2006-07-23 devnull return;
422 5551e51d 2006-07-23 devnull }
423 5551e51d 2006-07-23 devnull if(ff->ref < in->nlookup)
424 5551e51d 2006-07-23 devnull fprint(2, "bad count in forget\n");
425 5551e51d 2006-07-23 devnull ff->ref = 1;
426 5551e51d 2006-07-23 devnull freefusefid(ff);
427 d4ccb0a9 2012-09-11 rsc freefusemsg(m);
428 5551e51d 2006-07-23 devnull }
429 5551e51d 2006-07-23 devnull
430 5551e51d 2006-07-23 devnull /*
431 5551e51d 2006-07-23 devnull * Getattr.
432 5551e51d 2006-07-23 devnull * Replies with a fuse_attr_out structure giving the
433 5551e51d 2006-07-23 devnull * attr for the requested nodeid in out.attr.
434 fa325e9b 2020-01-10 cross * Out.attr_valid and out.attr_valid_nsec give
435 5551e51d 2006-07-23 devnull * the amount of time that the attributes can
436 5551e51d 2006-07-23 devnull * be cached.
437 5551e51d 2006-07-23 devnull *
438 5551e51d 2006-07-23 devnull * Empirically, though, if I run ls -ld on the root
439 5551e51d 2006-07-23 devnull * twice back to back, I still get two getattrs,
440 5551e51d 2006-07-23 devnull * even with a one second attribute timeout!
441 5551e51d 2006-07-23 devnull */
442 5551e51d 2006-07-23 devnull void
443 5551e51d 2006-07-23 devnull fusegetattr(FuseMsg *m)
444 5551e51d 2006-07-23 devnull {
445 5551e51d 2006-07-23 devnull CFid *fid;
446 5551e51d 2006-07-23 devnull struct fuse_attr_out out;
447 5551e51d 2006-07-23 devnull Dir *d;
448 5551e51d 2006-07-23 devnull
449 5551e51d 2006-07-23 devnull if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
450 5551e51d 2006-07-23 devnull replyfuseerrno(m, ESTALE);
451 5551e51d 2006-07-23 devnull return;
452 5551e51d 2006-07-23 devnull }
453 5551e51d 2006-07-23 devnull if((d = fsdirfstat(fid)) == nil){
454 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
455 5551e51d 2006-07-23 devnull return;
456 5551e51d 2006-07-23 devnull }
457 5551e51d 2006-07-23 devnull memset(&out, 0, sizeof out);
458 5551e51d 2006-07-23 devnull dir2attrout(d, &out);
459 5551e51d 2006-07-23 devnull free(d);
460 5551e51d 2006-07-23 devnull replyfuse(m, &out, sizeof out);
461 5551e51d 2006-07-23 devnull }
462 5551e51d 2006-07-23 devnull
463 5551e51d 2006-07-23 devnull /*
464 5551e51d 2006-07-23 devnull * Setattr.
465 5551e51d 2006-07-23 devnull * FUSE treats the many Unix attribute setting routines
466 5551e51d 2006-07-23 devnull * more or less like 9P does, with a single message.
467 5551e51d 2006-07-23 devnull */
468 5551e51d 2006-07-23 devnull void
469 5551e51d 2006-07-23 devnull fusesetattr(FuseMsg *m)
470 5551e51d 2006-07-23 devnull {
471 5551e51d 2006-07-23 devnull CFid *fid, *nfid;
472 5551e51d 2006-07-23 devnull Dir d, *dd;
473 5551e51d 2006-07-23 devnull struct fuse_setattr_in *in;
474 5551e51d 2006-07-23 devnull struct fuse_attr_out out;
475 5551e51d 2006-07-23 devnull
476 5551e51d 2006-07-23 devnull in = m->tx;
477 5551e51d 2006-07-23 devnull if(in->valid&FATTR_FH){
478 5551e51d 2006-07-23 devnull if((fid = fh2fid(in->fh)) == nil){
479 5551e51d 2006-07-23 devnull replyfuseerrno(m, ESTALE);
480 5551e51d 2006-07-23 devnull return;
481 5551e51d 2006-07-23 devnull }
482 5551e51d 2006-07-23 devnull }else{
483 5551e51d 2006-07-23 devnull if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
484 5551e51d 2006-07-23 devnull replyfuseerrno(m, ESTALE);
485 5551e51d 2006-07-23 devnull return;
486 5551e51d 2006-07-23 devnull }
487 5551e51d 2006-07-23 devnull /*
488 5551e51d 2006-07-23 devnull * Special case: Linux issues a size change to
489 5551e51d 2006-07-23 devnull * truncate a file before opening it OTRUNC.
490 fa325e9b 2020-01-10 cross * Synthetic file servers (e.g., plumber) honor
491 5551e51d 2006-07-23 devnull * open(OTRUNC) but not wstat.
492 5551e51d 2006-07-23 devnull */
493 5551e51d 2006-07-23 devnull if(in->valid == FATTR_SIZE && in->size == 0){
494 5551e51d 2006-07-23 devnull if((nfid = fswalk(fid, nil)) == nil){
495 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
496 5551e51d 2006-07-23 devnull return;
497 5551e51d 2006-07-23 devnull }
498 5551e51d 2006-07-23 devnull if(fsfopen(nfid, OWRITE|OTRUNC) < 0){
499 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
500 5551e51d 2006-07-23 devnull fsclose(nfid);
501 a695bc7d 2006-07-23 devnull return;
502 5551e51d 2006-07-23 devnull }
503 5551e51d 2006-07-23 devnull fsclose(nfid);
504 5551e51d 2006-07-23 devnull goto stat;
505 5551e51d 2006-07-23 devnull }
506 5551e51d 2006-07-23 devnull }
507 5551e51d 2006-07-23 devnull
508 5551e51d 2006-07-23 devnull nulldir(&d);
509 5551e51d 2006-07-23 devnull if(in->valid&FATTR_SIZE)
510 5551e51d 2006-07-23 devnull d.length = in->size;
511 5551e51d 2006-07-23 devnull if(in->valid&FATTR_ATIME)
512 5551e51d 2006-07-23 devnull d.atime = in->atime;
513 5551e51d 2006-07-23 devnull if(in->valid&FATTR_MTIME)
514 5551e51d 2006-07-23 devnull d.mtime = in->mtime;
515 5551e51d 2006-07-23 devnull if(in->valid&FATTR_MODE)
516 4798a8a5 2018-02-05 0intro d.mode = in->mode & 0777;
517 4798a8a5 2018-02-05 0intro if((in->mode&S_IFMT) == S_IFDIR)
518 4798a8a5 2018-02-05 0intro d.mode |= DMDIR;
519 5551e51d 2006-07-23 devnull if((in->valid&FATTR_UID) || (in->valid&FATTR_GID)){
520 5551e51d 2006-07-23 devnull /*
521 5551e51d 2006-07-23 devnull * I can't be bothered with these yet.
522 5551e51d 2006-07-23 devnull */
523 5551e51d 2006-07-23 devnull replyfuseerrno(m, EPERM);
524 5551e51d 2006-07-23 devnull return;
525 5551e51d 2006-07-23 devnull }
526 5551e51d 2006-07-23 devnull if(fsdirfwstat(fid, &d) < 0){
527 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
528 5551e51d 2006-07-23 devnull return;
529 5551e51d 2006-07-23 devnull }
530 5551e51d 2006-07-23 devnull stat:
531 5551e51d 2006-07-23 devnull if((dd = fsdirfstat(fid)) == nil){
532 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
533 5551e51d 2006-07-23 devnull return;
534 5551e51d 2006-07-23 devnull }
535 5551e51d 2006-07-23 devnull memset(&out, 0, sizeof out);
536 5551e51d 2006-07-23 devnull dir2attrout(dd, &out);
537 5551e51d 2006-07-23 devnull free(dd);
538 5551e51d 2006-07-23 devnull replyfuse(m, &out, sizeof out);
539 5551e51d 2006-07-23 devnull }
540 5551e51d 2006-07-23 devnull
541 5551e51d 2006-07-23 devnull CFid*
542 5551e51d 2006-07-23 devnull _fuseopenfid(uvlong nodeid, int isdir, int openmode, int *err)
543 5551e51d 2006-07-23 devnull {
544 5551e51d 2006-07-23 devnull CFid *fid, *newfid;
545 5551e51d 2006-07-23 devnull
546 5551e51d 2006-07-23 devnull if((fid = nodeid2fid(nodeid)) == nil){
547 5551e51d 2006-07-23 devnull *err = ESTALE;
548 5551e51d 2006-07-23 devnull return nil;
549 5551e51d 2006-07-23 devnull }
550 5551e51d 2006-07-23 devnull if(isdir && !(fsqid(fid).type&QTDIR)){
551 5551e51d 2006-07-23 devnull *err = ENOTDIR;
552 5551e51d 2006-07-23 devnull return nil;
553 5551e51d 2006-07-23 devnull }
554 5551e51d 2006-07-23 devnull if(openmode != OREAD && fsqid(fid).type&QTDIR){
555 5551e51d 2006-07-23 devnull *err = EISDIR;
556 5551e51d 2006-07-23 devnull return nil;
557 5551e51d 2006-07-23 devnull }
558 5551e51d 2006-07-23 devnull
559 5551e51d 2006-07-23 devnull /* Clone fid to get one we can open. */
560 5551e51d 2006-07-23 devnull newfid = fswalk(fid, nil);
561 5551e51d 2006-07-23 devnull if(newfid == nil){
562 5551e51d 2006-07-23 devnull *err = errstr2errno();
563 5551e51d 2006-07-23 devnull return nil;
564 5551e51d 2006-07-23 devnull }
565 fa325e9b 2020-01-10 cross
566 5551e51d 2006-07-23 devnull if(fsfopen(newfid, openmode) < 0){
567 5551e51d 2006-07-23 devnull *err = errstr2errno();
568 5551e51d 2006-07-23 devnull fsclose(newfid);
569 5551e51d 2006-07-23 devnull return nil;
570 5551e51d 2006-07-23 devnull }
571 5551e51d 2006-07-23 devnull
572 5551e51d 2006-07-23 devnull return newfid;
573 5551e51d 2006-07-23 devnull }
574 5551e51d 2006-07-23 devnull
575 5551e51d 2006-07-23 devnull /*
576 5551e51d 2006-07-23 devnull * Open & Opendir.
577 5551e51d 2006-07-23 devnull * Argument is a struct fuse_open_in.
578 5551e51d 2006-07-23 devnull * The mode field is ignored (presumably permission bits)
579 5551e51d 2006-07-23 devnull * and flags is the open mode.
580 5551e51d 2006-07-23 devnull * Replies with a struct fuse_open_out.
581 5551e51d 2006-07-23 devnull */
582 5551e51d 2006-07-23 devnull void
583 5551e51d 2006-07-23 devnull _fuseopen(FuseMsg *m, int isdir)
584 5551e51d 2006-07-23 devnull {
585 5551e51d 2006-07-23 devnull struct fuse_open_in *in;
586 5551e51d 2006-07-23 devnull struct fuse_open_out out;
587 5551e51d 2006-07-23 devnull CFid *fid;
588 5551e51d 2006-07-23 devnull int openmode, flags, err;
589 5551e51d 2006-07-23 devnull
590 5551e51d 2006-07-23 devnull in = m->tx;
591 5551e51d 2006-07-23 devnull flags = in->flags;
592 5551e51d 2006-07-23 devnull openmode = flags&3;
593 5551e51d 2006-07-23 devnull flags &= ~3;
594 93f9789c 2020-01-13 rsc flags &= ~(O_DIRECTORY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC|FMODE_EXEC);
595 281ca361 2011-10-05 rsc #ifdef O_NOFOLLOW
596 f9c8cdb5 2011-10-07 rsc flags &= ~O_NOFOLLOW;
597 281ca361 2011-10-05 rsc #endif
598 281ca361 2011-10-05 rsc #ifdef O_LARGEFILE
599 f9c8cdb5 2011-10-07 rsc flags &= ~O_LARGEFILE;
600 281ca361 2011-10-05 rsc #endif
601 281ca361 2011-10-05 rsc
602 e465991e 2008-12-30 rsc /*
603 e465991e 2008-12-30 rsc * Discarding O_APPEND here is not completely wrong,
604 e465991e 2008-12-30 rsc * because the host kernel will rewrite the offsets
605 e465991e 2008-12-30 rsc * of write system calls for us. That's the best we
606 e465991e 2008-12-30 rsc * can do on Unix anyway.
607 e465991e 2008-12-30 rsc */
608 e465991e 2008-12-30 rsc flags &= ~O_APPEND;
609 0d7fd011 2006-07-23 devnull if(flags & O_TRUNC){
610 0d7fd011 2006-07-23 devnull openmode |= OTRUNC;
611 0d7fd011 2006-07-23 devnull flags &= ~O_TRUNC;
612 0d7fd011 2006-07-23 devnull }
613 93f9789c 2020-01-13 rsc
614 0d7fd011 2006-07-23 devnull /*
615 0d7fd011 2006-07-23 devnull * Could translate but not standard 9P:
616 0d7fd011 2006-07-23 devnull * O_DIRECT -> ODIRECT
617 0d7fd011 2006-07-23 devnull * O_NONBLOCK -> ONONBLOCK
618 0d7fd011 2006-07-23 devnull */
619 5551e51d 2006-07-23 devnull if(flags){
620 93f9789c 2020-01-13 rsc fprint(2, "unexpected open flags requested=%#uo unhandled=%#uo\n", (uint)in->flags, (uint)flags);
621 5551e51d 2006-07-23 devnull replyfuseerrno(m, EACCES);
622 5551e51d 2006-07-23 devnull return;
623 5551e51d 2006-07-23 devnull }
624 5551e51d 2006-07-23 devnull if((fid = _fuseopenfid(m->hdr->nodeid, isdir, openmode, &err)) == nil){
625 5551e51d 2006-07-23 devnull replyfuseerrno(m, err);
626 5551e51d 2006-07-23 devnull return;
627 5551e51d 2006-07-23 devnull }
628 5551e51d 2006-07-23 devnull out.fh = allocfh(fid);
629 fa325e9b 2020-01-10 cross out.open_flags = FOPEN_DIRECT_IO; /* no page cache */
630 5551e51d 2006-07-23 devnull replyfuse(m, &out, sizeof out);
631 5551e51d 2006-07-23 devnull }
632 5551e51d 2006-07-23 devnull
633 5551e51d 2006-07-23 devnull void
634 5551e51d 2006-07-23 devnull fuseopen(FuseMsg *m)
635 5551e51d 2006-07-23 devnull {
636 5551e51d 2006-07-23 devnull _fuseopen(m, 0);
637 5551e51d 2006-07-23 devnull }
638 5551e51d 2006-07-23 devnull
639 5551e51d 2006-07-23 devnull void
640 5551e51d 2006-07-23 devnull fuseopendir(FuseMsg *m)
641 5551e51d 2006-07-23 devnull {
642 5551e51d 2006-07-23 devnull _fuseopen(m, 1);
643 5551e51d 2006-07-23 devnull }
644 5551e51d 2006-07-23 devnull
645 5551e51d 2006-07-23 devnull /*
646 5551e51d 2006-07-23 devnull * Create & Mkdir.
647 5551e51d 2006-07-23 devnull */
648 5551e51d 2006-07-23 devnull CFid*
649 5551e51d 2006-07-23 devnull _fusecreate(uvlong nodeid, char *name, int perm, int ismkdir, int omode, struct fuse_entry_out *out, int *err)
650 5551e51d 2006-07-23 devnull {
651 5551e51d 2006-07-23 devnull CFid *fid, *newfid, *newfid2;
652 5551e51d 2006-07-23 devnull Dir *d;
653 5551e51d 2006-07-23 devnull Fusefid *ff;
654 5551e51d 2006-07-23 devnull
655 5551e51d 2006-07-23 devnull if((fid = nodeid2fid(nodeid)) == nil){
656 5551e51d 2006-07-23 devnull *err = ESTALE;
657 5551e51d 2006-07-23 devnull return nil;
658 5551e51d 2006-07-23 devnull }
659 5551e51d 2006-07-23 devnull perm &= 0777;
660 5551e51d 2006-07-23 devnull if(ismkdir)
661 5551e51d 2006-07-23 devnull perm |= DMDIR;
662 5551e51d 2006-07-23 devnull if(ismkdir && omode != OREAD){
663 5551e51d 2006-07-23 devnull *err = EPERM;
664 5551e51d 2006-07-23 devnull return nil;
665 5551e51d 2006-07-23 devnull }
666 5551e51d 2006-07-23 devnull if((newfid = fswalk(fid, nil)) == nil){
667 5551e51d 2006-07-23 devnull *err = errstr2errno();
668 5551e51d 2006-07-23 devnull return nil;
669 5551e51d 2006-07-23 devnull }
670 e54f9a4a 2007-05-09 devnull if(fsfcreate(newfid, name, omode, perm) < 0){
671 5551e51d 2006-07-23 devnull *err = errstr2errno();
672 5551e51d 2006-07-23 devnull fsclose(newfid);
673 5551e51d 2006-07-23 devnull return nil;
674 5551e51d 2006-07-23 devnull }
675 5551e51d 2006-07-23 devnull if((d = fsdirfstat(newfid)) == nil){
676 5551e51d 2006-07-23 devnull *err = errstr2errno();
677 5551e51d 2006-07-23 devnull fsfremove(newfid);
678 5551e51d 2006-07-23 devnull return nil;
679 5551e51d 2006-07-23 devnull }
680 5551e51d 2006-07-23 devnull /*
681 5551e51d 2006-07-23 devnull * This fid is no good, because it's open.
682 5551e51d 2006-07-23 devnull * We need an unopened fid. Sigh.
683 5551e51d 2006-07-23 devnull */
684 5551e51d 2006-07-23 devnull if((newfid2 = fswalk(fid, name)) == nil){
685 5551e51d 2006-07-23 devnull *err = errstr2errno();
686 5551e51d 2006-07-23 devnull free(d);
687 5551e51d 2006-07-23 devnull fsfremove(newfid);
688 5551e51d 2006-07-23 devnull return nil;
689 5551e51d 2006-07-23 devnull }
690 5551e51d 2006-07-23 devnull out->nodeid = allocnodeid(newfid2);
691 5551e51d 2006-07-23 devnull ff = lookupfusefid(out->nodeid, 1);
692 5551e51d 2006-07-23 devnull out->generation = ff->gen;
693 5551e51d 2006-07-23 devnull f2timeout(attrtimeout, &out->attr_valid, &out->attr_valid_nsec);
694 5551e51d 2006-07-23 devnull f2timeout(entrytimeout, &out->entry_valid, &out->entry_valid_nsec);
695 5551e51d 2006-07-23 devnull dir2attr(d, &out->attr);
696 5551e51d 2006-07-23 devnull free(d);
697 5551e51d 2006-07-23 devnull return newfid;
698 5551e51d 2006-07-23 devnull }
699 5551e51d 2006-07-23 devnull
700 5551e51d 2006-07-23 devnull void
701 5551e51d 2006-07-23 devnull fusemkdir(FuseMsg *m)
702 5551e51d 2006-07-23 devnull {
703 5551e51d 2006-07-23 devnull struct fuse_mkdir_in *in;
704 5551e51d 2006-07-23 devnull struct fuse_entry_out out;
705 5551e51d 2006-07-23 devnull CFid *fid;
706 5551e51d 2006-07-23 devnull int err;
707 5551e51d 2006-07-23 devnull char *name;
708 fa325e9b 2020-01-10 cross
709 5551e51d 2006-07-23 devnull in = m->tx;
710 5551e51d 2006-07-23 devnull name = (char*)(in+1);
711 5551e51d 2006-07-23 devnull if((fid = _fusecreate(m->hdr->nodeid, name, in->mode, 1, OREAD, &out, &err)) == nil){
712 5551e51d 2006-07-23 devnull replyfuseerrno(m, err);
713 5551e51d 2006-07-23 devnull return;
714 5551e51d 2006-07-23 devnull }
715 5551e51d 2006-07-23 devnull /* Toss the open fid. */
716 5551e51d 2006-07-23 devnull fsclose(fid);
717 5551e51d 2006-07-23 devnull replyfuse(m, &out, sizeof out);
718 5551e51d 2006-07-23 devnull }
719 5551e51d 2006-07-23 devnull
720 5551e51d 2006-07-23 devnull void
721 5551e51d 2006-07-23 devnull fusecreate(FuseMsg *m)
722 5551e51d 2006-07-23 devnull {
723 5551e51d 2006-07-23 devnull struct fuse_open_in *in;
724 5551e51d 2006-07-23 devnull struct fuse_create_out out;
725 5551e51d 2006-07-23 devnull CFid *fid;
726 5551e51d 2006-07-23 devnull int err, openmode, flags;
727 5551e51d 2006-07-23 devnull char *name;
728 fa325e9b 2020-01-10 cross
729 5551e51d 2006-07-23 devnull in = m->tx;
730 5551e51d 2006-07-23 devnull flags = in->flags;
731 5551e51d 2006-07-23 devnull openmode = in->flags&3;
732 d7158243 2007-05-09 devnull flags &= ~3;
733 e10a8342 2009-04-30 rsc flags &= ~(O_DIRECTORY|O_NONBLOCK|O_LARGEFILE|O_EXCL);
734 e465991e 2008-12-30 rsc flags &= ~O_APPEND; /* see comment in _fuseopen */
735 d7158243 2007-05-09 devnull flags &= ~(O_CREAT|O_TRUNC); /* huh? */
736 5551e51d 2006-07-23 devnull if(flags){
737 5551e51d 2006-07-23 devnull fprint(2, "bad mode %#uo\n", in->flags);
738 5551e51d 2006-07-23 devnull replyfuseerrno(m, EACCES);
739 5551e51d 2006-07-23 devnull return;
740 5551e51d 2006-07-23 devnull }
741 5551e51d 2006-07-23 devnull name = (char*)(in+1);
742 5551e51d 2006-07-23 devnull if((fid = _fusecreate(m->hdr->nodeid, name, in->mode, 0, openmode, &out.e, &err)) == nil){
743 5551e51d 2006-07-23 devnull replyfuseerrno(m, err);
744 5551e51d 2006-07-23 devnull return;
745 5551e51d 2006-07-23 devnull }
746 5551e51d 2006-07-23 devnull out.o.fh = allocfh(fid);
747 5551e51d 2006-07-23 devnull out.o.open_flags = FOPEN_DIRECT_IO; /* no page cache */
748 5551e51d 2006-07-23 devnull replyfuse(m, &out, sizeof out);
749 5551e51d 2006-07-23 devnull }
750 5551e51d 2006-07-23 devnull
751 5551e51d 2006-07-23 devnull /*
752 fa325e9b 2020-01-10 cross * Access.
753 5551e51d 2006-07-23 devnull * Lib9pclient implements this just as Plan 9 does,
754 5551e51d 2006-07-23 devnull * by opening the file (or not) and then closing it.
755 5551e51d 2006-07-23 devnull */
756 5551e51d 2006-07-23 devnull void
757 5551e51d 2006-07-23 devnull fuseaccess(FuseMsg *m)
758 5551e51d 2006-07-23 devnull {
759 5551e51d 2006-07-23 devnull struct fuse_access_in *in;
760 5551e51d 2006-07-23 devnull CFid *fid;
761 143cdf57 2006-07-26 devnull int err, omode;
762 5551e51d 2006-07-23 devnull static int a2o[] = {
763 5551e51d 2006-07-23 devnull 0,
764 5551e51d 2006-07-23 devnull OEXEC,
765 5551e51d 2006-07-23 devnull OWRITE,
766 5551e51d 2006-07-23 devnull ORDWR,
767 5551e51d 2006-07-23 devnull OREAD,
768 5551e51d 2006-07-23 devnull OEXEC,
769 5551e51d 2006-07-23 devnull ORDWR,
770 5551e51d 2006-07-23 devnull ORDWR
771 5551e51d 2006-07-23 devnull };
772 fa325e9b 2020-01-10 cross
773 5551e51d 2006-07-23 devnull in = m->tx;
774 5551e51d 2006-07-23 devnull if(in->mask >= nelem(a2o)){
775 5551e51d 2006-07-23 devnull replyfuseerrno(m, EINVAL);
776 5551e51d 2006-07-23 devnull return;
777 5551e51d 2006-07-23 devnull }
778 143cdf57 2006-07-26 devnull omode = a2o[in->mask];
779 143cdf57 2006-07-26 devnull if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
780 143cdf57 2006-07-26 devnull replyfuseerrno(m, ESTALE);
781 143cdf57 2006-07-26 devnull return;
782 143cdf57 2006-07-26 devnull }
783 143cdf57 2006-07-26 devnull if(fsqid(fid).type&QTDIR)
784 143cdf57 2006-07-26 devnull omode = OREAD;
785 143cdf57 2006-07-26 devnull if((fid = _fuseopenfid(m->hdr->nodeid, 0, omode, &err)) == nil){
786 5551e51d 2006-07-23 devnull replyfuseerrno(m, err);
787 5551e51d 2006-07-23 devnull return;
788 5551e51d 2006-07-23 devnull }
789 5551e51d 2006-07-23 devnull fsclose(fid);
790 5551e51d 2006-07-23 devnull replyfuse(m, nil, 0);
791 5551e51d 2006-07-23 devnull }
792 5551e51d 2006-07-23 devnull
793 5551e51d 2006-07-23 devnull /*
794 5551e51d 2006-07-23 devnull * Release.
795 5551e51d 2006-07-23 devnull * Equivalent of clunk for file handles.
796 5551e51d 2006-07-23 devnull * in->flags is the open mode used in Open or Opendir.
797 5551e51d 2006-07-23 devnull */
798 5551e51d 2006-07-23 devnull void
799 5551e51d 2006-07-23 devnull fuserelease(FuseMsg *m)
800 5551e51d 2006-07-23 devnull {
801 5551e51d 2006-07-23 devnull struct fuse_release_in *in;
802 5551e51d 2006-07-23 devnull Fusefid *ff;
803 fa325e9b 2020-01-10 cross
804 5551e51d 2006-07-23 devnull in = m->tx;
805 5551e51d 2006-07-23 devnull if((ff = lookupfusefid(in->fh, 0)) != nil)
806 5551e51d 2006-07-23 devnull freefusefid(ff);
807 5551e51d 2006-07-23 devnull else
808 5551e51d 2006-07-23 devnull fprint(2, "fuserelease: fh not found\n");
809 5551e51d 2006-07-23 devnull replyfuse(m, nil, 0);
810 5551e51d 2006-07-23 devnull }
811 5551e51d 2006-07-23 devnull
812 5551e51d 2006-07-23 devnull void
813 5551e51d 2006-07-23 devnull fusereleasedir(FuseMsg *m)
814 5551e51d 2006-07-23 devnull {
815 5551e51d 2006-07-23 devnull fuserelease(m);
816 5551e51d 2006-07-23 devnull }
817 5551e51d 2006-07-23 devnull
818 5551e51d 2006-07-23 devnull /*
819 5551e51d 2006-07-23 devnull * Read.
820 5551e51d 2006-07-23 devnull * Read from file handle in->fh at offset in->offset for size in->size.
821 5551e51d 2006-07-23 devnull * We truncate size to maxwrite just to keep the buffer reasonable.
822 5551e51d 2006-07-23 devnull */
823 5551e51d 2006-07-23 devnull void
824 5551e51d 2006-07-23 devnull fuseread(FuseMsg *m)
825 5551e51d 2006-07-23 devnull {
826 5551e51d 2006-07-23 devnull int n;
827 5551e51d 2006-07-23 devnull uchar *buf;
828 5551e51d 2006-07-23 devnull CFid *fid;
829 5551e51d 2006-07-23 devnull struct fuse_read_in *in;
830 5551e51d 2006-07-23 devnull
831 5551e51d 2006-07-23 devnull in = m->tx;
832 5551e51d 2006-07-23 devnull if((fid = fh2fid(in->fh)) == nil){
833 5551e51d 2006-07-23 devnull replyfuseerrno(m, ESTALE);
834 5551e51d 2006-07-23 devnull return;
835 5551e51d 2006-07-23 devnull }
836 5551e51d 2006-07-23 devnull n = in->size;
837 5551e51d 2006-07-23 devnull if(n > fusemaxwrite)
838 5551e51d 2006-07-23 devnull n = fusemaxwrite;
839 5551e51d 2006-07-23 devnull buf = emalloc(n);
840 cd2bb6ce 2007-05-04 devnull n = fspread(fid, buf, n, in->offset);
841 5551e51d 2006-07-23 devnull if(n < 0){
842 5551e51d 2006-07-23 devnull free(buf);
843 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
844 3c8afaf2 2008-05-06 rsc return;
845 5551e51d 2006-07-23 devnull }
846 5551e51d 2006-07-23 devnull replyfuse(m, buf, n);
847 5551e51d 2006-07-23 devnull free(buf);
848 5551e51d 2006-07-23 devnull }
849 d07db89b 2008-07-04 rsc
850 d07db89b 2008-07-04 rsc /*
851 d07db89b 2008-07-04 rsc * Readlink.
852 d07db89b 2008-07-04 rsc */
853 d07db89b 2008-07-04 rsc void
854 d07db89b 2008-07-04 rsc fusereadlink(FuseMsg *m)
855 d07db89b 2008-07-04 rsc {
856 d07db89b 2008-07-04 rsc Dir *d;
857 d07db89b 2008-07-04 rsc CFid *fid;
858 5551e51d 2006-07-23 devnull
859 d07db89b 2008-07-04 rsc if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
860 d07db89b 2008-07-04 rsc replyfuseerrno(m, ESTALE);
861 d07db89b 2008-07-04 rsc return;
862 d07db89b 2008-07-04 rsc }
863 d07db89b 2008-07-04 rsc if((d = fsdirfstat(fid)) == nil){
864 d07db89b 2008-07-04 rsc replyfuseerrstr(m);
865 d07db89b 2008-07-04 rsc return;
866 d07db89b 2008-07-04 rsc }
867 d07db89b 2008-07-04 rsc if(!(d->mode&DMSYMLINK)){
868 d07db89b 2008-07-04 rsc replyfuseerrno(m, EINVAL);
869 d07db89b 2008-07-04 rsc return;
870 d07db89b 2008-07-04 rsc }
871 d07db89b 2008-07-04 rsc replyfuse(m, d->ext, strlen(d->ext));
872 d07db89b 2008-07-04 rsc free(d);
873 d07db89b 2008-07-04 rsc return;
874 d07db89b 2008-07-04 rsc }
875 d07db89b 2008-07-04 rsc
876 fa325e9b 2020-01-10 cross /*
877 5551e51d 2006-07-23 devnull * Readdir.
878 5551e51d 2006-07-23 devnull * Read from file handle in->fh at offset in->offset for size in->size.
879 5551e51d 2006-07-23 devnull * We truncate size to maxwrite just to keep the buffer reasonable.
880 5551e51d 2006-07-23 devnull * We assume 9P directory read semantics: a read at offset 0 rewinds
881 5551e51d 2006-07-23 devnull * and a read at any other offset starts where we left off.
882 5551e51d 2006-07-23 devnull * If it became necessary, we could implement a crude seek
883 5551e51d 2006-07-23 devnull * or cache the entire list of directory entries.
884 5551e51d 2006-07-23 devnull * Directory entries read from 9P but not yet handed to FUSE
885 5551e51d 2006-07-23 devnull * are stored in m->d,nd,d0.
886 5551e51d 2006-07-23 devnull */
887 5551e51d 2006-07-23 devnull int canpack(Dir*, uvlong, uchar**, uchar*);
888 fa588406 2020-01-13 rsc Dir *dotdir(CFid*);
889 5551e51d 2006-07-23 devnull void
890 5551e51d 2006-07-23 devnull fusereaddir(FuseMsg *m)
891 5551e51d 2006-07-23 devnull {
892 5551e51d 2006-07-23 devnull struct fuse_read_in *in;
893 5551e51d 2006-07-23 devnull uchar *buf, *p, *ep;
894 5551e51d 2006-07-23 devnull int n;
895 5551e51d 2006-07-23 devnull Fusefid *ff;
896 fa325e9b 2020-01-10 cross
897 5551e51d 2006-07-23 devnull in = m->tx;
898 5551e51d 2006-07-23 devnull if((ff = lookupfusefid(in->fh, 0)) == nil){
899 5551e51d 2006-07-23 devnull replyfuseerrno(m, ESTALE);
900 5551e51d 2006-07-23 devnull return;
901 fa325e9b 2020-01-10 cross }
902 5551e51d 2006-07-23 devnull if(in->offset == 0){
903 5551e51d 2006-07-23 devnull fsseek(ff->fid, 0, 0);
904 5551e51d 2006-07-23 devnull free(ff->d0);
905 fa588406 2020-01-13 rsc ff->d0 = ff->d = dotdir(ff->fid);
906 fa588406 2020-01-13 rsc ff->nd = 1;
907 5551e51d 2006-07-23 devnull }
908 5551e51d 2006-07-23 devnull n = in->size;
909 5551e51d 2006-07-23 devnull if(n > fusemaxwrite)
910 5551e51d 2006-07-23 devnull n = fusemaxwrite;
911 5551e51d 2006-07-23 devnull buf = emalloc(n);
912 5551e51d 2006-07-23 devnull p = buf;
913 5551e51d 2006-07-23 devnull ep = buf + n;
914 5551e51d 2006-07-23 devnull for(;;){
915 ca6a2d95 2006-08-01 devnull while(ff->nd > 0){
916 ca6a2d95 2006-08-01 devnull if(!canpack(ff->d, ff->off, &p, ep))
917 ca6a2d95 2006-08-01 devnull goto out;
918 5551e51d 2006-07-23 devnull ff->off++;
919 5551e51d 2006-07-23 devnull ff->d++;
920 5551e51d 2006-07-23 devnull ff->nd--;
921 5551e51d 2006-07-23 devnull }
922 ca6a2d95 2006-08-01 devnull free(ff->d0);
923 ca6a2d95 2006-08-01 devnull ff->d0 = nil;
924 ca6a2d95 2006-08-01 devnull ff->d = nil;
925 ca6a2d95 2006-08-01 devnull if((ff->nd = fsdirread(ff->fid, &ff->d0)) < 0){
926 ca6a2d95 2006-08-01 devnull replyfuseerrstr(m);
927 ca6a2d95 2006-08-01 devnull free(buf);
928 ca6a2d95 2006-08-01 devnull return;
929 ca6a2d95 2006-08-01 devnull }
930 ca6a2d95 2006-08-01 devnull if(ff->nd == 0)
931 ca6a2d95 2006-08-01 devnull break;
932 ca6a2d95 2006-08-01 devnull ff->d = ff->d0;
933 ca6a2d95 2006-08-01 devnull }
934 fa325e9b 2020-01-10 cross out:
935 5551e51d 2006-07-23 devnull replyfuse(m, buf, p - buf);
936 5551e51d 2006-07-23 devnull free(buf);
937 5551e51d 2006-07-23 devnull }
938 5551e51d 2006-07-23 devnull
939 9ec57f8b 2008-07-04 rsc /*
940 9ec57f8b 2008-07-04 rsc * Fuse assumes that it can always read two directory entries.
941 9ec57f8b 2008-07-04 rsc * If it gets just one, it will double it in the dirread results.
942 9ec57f8b 2008-07-04 rsc * Thus if a directory contains just "a", you see "a" twice.
943 9ec57f8b 2008-07-04 rsc * Adding . as the first directory entry works around this.
944 9ec57f8b 2008-07-04 rsc * We could add .. too, but it isn't necessary.
945 9ec57f8b 2008-07-04 rsc */
946 9ec57f8b 2008-07-04 rsc Dir*
947 fa588406 2020-01-13 rsc dotdir(CFid *f)
948 9ec57f8b 2008-07-04 rsc {
949 9ec57f8b 2008-07-04 rsc Dir *d;
950 9ec57f8b 2008-07-04 rsc
951 fa588406 2020-01-13 rsc d = emalloc(1*sizeof *d);
952 9ec57f8b 2008-07-04 rsc d[0].name = ".";
953 9ec57f8b 2008-07-04 rsc d[0].qid = fsqid(f);
954 9ec57f8b 2008-07-04 rsc return d;
955 9ec57f8b 2008-07-04 rsc }
956 9ec57f8b 2008-07-04 rsc
957 5551e51d 2006-07-23 devnull int
958 5551e51d 2006-07-23 devnull canpack(Dir *d, uvlong off, uchar **pp, uchar *ep)
959 5551e51d 2006-07-23 devnull {
960 5551e51d 2006-07-23 devnull uchar *p;
961 5551e51d 2006-07-23 devnull struct fuse_dirent *de;
962 5551e51d 2006-07-23 devnull int pad, size;
963 fa325e9b 2020-01-10 cross
964 5551e51d 2006-07-23 devnull p = *pp;
965 5551e51d 2006-07-23 devnull size = FUSE_NAME_OFFSET + strlen(d->name);
966 5551e51d 2006-07-23 devnull pad = 0;
967 5551e51d 2006-07-23 devnull if(size%8)
968 5551e51d 2006-07-23 devnull pad = 8 - size%8;
969 5551e51d 2006-07-23 devnull if(size+pad > ep - p)
970 5551e51d 2006-07-23 devnull return 0;
971 5551e51d 2006-07-23 devnull de = (struct fuse_dirent*)p;
972 5551e51d 2006-07-23 devnull de->ino = qid2inode(d->qid);
973 5551e51d 2006-07-23 devnull de->off = off;
974 5551e51d 2006-07-23 devnull de->namelen = strlen(d->name);
975 5551e51d 2006-07-23 devnull memmove(de->name, d->name, de->namelen);
976 5551e51d 2006-07-23 devnull if(pad > 0)
977 5551e51d 2006-07-23 devnull memset(de->name+de->namelen, 0, pad);
978 5551e51d 2006-07-23 devnull *pp = p+size+pad;
979 5551e51d 2006-07-23 devnull return 1;
980 5551e51d 2006-07-23 devnull }
981 5551e51d 2006-07-23 devnull
982 5551e51d 2006-07-23 devnull /*
983 5551e51d 2006-07-23 devnull * Write.
984 5551e51d 2006-07-23 devnull * Write from file handle in->fh at offset in->offset for size in->size.
985 5551e51d 2006-07-23 devnull * Don't know what in->write_flags means.
986 fa325e9b 2020-01-10 cross *
987 5551e51d 2006-07-23 devnull * Apparently implementations are allowed to buffer these writes
988 5551e51d 2006-07-23 devnull * and wait until Flush is sent, but FUSE docs say flush may be
989 5551e51d 2006-07-23 devnull * called zero, one, or even more times per close. So better do the
990 5551e51d 2006-07-23 devnull * actual writing here. Also, errors that happen during Flush just
991 5551e51d 2006-07-23 devnull * show up in the close() return status, which no one checks anyway.
992 5551e51d 2006-07-23 devnull */
993 5551e51d 2006-07-23 devnull void
994 5551e51d 2006-07-23 devnull fusewrite(FuseMsg *m)
995 5551e51d 2006-07-23 devnull {
996 5551e51d 2006-07-23 devnull struct fuse_write_in *in;
997 5551e51d 2006-07-23 devnull struct fuse_write_out out;
998 5551e51d 2006-07-23 devnull void *a;
999 5551e51d 2006-07-23 devnull CFid *fid;
1000 5551e51d 2006-07-23 devnull int n;
1001 fa325e9b 2020-01-10 cross
1002 5551e51d 2006-07-23 devnull in = m->tx;
1003 5551e51d 2006-07-23 devnull a = in+1;
1004 5551e51d 2006-07-23 devnull if((fid = fh2fid(in->fh)) == nil){
1005 5551e51d 2006-07-23 devnull replyfuseerrno(m, ESTALE);
1006 5551e51d 2006-07-23 devnull return;
1007 5551e51d 2006-07-23 devnull }
1008 5551e51d 2006-07-23 devnull if(in->size > fusemaxwrite){
1009 5551e51d 2006-07-23 devnull replyfuseerrno(m, EINVAL);
1010 5551e51d 2006-07-23 devnull return;
1011 5551e51d 2006-07-23 devnull }
1012 cd2bb6ce 2007-05-04 devnull n = fspwrite(fid, a, in->size, in->offset);
1013 5551e51d 2006-07-23 devnull if(n < 0){
1014 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
1015 5551e51d 2006-07-23 devnull return;
1016 5551e51d 2006-07-23 devnull }
1017 5551e51d 2006-07-23 devnull out.size = n;
1018 5551e51d 2006-07-23 devnull replyfuse(m, &out, sizeof out);
1019 5551e51d 2006-07-23 devnull }
1020 5551e51d 2006-07-23 devnull
1021 5551e51d 2006-07-23 devnull /*
1022 5551e51d 2006-07-23 devnull * Flush. Supposed to flush any buffered writes. Don't use this.
1023 fa325e9b 2020-01-10 cross *
1024 5551e51d 2006-07-23 devnull * Flush is a total crock. It gets called on close() of a file descriptor
1025 5551e51d 2006-07-23 devnull * associated with this open file. Some open files have multiple file
1026 5551e51d 2006-07-23 devnull * descriptors and thus multiple closes of those file descriptors.
1027 5551e51d 2006-07-23 devnull * In those cases, Flush is called multiple times. Some open files
1028 5551e51d 2006-07-23 devnull * have file descriptors that are closed on process exit instead of
1029 5551e51d 2006-07-23 devnull * closed explicitly. For those files, Flush is never called.
1030 5551e51d 2006-07-23 devnull * Even more amusing, Flush gets called before close() of read-only
1031 5551e51d 2006-07-23 devnull * file descriptors too!
1032 fa325e9b 2020-01-10 cross *
1033 5551e51d 2006-07-23 devnull * This is just a bad idea.
1034 5551e51d 2006-07-23 devnull */
1035 5551e51d 2006-07-23 devnull void
1036 5551e51d 2006-07-23 devnull fuseflush(FuseMsg *m)
1037 5551e51d 2006-07-23 devnull {
1038 5551e51d 2006-07-23 devnull replyfuse(m, nil, 0);
1039 5551e51d 2006-07-23 devnull }
1040 5551e51d 2006-07-23 devnull
1041 5551e51d 2006-07-23 devnull /*
1042 5551e51d 2006-07-23 devnull * Unlink & Rmdir.
1043 5551e51d 2006-07-23 devnull */
1044 5551e51d 2006-07-23 devnull void
1045 5551e51d 2006-07-23 devnull _fuseremove(FuseMsg *m, int isdir)
1046 5551e51d 2006-07-23 devnull {
1047 5551e51d 2006-07-23 devnull char *name;
1048 5551e51d 2006-07-23 devnull CFid *fid, *newfid;
1049 fa325e9b 2020-01-10 cross
1050 5551e51d 2006-07-23 devnull name = m->tx;
1051 5551e51d 2006-07-23 devnull if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
1052 5551e51d 2006-07-23 devnull replyfuseerrno(m, ESTALE);
1053 5551e51d 2006-07-23 devnull return;
1054 5551e51d 2006-07-23 devnull }
1055 5551e51d 2006-07-23 devnull if(strchr(name, '/')){
1056 5551e51d 2006-07-23 devnull replyfuseerrno(m, ENOENT);
1057 5551e51d 2006-07-23 devnull return;
1058 5551e51d 2006-07-23 devnull }
1059 5551e51d 2006-07-23 devnull if((newfid = fswalk(fid, name)) == nil){
1060 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
1061 5551e51d 2006-07-23 devnull return;
1062 5551e51d 2006-07-23 devnull }
1063 5551e51d 2006-07-23 devnull if(isdir && !(fsqid(newfid).type&QTDIR)){
1064 5551e51d 2006-07-23 devnull replyfuseerrno(m, ENOTDIR);
1065 5551e51d 2006-07-23 devnull fsclose(newfid);
1066 5551e51d 2006-07-23 devnull return;
1067 5551e51d 2006-07-23 devnull }
1068 5551e51d 2006-07-23 devnull if(!isdir && (fsqid(newfid).type&QTDIR)){
1069 5551e51d 2006-07-23 devnull replyfuseerrno(m, EISDIR);
1070 5551e51d 2006-07-23 devnull fsclose(newfid);
1071 5551e51d 2006-07-23 devnull return;
1072 5551e51d 2006-07-23 devnull }
1073 5551e51d 2006-07-23 devnull if(fsfremove(newfid) < 0){
1074 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
1075 5551e51d 2006-07-23 devnull return;
1076 5551e51d 2006-07-23 devnull }
1077 5551e51d 2006-07-23 devnull replyfuse(m, nil, 0);
1078 5551e51d 2006-07-23 devnull }
1079 5551e51d 2006-07-23 devnull
1080 5551e51d 2006-07-23 devnull void
1081 5551e51d 2006-07-23 devnull fuseunlink(FuseMsg *m)
1082 5551e51d 2006-07-23 devnull {
1083 5551e51d 2006-07-23 devnull _fuseremove(m, 0);
1084 5551e51d 2006-07-23 devnull }
1085 5551e51d 2006-07-23 devnull
1086 5551e51d 2006-07-23 devnull void
1087 5551e51d 2006-07-23 devnull fusermdir(FuseMsg *m)
1088 5551e51d 2006-07-23 devnull {
1089 5551e51d 2006-07-23 devnull _fuseremove(m, 1);
1090 5551e51d 2006-07-23 devnull }
1091 5551e51d 2006-07-23 devnull
1092 5551e51d 2006-07-23 devnull /*
1093 5551e51d 2006-07-23 devnull * Rename.
1094 5551e51d 2006-07-23 devnull *
1095 5551e51d 2006-07-23 devnull * FUSE sends the nodeid for the source and destination
1096 5551e51d 2006-07-23 devnull * directory and then the before and after names as strings.
1097 5551e51d 2006-07-23 devnull * 9P can only do the rename if the source and destination
1098 5551e51d 2006-07-23 devnull * are the same. If the same nodeid is used for source and
1099 5551e51d 2006-07-23 devnull * destination, we're fine, but if FUSE gives us different nodeids
1100 5551e51d 2006-07-23 devnull * that happen to correspond to the same directory, we have
1101 5551e51d 2006-07-23 devnull * no way of figuring that out. Let's hope it doesn't happen too often.
1102 5551e51d 2006-07-23 devnull */
1103 5551e51d 2006-07-23 devnull void
1104 5551e51d 2006-07-23 devnull fuserename(FuseMsg *m)
1105 5551e51d 2006-07-23 devnull {
1106 5551e51d 2006-07-23 devnull struct fuse_rename_in *in;
1107 5551e51d 2006-07-23 devnull char *before, *after;
1108 5551e51d 2006-07-23 devnull CFid *fid, *newfid;
1109 5551e51d 2006-07-23 devnull Dir d;
1110 fa325e9b 2020-01-10 cross
1111 5551e51d 2006-07-23 devnull in = m->tx;
1112 5551e51d 2006-07-23 devnull if(in->newdir != m->hdr->nodeid){
1113 5551e51d 2006-07-23 devnull replyfuseerrno(m, EXDEV);
1114 5551e51d 2006-07-23 devnull return;
1115 5551e51d 2006-07-23 devnull }
1116 5551e51d 2006-07-23 devnull before = (char*)(in+1);
1117 5551e51d 2006-07-23 devnull after = before + strlen(before) + 1;
1118 5551e51d 2006-07-23 devnull if((fid = nodeid2fid(m->hdr->nodeid)) == nil){
1119 5551e51d 2006-07-23 devnull replyfuseerrno(m, ESTALE);
1120 5551e51d 2006-07-23 devnull return;
1121 5551e51d 2006-07-23 devnull }
1122 5551e51d 2006-07-23 devnull if(strchr(before, '/') || strchr(after, '/')){
1123 5551e51d 2006-07-23 devnull replyfuseerrno(m, ENOENT);
1124 5551e51d 2006-07-23 devnull return;
1125 5551e51d 2006-07-23 devnull }
1126 5551e51d 2006-07-23 devnull if((newfid = fswalk(fid, before)) == nil){
1127 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
1128 5551e51d 2006-07-23 devnull return;
1129 5551e51d 2006-07-23 devnull }
1130 5551e51d 2006-07-23 devnull nulldir(&d);
1131 5551e51d 2006-07-23 devnull d.name = after;
1132 5551e51d 2006-07-23 devnull if(fsdirfwstat(newfid, &d) < 0){
1133 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
1134 5551e51d 2006-07-23 devnull fsclose(newfid);
1135 5551e51d 2006-07-23 devnull return;
1136 5551e51d 2006-07-23 devnull }
1137 5551e51d 2006-07-23 devnull fsclose(newfid);
1138 5551e51d 2006-07-23 devnull replyfuse(m, nil, 0);
1139 5551e51d 2006-07-23 devnull }
1140 5551e51d 2006-07-23 devnull
1141 5551e51d 2006-07-23 devnull /*
1142 5551e51d 2006-07-23 devnull * Fsync. Commit file info to stable storage.
1143 5551e51d 2006-07-23 devnull * Not sure what in->fsync_flags are.
1144 5551e51d 2006-07-23 devnull */
1145 5551e51d 2006-07-23 devnull void
1146 5551e51d 2006-07-23 devnull fusefsync(FuseMsg *m)
1147 5551e51d 2006-07-23 devnull {
1148 5551e51d 2006-07-23 devnull struct fuse_fsync_in *in;
1149 5551e51d 2006-07-23 devnull CFid *fid;
1150 5551e51d 2006-07-23 devnull Dir d;
1151 fa325e9b 2020-01-10 cross
1152 5551e51d 2006-07-23 devnull in = m->tx;
1153 5551e51d 2006-07-23 devnull if((fid = fh2fid(in->fh)) == nil){
1154 5551e51d 2006-07-23 devnull replyfuseerrno(m, ESTALE);
1155 5551e51d 2006-07-23 devnull return;
1156 5551e51d 2006-07-23 devnull }
1157 5551e51d 2006-07-23 devnull nulldir(&d);
1158 5551e51d 2006-07-23 devnull if(fsdirfwstat(fid, &d) < 0){
1159 5551e51d 2006-07-23 devnull replyfuseerrstr(m);
1160 5551e51d 2006-07-23 devnull return;
1161 5551e51d 2006-07-23 devnull }
1162 5551e51d 2006-07-23 devnull replyfuse(m, nil, 0);
1163 5551e51d 2006-07-23 devnull }
1164 5551e51d 2006-07-23 devnull
1165 5551e51d 2006-07-23 devnull /*
1166 5551e51d 2006-07-23 devnull * Fsyncdir. Commit dir info to stable storage?
1167 5551e51d 2006-07-23 devnull */
1168 5551e51d 2006-07-23 devnull void
1169 5551e51d 2006-07-23 devnull fusefsyncdir(FuseMsg *m)
1170 5551e51d 2006-07-23 devnull {
1171 5551e51d 2006-07-23 devnull fusefsync(m);
1172 5551e51d 2006-07-23 devnull }
1173 5551e51d 2006-07-23 devnull
1174 5551e51d 2006-07-23 devnull /*
1175 5551e51d 2006-07-23 devnull * Statfs. Send back information about file system.
1176 5551e51d 2006-07-23 devnull * Not really worth implementing, except that if we
1177 5551e51d 2006-07-23 devnull * reply with ENOSYS, programs like df print messages like
1178 5551e51d 2006-07-23 devnull * df: `/tmp/z': Function not implemented
1179 5551e51d 2006-07-23 devnull * and that gets annoying. Returning all zeros excludes
1180 5551e51d 2006-07-23 devnull * us from df without appearing to cause any problems.
1181 5551e51d 2006-07-23 devnull */
1182 5551e51d 2006-07-23 devnull void
1183 5551e51d 2006-07-23 devnull fusestatfs(FuseMsg *m)
1184 5551e51d 2006-07-23 devnull {
1185 5551e51d 2006-07-23 devnull struct fuse_statfs_out out;
1186 fa325e9b 2020-01-10 cross
1187 5551e51d 2006-07-23 devnull memset(&out, 0, sizeof out);
1188 5551e51d 2006-07-23 devnull replyfuse(m, &out, sizeof out);
1189 5551e51d 2006-07-23 devnull }
1190 5551e51d 2006-07-23 devnull
1191 5551e51d 2006-07-23 devnull void (*fusehandlers[100])(FuseMsg*);
1192 5551e51d 2006-07-23 devnull
1193 5551e51d 2006-07-23 devnull struct {
1194 5551e51d 2006-07-23 devnull int op;
1195 5551e51d 2006-07-23 devnull void (*fn)(FuseMsg*);
1196 5551e51d 2006-07-23 devnull } fuselist[] = {
1197 5551e51d 2006-07-23 devnull { FUSE_LOOKUP, fuselookup },
1198 5551e51d 2006-07-23 devnull { FUSE_FORGET, fuseforget },
1199 5551e51d 2006-07-23 devnull { FUSE_GETATTR, fusegetattr },
1200 5551e51d 2006-07-23 devnull { FUSE_SETATTR, fusesetattr },
1201 5551e51d 2006-07-23 devnull /*
1202 d07db89b 2008-07-04 rsc * FUSE_SYMLINK, FUSE_MKNOD are unimplemented.
1203 5551e51d 2006-07-23 devnull */
1204 d07db89b 2008-07-04 rsc { FUSE_READLINK, fusereadlink },
1205 5551e51d 2006-07-23 devnull { FUSE_MKDIR, fusemkdir },
1206 5551e51d 2006-07-23 devnull { FUSE_UNLINK, fuseunlink },
1207 5551e51d 2006-07-23 devnull { FUSE_RMDIR, fusermdir },
1208 5551e51d 2006-07-23 devnull { FUSE_RENAME, fuserename },
1209 5551e51d 2006-07-23 devnull /*
1210 5551e51d 2006-07-23 devnull * FUSE_LINK is unimplemented.
1211 5551e51d 2006-07-23 devnull */
1212 5551e51d 2006-07-23 devnull { FUSE_OPEN, fuseopen },
1213 5551e51d 2006-07-23 devnull { FUSE_READ, fuseread },
1214 5551e51d 2006-07-23 devnull { FUSE_WRITE, fusewrite },
1215 5551e51d 2006-07-23 devnull { FUSE_STATFS, fusestatfs },
1216 5551e51d 2006-07-23 devnull { FUSE_RELEASE, fuserelease },
1217 5551e51d 2006-07-23 devnull { FUSE_FSYNC, fusefsync },
1218 5551e51d 2006-07-23 devnull /*
1219 5551e51d 2006-07-23 devnull * FUSE_SETXATTR, FUSE_GETXATTR, FUSE_LISTXATTR, and
1220 fa325e9b 2020-01-10 cross * FUSE_REMOVEXATTR are unimplemented.
1221 5551e51d 2006-07-23 devnull * FUSE will stop sending these requests after getting
1222 5551e51d 2006-07-23 devnull * an -ENOSYS reply (see dispatch below).
1223 5551e51d 2006-07-23 devnull */
1224 5551e51d 2006-07-23 devnull { FUSE_FLUSH, fuseflush },
1225 5551e51d 2006-07-23 devnull /*
1226 5551e51d 2006-07-23 devnull * FUSE_INIT is handled in initfuse and should not be seen again.
1227 5551e51d 2006-07-23 devnull */
1228 5551e51d 2006-07-23 devnull { FUSE_OPENDIR, fuseopendir },
1229 5551e51d 2006-07-23 devnull { FUSE_READDIR, fusereaddir },
1230 5551e51d 2006-07-23 devnull { FUSE_RELEASEDIR, fusereleasedir },
1231 5551e51d 2006-07-23 devnull { FUSE_FSYNCDIR, fusefsyncdir },
1232 5551e51d 2006-07-23 devnull { FUSE_ACCESS, fuseaccess },
1233 5551e51d 2006-07-23 devnull { FUSE_CREATE, fusecreate },
1234 5551e51d 2006-07-23 devnull };
1235 5551e51d 2006-07-23 devnull
1236 5551e51d 2006-07-23 devnull void
1237 5551e51d 2006-07-23 devnull fusethread(void *v)
1238 5551e51d 2006-07-23 devnull {
1239 5551e51d 2006-07-23 devnull FuseMsg *m;
1240 5551e51d 2006-07-23 devnull
1241 5551e51d 2006-07-23 devnull m = v;
1242 fa325e9b 2020-01-10 cross if((uint)m->hdr->opcode >= nelem(fusehandlers)
1243 5551e51d 2006-07-23 devnull || !fusehandlers[m->hdr->opcode]){
1244 5551e51d 2006-07-23 devnull replyfuseerrno(m, ENOSYS);
1245 5551e51d 2006-07-23 devnull return;
1246 5551e51d 2006-07-23 devnull }
1247 5551e51d 2006-07-23 devnull fusehandlers[m->hdr->opcode](m);
1248 5551e51d 2006-07-23 devnull }
1249 5551e51d 2006-07-23 devnull
1250 5551e51d 2006-07-23 devnull void
1251 5551e51d 2006-07-23 devnull fusedispatch(void *v)
1252 5551e51d 2006-07-23 devnull {
1253 5551e51d 2006-07-23 devnull int i;
1254 5551e51d 2006-07-23 devnull FuseMsg *m;
1255 5551e51d 2006-07-23 devnull
1256 5551e51d 2006-07-23 devnull eofkill9pclient = 1; /* threadexitsall on 9P eof */
1257 5551e51d 2006-07-23 devnull atexit(unmountatexit);
1258 5551e51d 2006-07-23 devnull
1259 5551e51d 2006-07-23 devnull recvp(fusechan); /* sync */
1260 5551e51d 2006-07-23 devnull
1261 5551e51d 2006-07-23 devnull for(i=0; i<nelem(fuselist); i++){
1262 5551e51d 2006-07-23 devnull if(fuselist[i].op >= nelem(fusehandlers))
1263 5551e51d 2006-07-23 devnull sysfatal("make fusehandlers bigger op=%d", fuselist[i].op);
1264 5551e51d 2006-07-23 devnull fusehandlers[fuselist[i].op] = fuselist[i].fn;
1265 5551e51d 2006-07-23 devnull }
1266 5551e51d 2006-07-23 devnull
1267 d4ccb0a9 2012-09-11 rsc while((m = recvp(fusechan)) != nil) {
1268 d4ccb0a9 2012-09-11 rsc switch(m->hdr->opcode) {
1269 d4ccb0a9 2012-09-11 rsc case FUSE_FORGET:
1270 d4ccb0a9 2012-09-11 rsc fusehandlers[m->hdr->opcode](m);
1271 d4ccb0a9 2012-09-11 rsc break;
1272 fa325e9b 2020-01-10 cross default:
1273 d4ccb0a9 2012-09-11 rsc threadcreate(fusethread, m, STACK);
1274 d4ccb0a9 2012-09-11 rsc }
1275 d4ccb0a9 2012-09-11 rsc }
1276 5551e51d 2006-07-23 devnull }
1277 5551e51d 2006-07-23 devnull
1278 5551e51d 2006-07-23 devnull void*
1279 5551e51d 2006-07-23 devnull emalloc(uint n)
1280 5551e51d 2006-07-23 devnull {
1281 5551e51d 2006-07-23 devnull void *p;
1282 5551e51d 2006-07-23 devnull
1283 5551e51d 2006-07-23 devnull p = malloc(n);
1284 5551e51d 2006-07-23 devnull if(p == nil)
1285 5551e51d 2006-07-23 devnull sysfatal("malloc(%d): %r", n);
1286 5551e51d 2006-07-23 devnull memset(p, 0, n);
1287 5551e51d 2006-07-23 devnull return p;
1288 5551e51d 2006-07-23 devnull }
1289 5551e51d 2006-07-23 devnull
1290 5551e51d 2006-07-23 devnull void*
1291 5551e51d 2006-07-23 devnull erealloc(void *p, uint n)
1292 5551e51d 2006-07-23 devnull {
1293 5551e51d 2006-07-23 devnull p = realloc(p, n);
1294 5551e51d 2006-07-23 devnull if(p == nil)
1295 5551e51d 2006-07-23 devnull sysfatal("realloc(..., %d): %r", n);
1296 5551e51d 2006-07-23 devnull return p;
1297 5551e51d 2006-07-23 devnull }
1298 5551e51d 2006-07-23 devnull
1299 5551e51d 2006-07-23 devnull char*
1300 5551e51d 2006-07-23 devnull estrdup(char *p)
1301 5551e51d 2006-07-23 devnull {
1302 5551e51d 2006-07-23 devnull char *pp;
1303 5551e51d 2006-07-23 devnull pp = strdup(p);
1304 5551e51d 2006-07-23 devnull if(pp == nil)
1305 5551e51d 2006-07-23 devnull sysfatal("strdup(%.20s): %r", p);
1306 5551e51d 2006-07-23 devnull return pp;
1307 5551e51d 2006-07-23 devnull }
1308 5551e51d 2006-07-23 devnull
1309 e63025d0 2008-04-17 rsc void
1310 e63025d0 2008-04-17 rsc watchfd(void *v)
1311 e63025d0 2008-04-17 rsc {
1312 e63025d0 2008-04-17 rsc int fd = (int)(uintptr)v;
1313 5551e51d 2006-07-23 devnull
1314 e63025d0 2008-04-17 rsc /* wait for exception (file closed) */
1315 e63025d0 2008-04-17 rsc fd_set set;
1316 e63025d0 2008-04-17 rsc FD_ZERO(&set);
1317 e63025d0 2008-04-17 rsc FD_SET(fd, &set);
1318 e63025d0 2008-04-17 rsc if(select(fd+1, NULL, NULL, &set, NULL) >= 0)
1319 e63025d0 2008-04-17 rsc threadexitsall(nil);
1320 e63025d0 2008-04-17 rsc return;
1321 e63025d0 2008-04-17 rsc }