A while ago I ran acme at home to edit files at work using the neat u9fs over ssh trick[1]. I was impressed with how well it worked, so I thought I'd try it the other way. But obviously, my work machine isn't running plan9 so I can't use exactly the same approach. Also, my username at home is different to my username at work. Wouldn't have expected this to give me trouble, but p9p doesn't appear provide any facility to attach as a different user. So, I modified the attach strategy to look for a USER environment variable before falling back on getuser(). I've attached the diff, hopefully I got everything. At this point all the connections work:
$ rm `namespace`/wren #wren is my home server $ srv sqweek.dnsdojo.org wren $ USER=sqweek /opt/plan9/src/cmd/o.9p -D ls wren/ <- Tversion tag 0 msize 8192 version '9P2000' -> Rversion tag 65535 msize 8192 version '9P2000' <- Tauth tag 0 afid 0 uname sqweek aname <nil> -> Rauth tag 0 qid (0000000000000001 0 A) <- Tversion tag 0 msize 8192 version '9P2000' -> Rversion tag 65535 msize 8192 version '9P2000' <- Tattach tag 0 fid 0 afid -1 uname sqweek aname -> Rattach tag 0 qid (0000000000000001 0 d) <snip> !adding key: role=speakfor proto=p9sk1 dom=sqweek.dnsdojo.org user: sqweek password: ! <snip> d-rwxr-xr-x M 0 root wheel 2048 Feb 3 23:01 etc d-r-xr-xr-x M 0 root wheel 512 Feb 7 15:14 kern d-rwxr-xr-x M 0 root wheel 512 Sep 4 2006 proc <snip> wren runs u9fs on netbsd, hence the root/wheel/etc. All is good, until I go to mount it using 9pfuse: $ USER=sqweek /opt/plan9/src/cmd/9pfuse/o.9pfuse -D `namespace`/wren $HOME/n/wren <- Tversion tag 0 msize 8192 version '9P2000' -> Rversion tag 65535 msize 8192 version '9P2000' <- Tattach tag 0 fid 0 afid -1 uname sqweek aname -> Rerror tag 0 ename fid unknown or out of range /opt/plan9/src/cmd/9pfuse/o.9pfuse: fsmount: fid unknown or out of range The thing that baffles me the most here (not that it takes much to baffle my rudimentry understanding of 9p) is that 9p and 9pfuse both send the exact same Tattach, 9p just precedes it with a Tauth and suddenly u9fs thinks fid 0 is valid. Isn't the client free to choose any fid it wants? The only reasonable suggestion I can come up with is that 9pfuse doesn't do auth, and u9fs gives a silly error. If I try with srv -a, subsequent attempts to access the socket using 9p or 9pfuse give "authentication failed": $ rm `namespace`/wren $ USER=sqweek /opt/plan9/src/cmd/o.srv -D -a sqweek.dnsdojo.org wren <- Tversion tag 65535 msize 8192 version '9P2000' -> Rversion tag 65535 msize 8192 version '9P2000' <- Tauth tag 1 afid 0 uname sqweek aname -> Rauth tag 1 qid (0000000000000001 0 A) <- Tread tag 1 fid 0 offset 0 count 4096 -> Rread tag 1 count 25 '[EMAIL PROTECTED]' <- Twrite tag 1 fid 0 offset 0 count 25 'p9sk1 sqweek.dnsdojo.org\0' -> Rwrite tag 1 count 25 <- Twrite tag 1 fid 0 offset 0 count 8 'eae63a67 1869ea20' -> Rwrite tag 1 count 8 <- Tread tag 1 fid 0 offset 0 count 141 -> Rread tag 1 count 141 '01737177 65656b00 00000000 00000000 00000000 00000000 00000000 00737177 65656b2e 646e7364 6f6a6f2e 6f726700 00000000 00000000 00000000 00000000' <- Twrite tag 1 fid 0 offset 0 count 85 '616d745f 42b7fd6d c7ff2799 fb85434e 147a35d6 ed1c60b6 172666fd 5dd47b3d dd1e45ef 90b11ebc cf207605 d7b5463d 55e0f6b4 75c11a40 1d2dac39 7fb09376' -> Rwrite tag 1 count 85 <- Tread tag 1 fid 0 offset 0 count 13 -> Rread tag 1 count 13 '7c5995b6 58424643 8a6135e2 00' $ USER=sqweek /opt/plan9/src/cmd/o.9p -D ls wren/ <- Tversion tag 0 msize 8192 version '9P2000' -> Rversion tag 65535 msize 8192 version '9P2000' <- Tauth tag 0 afid 0 uname sqweek aname <nil> -> Rerror tag 0 ename authentication not required <- Tattach tag 0 fid 0 afid -1 uname sqweek aname -> Rerror tag 0 ename authentication failed /opt/plan9/src/cmd/o.9p: mount: authentication failed $ USER=sqweek /opt/plan9/src/cmd/9pfuse/o.9pfuse -D `namespace`/wren $HOME/n/wren <- Tversion tag 0 msize 8192 version '9P2000' -> Rversion tag 65535 msize 8192 version '9P2000' <- Tattach tag 0 fid 0 afid -1 uname sqweek aname -> Rerror tag 0 ename authentication failed /opt/plan9/src/cmd/9pfuse/o.9pfuse: fsmount: authentication failed Finally, 9pfuse doesn't want to work in general. John Soros reported a similar problem[2] and on IRC it was discovered we're both running 64-bit linux, which may be related: $ 9pfuse `namespace`/plumb $HOME/n/:0.0/plumb $ cd $HOME/n/plumb $ ls unexpected open flags 0304000ls: .: Permission denied $ 9 ls unexpected open flags 0100000ls: .: Permission denied I'm not quite sure what GNU ls is adding into the mix, but 0100000 is the O_LARGEFILE flag, which ought to get filtered out in _fuseopen: /usr/local/plan9/src/cmd/9pfuse/main.c:564: flags &= ~(O_DIRECTORY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC); But for some reason isn't. It's certainly cpp related: $ 9c -E main.c |grep 'flags &=' flags &= ~3; flags &= ~(0200000|04000|0|02000000); flags &= ~01000; flags &= ~3; flags &= ~(0200000|04000|0); flags &= ~(0100|01000); And it turns out /usr/include/bits/fcntl.h #defines O_LARGEFILE to be 0 when __WORDSIZE == 64 (which I verified is the case). So 9pfuse looks fine, and the question becomes where the hell does ls pull 0100000 from... gdb nails it down to something in the fuse stack: 43 fd = open(name, umode); (gdb) print umode $5 = 0 (gdb) step unexpected open flags 0100000 44 if(fd >= 0){ (gdb) bt #0 p9open (name=0x4083cc ".", mode=<value optimized out>) at open.c:44 #1 0x0000000000401a0d in ls (s=0x4083cc ".", multi=0) at ls.c:109 #2 0x0000000000401cc5 in p9main (argc=0, argv=0x7fffd9eea508) at ls.c:78 #3 0x00000000004030f9 in main (argc=4228044, argv=0x0) at main.c:10 Assuming I can trust gdb anyway, which is not always the case *sigh*. Well, I don't have the fuse source handy so this adventure will have to end here. Apologies for blogging up 9fans, but I'd appreciate any answers to my 9p questions. -sqweek [1] http://cm.bell-labs.com/wiki/plan9/Tip_o'_the_day/index.html [2] http://lists.cse.psu.edu/archives/9fans/2007-December/056900.html
Index: src/cmd/9pserve.c =================================================================== RCS file: /cvs/plan9/src/cmd/9pserve.c,v retrieving revision 1.40 diff -u -r1.40 9pserve.c --- src/cmd/9pserve.c 12 Oct 2007 17:01:00 -0000 1.40 +++ src/cmd/9pserve.c 6 Feb 2008 03:47:36 -0000 @@ -427,7 +427,8 @@ } m->tx.afid = xafid; m->tx.aname = xaname; - m->tx.uname = getuser(); /* what srv.c used */ + if((m->tx.uname = getenv("USER")) == nil) + m->tx.uname = getuser(); /* what srv.c used */ repack(&m->tx, &m->tpkt, c->dotu); } break; Index: src/cmd/srv.c =================================================================== RCS file: /cvs/plan9/src/cmd/srv.c,v retrieving revision 1.6 diff -u -r1.6 srv.c --- src/cmd/srv.c 12 Oct 2007 17:01:09 -0000 1.6 +++ src/cmd/srv.c 6 Feb 2008 03:47:36 -0000 @@ -136,7 +136,8 @@ tx.type = Tauth; tx.tag = 1; tx.afid = afid; - tx.uname = getuser(); + if((tx.uname = getenv("USER")) == nil) + tx.uname = getuser(); tx.aname = aname; do9p(&tx, &rx); if(rx.type == Rerror){ Index: src/lib9pclient/fs.c =================================================================== RCS file: /cvs/plan9/src/lib9pclient/fs.c,v retrieving revision 1.10 diff -u -r1.10 fs.c --- src/lib9pclient/fs.c 23 Jul 2006 02:55:33 -0000 1.10 +++ src/lib9pclient/fs.c 6 Feb 2008 03:47:40 -0000 @@ -69,14 +69,17 @@ CFsys* fsmount(int fd, char *aname) { + char *uname; CFsys *fs; CFid *fid; + if((uname = getenv("USER")) == nil) + uname = getuser(); fs = fsinit(fd); if(fs == nil) return nil; - if((fid = fsattach(fs, nil, getuser(), aname)) == nil){ + if((fid = fsattach(fs, nil, uname, aname)) == nil){ _fsunmount(fs); return nil; } Index: src/lib9pclient/ns.c =================================================================== RCS file: /cvs/plan9/src/lib9pclient/ns.c,v retrieving revision 1.4 diff -u -r1.4 ns.c --- src/lib9pclient/ns.c 13 Jul 2005 10:50:44 -0000 1.4 +++ src/lib9pclient/ns.c 6 Feb 2008 03:47:40 -0000 @@ -38,13 +38,16 @@ CFsys* nsmount(char *name, char *aname) { + char *uname; CFsys *fs; CFid *fid; + if((uname = getenv("USER")) == nil) + uname = getuser(); fs = nsinit(name); if(fs == nil) return nil; - if((fid = fsattach(fs, nil, getuser(), aname)) == nil){ + if((fid = fsattach(fs, nil, uname, aname)) == nil){ _fsunmount(fs); return nil; } Index: src/libauth/fsamount.c =================================================================== RCS file: /cvs/plan9/src/libauth/fsamount.c,v retrieving revision 1.1 diff -u -r1.1 fsamount.c --- src/libauth/fsamount.c 11 Feb 2005 17:01:17 -0000 1.1 +++ src/libauth/fsamount.c 6 Feb 2008 03:47:40 -0000 @@ -8,20 +8,23 @@ CFsys* fsamount(int fd, char *aname) { + char *uname; CFid *afid, *fid; AuthInfo *ai; CFsys *fs; + if((uname = getenv("USER")) == nil) + uname = getuser(); fs = fsinit(fd); if(fs == nil) return nil; - if((afid = fsauth(fs, getuser(), aname)) == nil) + if((afid = fsauth(fs, uname, aname)) == nil) goto noauth; ai = fsauth_proxy(afid, amount_getkey, "proto=p9any role=client"); if(ai != nil) auth_freeAI(ai); noauth: - fid = fsattach(fs, afid, getuser(), aname); + fid = fsattach(fs, afid, uname, aname); fsclose(afid); if(fid == nil){ _fsunmount(fs); Index: src/libauth/nsamount.c =================================================================== RCS file: /cvs/plan9/src/libauth/nsamount.c,v retrieving revision 1.1 diff -u -r1.1 nsamount.c --- src/libauth/nsamount.c 11 Feb 2005 17:01:18 -0000 1.1 +++ src/libauth/nsamount.c 6 Feb 2008 03:47:40 -0000 @@ -8,20 +8,23 @@ CFsys* nsamount(char *name, char *aname) { + char *uname; CFid *afid, *fid; AuthInfo *ai; CFsys *fs; + if((uname = getenv("USER")) == nil) + uname = getuser(); fs = nsinit(name); if(fs == nil) return nil; - if((afid = fsauth(fs, getuser(), aname)) == nil) + if((afid = fsauth(fs, uname, aname)) == nil) goto noauth; ai = fsauth_proxy(afid, amount_getkey, "proto=p9any role=client"); if(ai != nil) auth_freeAI(ai); noauth: - fid = fsattach(fs, afid, getuser(), aname); + fid = fsattach(fs, afid, uname, aname); fsclose(afid); if(fid == nil){ _fsunmount(fs);