diff options
Diffstat (limited to 'src/cmd/9pfuse/main.c')
-rw-r--r-- | src/cmd/9pfuse/main.c | 104 |
1 files changed, 53 insertions, 51 deletions
diff --git a/src/cmd/9pfuse/main.c b/src/cmd/9pfuse/main.c index a3662898..69d1ad75 100644 --- a/src/cmd/9pfuse/main.c +++ b/src/cmd/9pfuse/main.c @@ -14,7 +14,7 @@ * writing the 9P connection. Thus the many threads in the * request proc can do 9P interactions without blocking. */ - + #define _GNU_SOURCE 1 /* for O_DIRECTORY on Linux */ #include "a.h" @@ -51,6 +51,14 @@ # endif #endif +#ifndef FMODE_EXEC +# if defined(__linux__) +# define FMODE_EXEC 040 +# else +# define FMODE_EXEC 0 +# endif +#endif + int debug; char *argv0; char *aname = ""; @@ -165,16 +173,16 @@ init9p(char *addr, char *spec) /* * FUSE uses nodeids to refer to active "struct inodes" * (9P's unopened fids). FUSE uses fhs to refer to active - * "struct fuse_files" (9P's opened fids). The choice of + * "struct fuse_files" (9P's opened fids). The choice of * numbers is up to us except that nodeid 1 is the root directory. - * We use the same number space for both and call the + * We use the same number space for both and call the * bookkeeping structure a FuseFid. * - * FUSE requires nodeids to have associated generation - * numbers. If we reuse a nodeid, we have to bump the + * FUSE requires nodeids to have associated generation + * numbers. If we reuse a nodeid, we have to bump the * generation number to guarantee that the nodeid,gen * combination is never reused. - * + * * There are also inode numbers returned in directory reads * and file attributes, but these do NOT need to match the nodeids. * We use a combination of qid.path and qid.type as the inode @@ -192,7 +200,7 @@ struct Fusefid int id; int gen; int isnodeid; - + /* directory read state */ Dir *d0; Dir *d; @@ -208,7 +216,7 @@ Fusefid* allocfusefid(void) { Fusefid *f; - + if((f = freefusefidlist) == nil){ f = emalloc(sizeof *f); fusefid = erealloc(fusefid, (nfusefid+1)*sizeof *fusefid); @@ -247,7 +255,7 @@ uvlong _alloc(CFid *fid, int isnodeid) { Fusefid *ff; - + ff = allocfusefid(); ff->fid = fid; ff->isnodeid = isnodeid; @@ -283,7 +291,7 @@ CFid* _lookupcfid(uvlong id, int isnodeid) { Fusefid *ff; - + if((ff = lookupfusefid(id, isnodeid)) == nil) return nil; return ff->fid; @@ -360,7 +368,7 @@ fuselookup(FuseMsg *m) CFid *fid, *newfid; Dir *d; struct fuse_entry_out out; - + name = m->tx; if((fid = nodeid2fid(m->hdr->nodeid)) == nil){ replyfuseerrno(m, ESTALE); @@ -392,7 +400,7 @@ fuselookup(FuseMsg *m) /* * Forget. Reference-counted clunk for nodeids. * Does not send a reply. - * Each lookup response gives the kernel an additional reference + * Each lookup response gives the kernel an additional reference * to the returned nodeid. Forget says "drop this many references * to this nodeid". Our fuselookup, when presented with the same query, * does not return the same results (it allocates a new nodeid for each @@ -423,7 +431,7 @@ fuseforget(FuseMsg *m) * Getattr. * Replies with a fuse_attr_out structure giving the * attr for the requested nodeid in out.attr. - * Out.attr_valid and out.attr_valid_nsec give + * Out.attr_valid and out.attr_valid_nsec give * the amount of time that the attributes can * be cached. * @@ -479,7 +487,7 @@ fusesetattr(FuseMsg *m) /* * Special case: Linux issues a size change to * truncate a file before opening it OTRUNC. - * Synthetic file servers (e.g., plumber) honor + * Synthetic file servers (e.g., plumber) honor * open(OTRUNC) but not wstat. */ if(in->valid == FATTR_SIZE && in->size == 0){ @@ -554,7 +562,7 @@ _fuseopenfid(uvlong nodeid, int isdir, int openmode, int *err) *err = errstr2errno(); return nil; } - + if(fsfopen(newfid, openmode) < 0){ *err = errstr2errno(); fsclose(newfid); @@ -583,7 +591,7 @@ _fuseopen(FuseMsg *m, int isdir) flags = in->flags; openmode = flags&3; flags &= ~3; - flags &= ~(O_DIRECTORY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC); + flags &= ~(O_DIRECTORY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC|FMODE_EXEC); #ifdef O_NOFOLLOW flags &= ~O_NOFOLLOW; #endif @@ -602,13 +610,14 @@ _fuseopen(FuseMsg *m, int isdir) openmode |= OTRUNC; flags &= ~O_TRUNC; } + /* * Could translate but not standard 9P: * O_DIRECT -> ODIRECT * O_NONBLOCK -> ONONBLOCK */ if(flags){ - fprint(2, "unexpected open flags %#uo\n", (uint)in->flags); + fprint(2, "unexpected open flags requested=%#uo unhandled=%#uo\n", (uint)in->flags, (uint)flags); replyfuseerrno(m, EACCES); return; } @@ -617,7 +626,7 @@ _fuseopen(FuseMsg *m, int isdir) return; } out.fh = allocfh(fid); - out.open_flags = FOPEN_DIRECT_IO; /* no page cache */ + out.open_flags = FOPEN_DIRECT_IO; /* no page cache */ replyfuse(m, &out, sizeof out); } @@ -696,7 +705,7 @@ fusemkdir(FuseMsg *m) CFid *fid; int err; char *name; - + in = m->tx; name = (char*)(in+1); if((fid = _fusecreate(m->hdr->nodeid, name, in->mode, 1, OREAD, &out, &err)) == nil){ @@ -716,7 +725,7 @@ fusecreate(FuseMsg *m) CFid *fid; int err, openmode, flags; char *name; - + in = m->tx; flags = in->flags; openmode = in->flags&3; @@ -740,7 +749,7 @@ fusecreate(FuseMsg *m) } /* - * Access. + * Access. * Lib9pclient implements this just as Plan 9 does, * by opening the file (or not) and then closing it. */ @@ -760,7 +769,7 @@ fuseaccess(FuseMsg *m) ORDWR, ORDWR }; - + in = m->tx; if(in->mask >= nelem(a2o)){ replyfuseerrno(m, EINVAL); @@ -791,7 +800,7 @@ fuserelease(FuseMsg *m) { struct fuse_release_in *in; Fusefid *ff; - + in = m->tx; if((ff = lookupfusefid(in->fh, 0)) != nil) freefusefid(ff); @@ -864,7 +873,7 @@ fusereadlink(FuseMsg *m) return; } -/* +/* * Readdir. * Read from file handle in->fh at offset in->offset for size in->size. * We truncate size to maxwrite just to keep the buffer reasonable. @@ -876,7 +885,7 @@ fusereadlink(FuseMsg *m) * are stored in m->d,nd,d0. */ int canpack(Dir*, uvlong, uchar**, uchar*); -Dir *dotdirs(CFid*); +Dir *dotdir(CFid*); void fusereaddir(FuseMsg *m) { @@ -884,17 +893,17 @@ fusereaddir(FuseMsg *m) uchar *buf, *p, *ep; int n; Fusefid *ff; - + in = m->tx; if((ff = lookupfusefid(in->fh, 0)) == nil){ replyfuseerrno(m, ESTALE); return; - } + } if(in->offset == 0){ fsseek(ff->fid, 0, 0); free(ff->d0); - ff->d0 = ff->d = dotdirs(ff->fid); - ff->nd = 2; + ff->d0 = ff->d = dotdir(ff->fid); + ff->nd = 1; } n = in->size; if(n > fusemaxwrite) @@ -922,7 +931,7 @@ fusereaddir(FuseMsg *m) break; ff->d = ff->d0; } -out: +out: replyfuse(m, buf, p - buf); free(buf); } @@ -935,20 +944,13 @@ out: * We could add .. too, but it isn't necessary. */ Dir* -dotdirs(CFid *f) +dotdir(CFid *f) { Dir *d; - CFid *f1; - d = emalloc(2*sizeof *d); + d = emalloc(1*sizeof *d); d[0].name = "."; d[0].qid = fsqid(f); - d[1].name = ".."; - f1 = fswalk(f, ".."); - if(f1){ - d[1].qid = fsqid(f1); - fsclose(f1); - } return d; } @@ -958,7 +960,7 @@ canpack(Dir *d, uvlong off, uchar **pp, uchar *ep) uchar *p; struct fuse_dirent *de; int pad, size; - + p = *pp; size = FUSE_NAME_OFFSET + strlen(d->name); pad = 0; @@ -981,7 +983,7 @@ canpack(Dir *d, uvlong off, uchar **pp, uchar *ep) * Write. * Write from file handle in->fh at offset in->offset for size in->size. * Don't know what in->write_flags means. - * + * * Apparently implementations are allowed to buffer these writes * and wait until Flush is sent, but FUSE docs say flush may be * called zero, one, or even more times per close. So better do the @@ -996,7 +998,7 @@ fusewrite(FuseMsg *m) void *a; CFid *fid; int n; - + in = m->tx; a = in+1; if((fid = fh2fid(in->fh)) == nil){ @@ -1018,7 +1020,7 @@ fusewrite(FuseMsg *m) /* * Flush. Supposed to flush any buffered writes. Don't use this. - * + * * Flush is a total crock. It gets called on close() of a file descriptor * associated with this open file. Some open files have multiple file * descriptors and thus multiple closes of those file descriptors. @@ -1027,7 +1029,7 @@ fusewrite(FuseMsg *m) * closed explicitly. For those files, Flush is never called. * Even more amusing, Flush gets called before close() of read-only * file descriptors too! - * + * * This is just a bad idea. */ void @@ -1044,7 +1046,7 @@ _fuseremove(FuseMsg *m, int isdir) { char *name; CFid *fid, *newfid; - + name = m->tx; if((fid = nodeid2fid(m->hdr->nodeid)) == nil){ replyfuseerrno(m, ESTALE); @@ -1105,7 +1107,7 @@ fuserename(FuseMsg *m) char *before, *after; CFid *fid, *newfid; Dir d; - + in = m->tx; if(in->newdir != m->hdr->nodeid){ replyfuseerrno(m, EXDEV); @@ -1146,7 +1148,7 @@ fusefsync(FuseMsg *m) struct fuse_fsync_in *in; CFid *fid; Dir d; - + in = m->tx; if((fid = fh2fid(in->fh)) == nil){ replyfuseerrno(m, ESTALE); @@ -1181,7 +1183,7 @@ void fusestatfs(FuseMsg *m) { struct fuse_statfs_out out; - + memset(&out, 0, sizeof out); replyfuse(m, &out, sizeof out); } @@ -1215,7 +1217,7 @@ struct { { FUSE_FSYNC, fusefsync }, /* * FUSE_SETXATTR, FUSE_GETXATTR, FUSE_LISTXATTR, and - * FUSE_REMOVEXATTR are unimplemented. + * FUSE_REMOVEXATTR are unimplemented. * FUSE will stop sending these requests after getting * an -ENOSYS reply (see dispatch below). */ @@ -1237,7 +1239,7 @@ fusethread(void *v) FuseMsg *m; m = v; - if((uint)m->hdr->opcode >= nelem(fusehandlers) + if((uint)m->hdr->opcode >= nelem(fusehandlers) || !fusehandlers[m->hdr->opcode]){ replyfuseerrno(m, ENOSYS); return; @@ -1267,7 +1269,7 @@ fusedispatch(void *v) case FUSE_FORGET: fusehandlers[m->hdr->opcode](m); break; - default: + default: threadcreate(fusethread, m, STACK); } } |