19a747e4fSDavid du Colombier #include "all.h" 29a747e4fSDavid du Colombier 39a747e4fSDavid du Colombier /* 49a747e4fSDavid du Colombier * Cf. /lib/rfc/rfc1094 59a747e4fSDavid du Colombier */ 69a747e4fSDavid du Colombier 79a747e4fSDavid du Colombier static int nfsnull(int, Rpccall*, Rpccall*); 89a747e4fSDavid du Colombier static int nfsgetattr(int, Rpccall*, Rpccall*); 99a747e4fSDavid du Colombier static int nfssetattr(int, Rpccall*, Rpccall*); 109a747e4fSDavid du Colombier static int nfsroot(int, Rpccall*, Rpccall*); 119a747e4fSDavid du Colombier static int nfslookup(int, Rpccall*, Rpccall*); 129a747e4fSDavid du Colombier static int nfsreadlink(int, Rpccall*, Rpccall*); 139a747e4fSDavid du Colombier static int nfsread(int, Rpccall*, Rpccall*); 149a747e4fSDavid du Colombier static int nfswritecache(int, Rpccall*, Rpccall*); 159a747e4fSDavid du Colombier static int nfswrite(int, Rpccall*, Rpccall*); 169a747e4fSDavid du Colombier static int nfscreate(int, Rpccall*, Rpccall*); 179a747e4fSDavid du Colombier static int nfsremove(int, Rpccall*, Rpccall*); 189a747e4fSDavid du Colombier static int nfsrename(int, Rpccall*, Rpccall*); 199a747e4fSDavid du Colombier static int nfslink(int, Rpccall*, Rpccall*); 209a747e4fSDavid du Colombier static int nfssymlink(int, Rpccall*, Rpccall*); 219a747e4fSDavid du Colombier static int nfsmkdir(int, Rpccall*, Rpccall*); 229a747e4fSDavid du Colombier static int nfsrmdir(int, Rpccall*, Rpccall*); 239a747e4fSDavid du Colombier static int nfsreaddir(int, Rpccall*, Rpccall*); 249a747e4fSDavid du Colombier static int nfsstatfs(int, Rpccall*, Rpccall*); 259a747e4fSDavid du Colombier 269a747e4fSDavid du Colombier Procmap nfsproc[] = { 279a747e4fSDavid du Colombier 0, nfsnull, /* void */ 289a747e4fSDavid du Colombier 1, nfsgetattr, /* Fhandle */ 299a747e4fSDavid du Colombier 2, nfssetattr, /* Fhandle, Sattr */ 309a747e4fSDavid du Colombier 3, nfsroot, /* void */ 319a747e4fSDavid du Colombier 4, nfslookup, /* Fhandle, String */ 329a747e4fSDavid du Colombier 5, nfsreadlink, /* Fhandle */ 339a747e4fSDavid du Colombier 6, nfsread, /* Fhandle, long, long, long */ 349a747e4fSDavid du Colombier 7, nfswritecache,/* void */ 359a747e4fSDavid du Colombier 8, nfswrite, /* Fhandle, long, long, long, String */ 369a747e4fSDavid du Colombier 9, nfscreate, /* Fhandle, String, Sattr */ 379a747e4fSDavid du Colombier 10, nfsremove, /* Fhandle, String */ 389a747e4fSDavid du Colombier 11, nfsrename, /* Fhandle, String, Fhandle, String */ 399a747e4fSDavid du Colombier 12, nfslink, /* Fhandle, Fhandle, String */ 409a747e4fSDavid du Colombier 13, nfssymlink, /* Fhandle, String, String, Sattr */ 419a747e4fSDavid du Colombier 14, nfsmkdir, /* Fhandle, String, Sattr */ 429a747e4fSDavid du Colombier 15, nfsrmdir, /* Fhandle, String */ 439a747e4fSDavid du Colombier 16, nfsreaddir, /* Fhandle, long, long */ 449a747e4fSDavid du Colombier 17, nfsstatfs, /* Fhandle */ 459a747e4fSDavid du Colombier 0, 0 469a747e4fSDavid du Colombier }; 479a747e4fSDavid du Colombier 489a747e4fSDavid du Colombier void nfsinit(int, char**); 499a747e4fSDavid du Colombier extern void mntinit(int, char**); 509a747e4fSDavid du Colombier extern Procmap mntproc[]; 519a747e4fSDavid du Colombier 529a747e4fSDavid du Colombier Progmap progmap[] = { 539a747e4fSDavid du Colombier 100005, 1, mntinit, mntproc, 549a747e4fSDavid du Colombier 100003, 2, nfsinit, nfsproc, 559a747e4fSDavid du Colombier 0, 0, 0, 569a747e4fSDavid du Colombier }; 579a747e4fSDavid du Colombier 589a747e4fSDavid du Colombier int myport = 2049; 599a747e4fSDavid du Colombier long nfstime; 609a747e4fSDavid du Colombier int conftime; 619a747e4fSDavid du Colombier 629a747e4fSDavid du Colombier void 639a747e4fSDavid du Colombier main(int argc, char *argv[]) 649a747e4fSDavid du Colombier { 659a747e4fSDavid du Colombier server(argc, argv, myport, progmap); 669a747e4fSDavid du Colombier } 679a747e4fSDavid du Colombier 689a747e4fSDavid du Colombier static void 699a747e4fSDavid du Colombier doalarm(void) 709a747e4fSDavid du Colombier { 719a747e4fSDavid du Colombier nfstime = time(0); 729a747e4fSDavid du Colombier mnttimer(nfstime); 736ab4d0ffSDavid du Colombier if(conftime+5*60 < nfstime){ 746ab4d0ffSDavid du Colombier conftime = nfstime; 759a747e4fSDavid du Colombier readunixidmaps(config); 769a747e4fSDavid du Colombier } 779a747e4fSDavid du Colombier } 789a747e4fSDavid du Colombier 799a747e4fSDavid du Colombier void 809a747e4fSDavid du Colombier nfsinit(int argc, char **argv) 819a747e4fSDavid du Colombier { 829a747e4fSDavid du Colombier USED(argc, argv); 839a747e4fSDavid du Colombier clog("nfs file server init\n"); 849a747e4fSDavid du Colombier rpcalarm = doalarm; 859a747e4fSDavid du Colombier nfstime = time(0); 869a747e4fSDavid du Colombier } 879a747e4fSDavid du Colombier 889a747e4fSDavid du Colombier static int 899a747e4fSDavid du Colombier nfsnull(int n, Rpccall *cmd, Rpccall *reply) 909a747e4fSDavid du Colombier { 919a747e4fSDavid du Colombier USED(n, reply); 929a747e4fSDavid du Colombier chat("nfsnull..."); 939a747e4fSDavid du Colombier showauth(&cmd->cred); 949a747e4fSDavid du Colombier chat("OK\n"); 959a747e4fSDavid du Colombier return 0; 969a747e4fSDavid du Colombier } 979a747e4fSDavid du Colombier 989a747e4fSDavid du Colombier static int 999a747e4fSDavid du Colombier nfsgetattr(int n, Rpccall *cmd, Rpccall *reply) 1009a747e4fSDavid du Colombier { 1019a747e4fSDavid du Colombier Xfid *xf; 1029a747e4fSDavid du Colombier Dir dir; 1039a747e4fSDavid du Colombier uchar *dataptr = reply->results; 1049a747e4fSDavid du Colombier 1059a747e4fSDavid du Colombier chat("getattr..."); 1069a747e4fSDavid du Colombier if(n != FHSIZE) 1079a747e4fSDavid du Colombier return garbage(reply, "bad count"); 1089a747e4fSDavid du Colombier xf = rpc2xfid(cmd, &dir); 1099a747e4fSDavid du Colombier if(xf == 0) 1109a747e4fSDavid du Colombier return error(reply, NFSERR_STALE); 1119a747e4fSDavid du Colombier chat("%s...", xf->xp->name); 1129a747e4fSDavid du Colombier PLONG(NFS_OK); 1139a747e4fSDavid du Colombier dataptr += dir2fattr(cmd->up, &dir, dataptr); 1149a747e4fSDavid du Colombier chat("OK\n"); 1159a747e4fSDavid du Colombier return dataptr - (uchar *)reply->results; 1169a747e4fSDavid du Colombier } 1179a747e4fSDavid du Colombier 1189a747e4fSDavid du Colombier static int 1199a747e4fSDavid du Colombier nfssetattr(int n, Rpccall *cmd, Rpccall *reply) 1209a747e4fSDavid du Colombier { 1219a747e4fSDavid du Colombier Xfid *xf; 1226ab4d0ffSDavid du Colombier Dir dir, nd; 1239a747e4fSDavid du Colombier Sattr sattr; 1249a747e4fSDavid du Colombier int r; 1259a747e4fSDavid du Colombier uchar *argptr = cmd->args; 1269a747e4fSDavid du Colombier uchar *dataptr = reply->results; 1279a747e4fSDavid du Colombier 1289a747e4fSDavid du Colombier chat("setattr..."); 1299a747e4fSDavid du Colombier if(n <= FHSIZE) 1309a747e4fSDavid du Colombier return garbage(reply, "count too small"); 1319a747e4fSDavid du Colombier xf = rpc2xfid(cmd, &dir); 1329a747e4fSDavid du Colombier argptr += FHSIZE; 1339a747e4fSDavid du Colombier argptr += convM2sattr(argptr, &sattr); 1349a747e4fSDavid du Colombier if(argptr != &((uchar *)cmd->args)[n]) 1359a747e4fSDavid du Colombier return garbage(reply, "bad count"); 1369a747e4fSDavid du Colombier chat("mode=0%lo,u=%ld,g=%ld,size=%ld,atime=%ld,mtime=%ld...", 1379a747e4fSDavid du Colombier sattr.mode, sattr.uid, sattr.gid, sattr.size, 1389a747e4fSDavid du Colombier sattr.atime, sattr.mtime); 1399a747e4fSDavid du Colombier if(xf == 0) 1409a747e4fSDavid du Colombier return error(reply, NFSERR_STALE); 1419a747e4fSDavid du Colombier if(sattr.uid != NOATTR || sattr.gid != NOATTR) 1429a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 1439a747e4fSDavid du Colombier if(sattr.size == 0){ 1449a747e4fSDavid du Colombier if(xf->xp->s != xf->xp->parent->s){ 1459a747e4fSDavid du Colombier if(xfauthremove(xf, cmd->user) < 0) 1469a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 1479a747e4fSDavid du Colombier }else if(dir.length && xfopen(xf, Trunc|Oread|Owrite) < 0) 1489a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 1499a747e4fSDavid du Colombier }else if(sattr.size != NOATTR) 1509a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 1519a747e4fSDavid du Colombier r = 0; 1526ab4d0ffSDavid du Colombier nulldir(&nd); 1539a747e4fSDavid du Colombier if(sattr.mode != NOATTR) 1546ab4d0ffSDavid du Colombier ++r, nd.mode = (dir.mode & ~0777) | (sattr.mode & 0777); 1559a747e4fSDavid du Colombier if(sattr.atime != NOATTR) 1566ab4d0ffSDavid du Colombier ++r, nd.atime = sattr.atime; 1579a747e4fSDavid du Colombier if(sattr.mtime != NOATTR) 1586ab4d0ffSDavid du Colombier ++r, nd.mtime = sattr.mtime; 1596ab4d0ffSDavid du Colombier chat("sattr.mode=%luo dir.mode=%luo nd.mode=%luo...", sattr.mode, dir.mode, nd.mode); 1609a747e4fSDavid du Colombier if(r){ 1616ab4d0ffSDavid du Colombier r = xfwstat(xf, &nd); 1629a747e4fSDavid du Colombier if(r < 0) 1639a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 1649a747e4fSDavid du Colombier } 1659a747e4fSDavid du Colombier if(xfstat(xf, &dir) < 0) 1669a747e4fSDavid du Colombier return error(reply, NFSERR_STALE); 1679a747e4fSDavid du Colombier PLONG(NFS_OK); 1689a747e4fSDavid du Colombier dataptr += dir2fattr(cmd->up, &dir, dataptr); 1699a747e4fSDavid du Colombier chat("OK\n"); 1709a747e4fSDavid du Colombier return dataptr - (uchar *)reply->results; 1719a747e4fSDavid du Colombier } 1729a747e4fSDavid du Colombier 1739a747e4fSDavid du Colombier static int 1749a747e4fSDavid du Colombier nfsroot(int n, Rpccall *cmd, Rpccall *reply) 1759a747e4fSDavid du Colombier { 1769a747e4fSDavid du Colombier USED(n, reply); 1779a747e4fSDavid du Colombier chat("nfsroot..."); 1789a747e4fSDavid du Colombier showauth(&cmd->cred); 1799a747e4fSDavid du Colombier chat("OK\n"); 1809a747e4fSDavid du Colombier return 0; 1819a747e4fSDavid du Colombier } 1829a747e4fSDavid du Colombier 1839a747e4fSDavid du Colombier static int 1849a747e4fSDavid du Colombier nfslookup(int n, Rpccall *cmd, Rpccall *reply) 1859a747e4fSDavid du Colombier { 1869a747e4fSDavid du Colombier Xfile *xp; 1879a747e4fSDavid du Colombier Xfid *xf, *newxf; 1889a747e4fSDavid du Colombier String elem; 1899a747e4fSDavid du Colombier Dir dir; 1909a747e4fSDavid du Colombier uchar *argptr = cmd->args; 1919a747e4fSDavid du Colombier uchar *dataptr = reply->results; 1929a747e4fSDavid du Colombier 1939a747e4fSDavid du Colombier chat("lookup..."); 1949a747e4fSDavid du Colombier if(n <= FHSIZE) 1959a747e4fSDavid du Colombier return garbage(reply, "count too small"); 1969a747e4fSDavid du Colombier xf = rpc2xfid(cmd, 0); 1979a747e4fSDavid du Colombier argptr += FHSIZE; 1989a747e4fSDavid du Colombier argptr += string2S(argptr, &elem); 1999a747e4fSDavid du Colombier if(argptr != &((uchar *)cmd->args)[n]) 2009a747e4fSDavid du Colombier return garbage(reply, "bad count"); 2019a747e4fSDavid du Colombier if(xf == 0) 2029a747e4fSDavid du Colombier return error(reply, NFSERR_STALE); 2039a747e4fSDavid du Colombier xp = xf->xp; 2049a747e4fSDavid du Colombier if(!(xp->qid.type & QTDIR)) 2059a747e4fSDavid du Colombier return error(reply, NFSERR_NOTDIR); 2069a747e4fSDavid du Colombier chat("%s -> \"%.*s\"...", xp->name, utfnlen(elem.s, elem.n), elem.s); 2079a747e4fSDavid du Colombier if(xp->s->noauth == 0 && xp->parent == xp && elem.s[0] == '#') 2089a747e4fSDavid du Colombier newxf = xfauth(xp, &elem); 2099a747e4fSDavid du Colombier else 2109a747e4fSDavid du Colombier newxf = xfwalkcr(Twalk, xf, &elem, 0); 2119a747e4fSDavid du Colombier if(newxf == 0) 2129a747e4fSDavid du Colombier return error(reply, NFSERR_NOENT); 2139a747e4fSDavid du Colombier if(xfstat(newxf, &dir) < 0) 2149a747e4fSDavid du Colombier return error(reply, NFSERR_IO); 2159a747e4fSDavid du Colombier PLONG(NFS_OK); 2169a747e4fSDavid du Colombier dataptr += xp2fhandle(newxf->xp, dataptr); 2179a747e4fSDavid du Colombier dataptr += dir2fattr(cmd->up, &dir, dataptr); 2189a747e4fSDavid du Colombier chat("OK\n"); 2199a747e4fSDavid du Colombier return dataptr - (uchar *)reply->results; 2209a747e4fSDavid du Colombier } 2219a747e4fSDavid du Colombier 2229a747e4fSDavid du Colombier static int 2239a747e4fSDavid du Colombier nfsreadlink(int n, Rpccall *cmd, Rpccall *reply) 2249a747e4fSDavid du Colombier { 2259a747e4fSDavid du Colombier USED(n, reply); 2269a747e4fSDavid du Colombier chat("readlink..."); 2279a747e4fSDavid du Colombier showauth(&cmd->cred); 2289a747e4fSDavid du Colombier return error(reply, NFSERR_NOENT); 2299a747e4fSDavid du Colombier } 2309a747e4fSDavid du Colombier 2319a747e4fSDavid du Colombier static int 2329a747e4fSDavid du Colombier nfsread(int n, Rpccall *cmd, Rpccall *reply) 2339a747e4fSDavid du Colombier { 2349a747e4fSDavid du Colombier Session *s; 2359a747e4fSDavid du Colombier Xfid *xf; 2369a747e4fSDavid du Colombier Dir dir; 2379a747e4fSDavid du Colombier int offset, count; 2389a747e4fSDavid du Colombier uchar *argptr = cmd->args; 2399a747e4fSDavid du Colombier uchar *dataptr = reply->results; 2409a747e4fSDavid du Colombier uchar *readptr = dataptr + 4 + 17*4 + 4; 2419a747e4fSDavid du Colombier 2429a747e4fSDavid du Colombier chat("read..."); 2439a747e4fSDavid du Colombier if(n != FHSIZE+12) 2449a747e4fSDavid du Colombier return garbage(reply, "bad count"); 2459a747e4fSDavid du Colombier xf = rpc2xfid(cmd, 0); 2469a747e4fSDavid du Colombier argptr += FHSIZE; 2479a747e4fSDavid du Colombier offset = GLONG(); 2489a747e4fSDavid du Colombier count = GLONG(); 2499a747e4fSDavid du Colombier if(xf == 0) 2509a747e4fSDavid du Colombier return error(reply, NFSERR_STALE); 2519a747e4fSDavid du Colombier chat("%s %d %d...", xf->xp->name, offset, count); 2529a747e4fSDavid du Colombier if(xf->xp->s != xf->xp->parent->s){ 2539a747e4fSDavid du Colombier count = xfauthread(xf, offset, readptr, count); 2549a747e4fSDavid du Colombier }else{ 2559a747e4fSDavid du Colombier if(xfopen(xf, Oread) < 0) 2569a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 2579a747e4fSDavid du Colombier if(count > 8192) 2589a747e4fSDavid du Colombier count = 8192; 2599a747e4fSDavid du Colombier s = xf->xp->s; 2609a747e4fSDavid du Colombier setfid(s, xf->opfid); 2619a747e4fSDavid du Colombier xf->opfid->tstale = nfstime + 60; 2629a747e4fSDavid du Colombier s->f.offset = offset; 2639a747e4fSDavid du Colombier s->f.count = count; 2649a747e4fSDavid du Colombier if(xmesg(s, Tread) < 0) 2659a747e4fSDavid du Colombier return error(reply, NFSERR_IO); 2669a747e4fSDavid du Colombier count = s->f.count; 2679a747e4fSDavid du Colombier memmove(readptr, s->f.data, count); 2689a747e4fSDavid du Colombier } 2699a747e4fSDavid du Colombier if(xfstat(xf, &dir) < 0) 2709a747e4fSDavid du Colombier return error(reply, NFSERR_IO); 2719a747e4fSDavid du Colombier PLONG(NFS_OK); 2729a747e4fSDavid du Colombier dataptr += dir2fattr(cmd->up, &dir, dataptr); 2739a747e4fSDavid du Colombier PLONG(count); 2749a747e4fSDavid du Colombier dataptr += ROUNDUP(count); 2759a747e4fSDavid du Colombier chat("%d OK\n", count); 2769a747e4fSDavid du Colombier return dataptr - (uchar *)reply->results; 2779a747e4fSDavid du Colombier } 2789a747e4fSDavid du Colombier 2799a747e4fSDavid du Colombier static int 2809a747e4fSDavid du Colombier nfswritecache(int n, Rpccall *cmd, Rpccall *reply) 2819a747e4fSDavid du Colombier { 2829a747e4fSDavid du Colombier USED(n, reply); 2839a747e4fSDavid du Colombier chat("writecache..."); 2849a747e4fSDavid du Colombier showauth(&cmd->cred); 2859a747e4fSDavid du Colombier chat("OK\n"); 2869a747e4fSDavid du Colombier return 0; 2879a747e4fSDavid du Colombier } 2889a747e4fSDavid du Colombier 2899a747e4fSDavid du Colombier static int 2909a747e4fSDavid du Colombier nfswrite(int n, Rpccall *cmd, Rpccall *reply) 2919a747e4fSDavid du Colombier { 2929a747e4fSDavid du Colombier Session *s; 2939a747e4fSDavid du Colombier Xfid *xf; 2949a747e4fSDavid du Colombier Dir dir; 2959a747e4fSDavid du Colombier int offset, count; 2969a747e4fSDavid du Colombier uchar *argptr = cmd->args; 2979a747e4fSDavid du Colombier uchar *dataptr = reply->results; 2989a747e4fSDavid du Colombier 2999a747e4fSDavid du Colombier chat("write..."); 3009a747e4fSDavid du Colombier if(n < FHSIZE+16) 3019a747e4fSDavid du Colombier return garbage(reply, "count too small"); 3029a747e4fSDavid du Colombier xf = rpc2xfid(cmd, 0); 3039a747e4fSDavid du Colombier argptr += FHSIZE + 4; 3049a747e4fSDavid du Colombier offset = GLONG(); 3059a747e4fSDavid du Colombier argptr += 4; 3069a747e4fSDavid du Colombier count = GLONG(); 3079a747e4fSDavid du Colombier if(xf == 0) 3089a747e4fSDavid du Colombier return error(reply, NFSERR_STALE); 3099a747e4fSDavid du Colombier chat("%s %d %d...", xf->xp->name, offset, count); 3109a747e4fSDavid du Colombier if(xf->xp->s != xf->xp->parent->s){ 3119a747e4fSDavid du Colombier if(xfauthwrite(xf, offset, argptr, count) < 0) 3129a747e4fSDavid du Colombier return error(reply, NFSERR_IO); 3139a747e4fSDavid du Colombier }else{ 3149a747e4fSDavid du Colombier if(xfopen(xf, Owrite) < 0) 3159a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 3169a747e4fSDavid du Colombier s = xf->xp->s; 3179a747e4fSDavid du Colombier setfid(s, xf->opfid); 3189a747e4fSDavid du Colombier xf->opfid->tstale = nfstime + 60; 3199a747e4fSDavid du Colombier s->f.offset = offset; 3209a747e4fSDavid du Colombier s->f.count = count; 3219a747e4fSDavid du Colombier s->f.data = (char *)argptr; 3229a747e4fSDavid du Colombier if(xmesg(s, Twrite) < 0) 3239a747e4fSDavid du Colombier return error(reply, NFSERR_IO); 3249a747e4fSDavid du Colombier } 3259a747e4fSDavid du Colombier if(xfstat(xf, &dir) < 0) 3269a747e4fSDavid du Colombier return error(reply, NFSERR_IO); 3279a747e4fSDavid du Colombier PLONG(NFS_OK); 3289a747e4fSDavid du Colombier dataptr += dir2fattr(cmd->up, &dir, dataptr); 3299a747e4fSDavid du Colombier chat("OK\n"); 3309a747e4fSDavid du Colombier return dataptr - (uchar *)reply->results; 3319a747e4fSDavid du Colombier } 3329a747e4fSDavid du Colombier 3339a747e4fSDavid du Colombier static int 3349a747e4fSDavid du Colombier creat(int n, Rpccall *cmd, Rpccall *reply, int chdir) 3359a747e4fSDavid du Colombier { 3369a747e4fSDavid du Colombier Xfid *xf, *newxf; 3379a747e4fSDavid du Colombier Xfile *xp; 3389a747e4fSDavid du Colombier String elem; 3399a747e4fSDavid du Colombier Dir dir; Sattr sattr; 3409a747e4fSDavid du Colombier uchar *argptr = cmd->args; 3419a747e4fSDavid du Colombier uchar *dataptr = reply->results; 3429a747e4fSDavid du Colombier int trunced; 3439a747e4fSDavid du Colombier 3449a747e4fSDavid du Colombier if(n <= FHSIZE) 3459a747e4fSDavid du Colombier return garbage(reply, "count too small"); 3469a747e4fSDavid du Colombier xf = rpc2xfid(cmd, 0); 3479a747e4fSDavid du Colombier argptr += FHSIZE; 3489a747e4fSDavid du Colombier argptr += string2S(argptr, &elem); 3499a747e4fSDavid du Colombier argptr += convM2sattr(argptr, &sattr); 3509a747e4fSDavid du Colombier if(argptr != &((uchar *)cmd->args)[n]) 3519a747e4fSDavid du Colombier return garbage(reply, "bad count"); 3529a747e4fSDavid du Colombier if(xf == 0) 3539a747e4fSDavid du Colombier return error(reply, NFSERR_STALE); 3549a747e4fSDavid du Colombier xp = xf->xp; 3559a747e4fSDavid du Colombier if(!(xp->qid.type & QTDIR)) 3569a747e4fSDavid du Colombier return error(reply, NFSERR_NOTDIR); 3579a747e4fSDavid du Colombier chat("%s/%.*s...", xp->name, utfnlen(elem.s, elem.n), elem.s); 3589a747e4fSDavid du Colombier trunced = 0; 3599a747e4fSDavid du Colombier if(xp->parent == xp && elem.s[0] == '#'){ 3609a747e4fSDavid du Colombier newxf = xfauth(xp, &elem); 3619a747e4fSDavid du Colombier if(newxf == 0) 3629a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 3639a747e4fSDavid du Colombier if(xfauthremove(newxf, cmd->user) < 0) 3649a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 3659a747e4fSDavid du Colombier trunced = 1; 3669a747e4fSDavid du Colombier }else 3679a747e4fSDavid du Colombier newxf = xfwalkcr(Twalk, xf, &elem, 0); 3689a747e4fSDavid du Colombier if(newxf == 0){ 3699a747e4fSDavid du Colombier newxf = xfwalkcr(Tcreate, xf, &elem, chdir|(sattr.mode&0777)); 3709a747e4fSDavid du Colombier if(newxf) 3719a747e4fSDavid du Colombier trunced = 1; 3729a747e4fSDavid du Colombier else 3739a747e4fSDavid du Colombier newxf = xfwalkcr(Twalk, xf, &elem, 0); 3749a747e4fSDavid du Colombier } 3759a747e4fSDavid du Colombier if(newxf == 0) 3769a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 3779a747e4fSDavid du Colombier if(!trunced && chdir) 3789a747e4fSDavid du Colombier return error(reply, NFSERR_EXIST); 3799a747e4fSDavid du Colombier if(!trunced && xfopen(newxf, Trunc|Oread|Owrite) < 0) 3809a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 3819a747e4fSDavid du Colombier if(xfstat(newxf, &dir) < 0) 3829a747e4fSDavid du Colombier return error(reply, NFSERR_IO); 3839a747e4fSDavid du Colombier 3849a747e4fSDavid du Colombier PLONG(NFS_OK); 3859a747e4fSDavid du Colombier dataptr += xp2fhandle(newxf->xp, dataptr); 3869a747e4fSDavid du Colombier dataptr += dir2fattr(cmd->up, &dir, dataptr); 3879a747e4fSDavid du Colombier chat("OK\n"); 3889a747e4fSDavid du Colombier return dataptr - (uchar *)reply->results; 3899a747e4fSDavid du Colombier } 3909a747e4fSDavid du Colombier 3919a747e4fSDavid du Colombier static int 3929a747e4fSDavid du Colombier nfscreate(int n, Rpccall *cmd, Rpccall *reply) 3939a747e4fSDavid du Colombier { 3949a747e4fSDavid du Colombier chat("create..."); 3959a747e4fSDavid du Colombier return creat(n, cmd, reply, 0); 3969a747e4fSDavid du Colombier } 3979a747e4fSDavid du Colombier 3989a747e4fSDavid du Colombier static int 3999a747e4fSDavid du Colombier remov(int n, Rpccall *cmd, Rpccall *reply) 4009a747e4fSDavid du Colombier { 4019a747e4fSDavid du Colombier Session *s; 4029a747e4fSDavid du Colombier Xfile *xp; 4039a747e4fSDavid du Colombier Xfid *xf, *newxf; 4049a747e4fSDavid du Colombier String elem; 4059a747e4fSDavid du Colombier Fid *nfid; 4069a747e4fSDavid du Colombier uchar *argptr = cmd->args; 4079a747e4fSDavid du Colombier uchar *dataptr = reply->results; 4089a747e4fSDavid du Colombier 4099a747e4fSDavid du Colombier if(n <= FHSIZE) 4109a747e4fSDavid du Colombier return garbage(reply, "count too small"); 4119a747e4fSDavid du Colombier xf = rpc2xfid(cmd, 0); 4129a747e4fSDavid du Colombier argptr += FHSIZE; 4139a747e4fSDavid du Colombier argptr += string2S(argptr, &elem); 4149a747e4fSDavid du Colombier if(argptr != &((uchar *)cmd->args)[n]) 4159a747e4fSDavid du Colombier return garbage(reply, "bad count"); 4169a747e4fSDavid du Colombier if(xf == 0) 4179a747e4fSDavid du Colombier return error(reply, NFSERR_STALE); 4189a747e4fSDavid du Colombier xp = xf->xp; 4199a747e4fSDavid du Colombier if(!(xp->qid.type & QTDIR)) 4209a747e4fSDavid du Colombier return error(reply, NFSERR_NOTDIR); 4219a747e4fSDavid du Colombier chat("%s/%.*s...", xp->name, utfnlen(elem.s, elem.n), elem.s); 4229a747e4fSDavid du Colombier if(xp->s->noauth == 0 && xp->parent == xp && elem.s[0] == '#') 4239a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 4249a747e4fSDavid du Colombier newxf = xfwalkcr(Twalk, xf, &elem, 0); 4259a747e4fSDavid du Colombier if(newxf == 0) 4269a747e4fSDavid du Colombier return error(reply, NFSERR_NOENT); 4279a747e4fSDavid du Colombier s = xp->s; 4289a747e4fSDavid du Colombier nfid = newfid(s); 4299a747e4fSDavid du Colombier setfid(s, newxf->urfid); 4309a747e4fSDavid du Colombier s->f.newfid = nfid - s->fids; 4319a747e4fSDavid du Colombier s->f.nwname = 0; 4329a747e4fSDavid du Colombier if(xmesg(s, Twalk) < 0){ 4339a747e4fSDavid du Colombier putfid(s, nfid); 4349a747e4fSDavid du Colombier return error(reply, NFSERR_IO); 4359a747e4fSDavid du Colombier } 4369a747e4fSDavid du Colombier s->f.fid = nfid - s->fids; 4379a747e4fSDavid du Colombier if(xmesg(s, Tremove) < 0){ 4389a747e4fSDavid du Colombier putfid(s, nfid); 4399a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 4409a747e4fSDavid du Colombier } 4419a747e4fSDavid du Colombier putfid(s, nfid); 4429a747e4fSDavid du Colombier xpclear(newxf->xp); 4439a747e4fSDavid du Colombier PLONG(NFS_OK); 4449a747e4fSDavid du Colombier chat("OK\n"); 4459a747e4fSDavid du Colombier return dataptr - (uchar *)reply->results; 4469a747e4fSDavid du Colombier } 4479a747e4fSDavid du Colombier 4489a747e4fSDavid du Colombier static int 4499a747e4fSDavid du Colombier nfsremove(int n, Rpccall *cmd, Rpccall *reply) 4509a747e4fSDavid du Colombier { 4519a747e4fSDavid du Colombier chat("remove..."); 4529a747e4fSDavid du Colombier return remov(n, cmd, reply); 4539a747e4fSDavid du Colombier } 4549a747e4fSDavid du Colombier 4559a747e4fSDavid du Colombier static int 4569a747e4fSDavid du Colombier nfsrename(int n, Rpccall *cmd, Rpccall *reply) 4579a747e4fSDavid du Colombier { 4589a747e4fSDavid du Colombier Xfid *xf, *newxf; 4599a747e4fSDavid du Colombier Xfile *xp; 4609a747e4fSDavid du Colombier uchar *fromdir, *todir; 4619a747e4fSDavid du Colombier String fromelem, toelem; 4629a747e4fSDavid du Colombier Dir dir; 4639a747e4fSDavid du Colombier uchar *argptr = cmd->args; 4649a747e4fSDavid du Colombier uchar *dataptr = reply->results; 4659a747e4fSDavid du Colombier 4669a747e4fSDavid du Colombier chat("rename..."); 4679a747e4fSDavid du Colombier if(n <= FHSIZE) 4689a747e4fSDavid du Colombier return garbage(reply, "count too small"); 4699a747e4fSDavid du Colombier xf = rpc2xfid(cmd, 0); 4709a747e4fSDavid du Colombier fromdir = argptr; 4719a747e4fSDavid du Colombier argptr += FHSIZE; 4729a747e4fSDavid du Colombier argptr += string2S(argptr, &fromelem); 4739a747e4fSDavid du Colombier todir = argptr; 4749a747e4fSDavid du Colombier argptr += FHSIZE; 4759a747e4fSDavid du Colombier argptr += string2S(argptr, &toelem); 4769a747e4fSDavid du Colombier if(argptr != &((uchar *)cmd->args)[n]) 4779a747e4fSDavid du Colombier return garbage(reply, "bad count"); 4789a747e4fSDavid du Colombier if(xf == 0) 4799a747e4fSDavid du Colombier return error(reply, NFSERR_STALE); 4809a747e4fSDavid du Colombier xp = xf->xp; 4819a747e4fSDavid du Colombier if(!(xp->qid.type & QTDIR)) 4829a747e4fSDavid du Colombier return error(reply, NFSERR_NOTDIR); 4839a747e4fSDavid du Colombier if(memcmp(fromdir, todir, FHSIZE) != 0) 4849a747e4fSDavid du Colombier return error(reply, NFSERR_NXIO); 4859a747e4fSDavid du Colombier newxf = xfwalkcr(Twalk, xf, &fromelem, 0); 4869a747e4fSDavid du Colombier if(newxf == 0) 4879a747e4fSDavid du Colombier return error(reply, NFSERR_NOENT); 4889a747e4fSDavid du Colombier if(xfstat(newxf, &dir) < 0) 4899a747e4fSDavid du Colombier return error(reply, NFSERR_IO); 4909a747e4fSDavid du Colombier 4919a747e4fSDavid du Colombier if(xp->parent == xp && toelem.s[0] == '#') 4929a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 493d9306527SDavid du Colombier nulldir(&dir); 4949a747e4fSDavid du Colombier dir.name = toelem.s; 4959a747e4fSDavid du Colombier if(xfwstat(newxf, &dir) < 0) 4969a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 4979a747e4fSDavid du Colombier PLONG(NFS_OK); 4989a747e4fSDavid du Colombier chat("OK\n"); 4999a747e4fSDavid du Colombier return dataptr - (uchar *)reply->results; 5009a747e4fSDavid du Colombier } 5019a747e4fSDavid du Colombier 5029a747e4fSDavid du Colombier static int 5039a747e4fSDavid du Colombier nfslink(int n, Rpccall *cmd, Rpccall *reply) 5049a747e4fSDavid du Colombier { 5059a747e4fSDavid du Colombier USED(n, reply); 5069a747e4fSDavid du Colombier chat("link..."); 5079a747e4fSDavid du Colombier showauth(&cmd->cred); 5089a747e4fSDavid du Colombier return error(reply, NFSERR_NOENT); 5099a747e4fSDavid du Colombier } 5109a747e4fSDavid du Colombier 5119a747e4fSDavid du Colombier static int 5129a747e4fSDavid du Colombier nfssymlink(int n, Rpccall *cmd, Rpccall *reply) 5139a747e4fSDavid du Colombier { 5149a747e4fSDavid du Colombier USED(n, reply); 5159a747e4fSDavid du Colombier chat("symlink..."); 5169a747e4fSDavid du Colombier showauth(&cmd->cred); 5179a747e4fSDavid du Colombier return error(reply, NFSERR_NOENT); 5189a747e4fSDavid du Colombier } 5199a747e4fSDavid du Colombier 5209a747e4fSDavid du Colombier static int 5219a747e4fSDavid du Colombier nfsmkdir(int n, Rpccall *cmd, Rpccall *reply) 5229a747e4fSDavid du Colombier { 5239a747e4fSDavid du Colombier chat("mkdir..."); 5249a747e4fSDavid du Colombier return creat(n, cmd, reply, DMDIR); 5259a747e4fSDavid du Colombier } 5269a747e4fSDavid du Colombier 5279a747e4fSDavid du Colombier static int 5289a747e4fSDavid du Colombier nfsrmdir(int n, Rpccall *cmd, Rpccall *reply) 5299a747e4fSDavid du Colombier { 5309a747e4fSDavid du Colombier chat("rmdir..."); 5319a747e4fSDavid du Colombier return remov(n, cmd, reply); 5329a747e4fSDavid du Colombier } 5339a747e4fSDavid du Colombier 5349a747e4fSDavid du Colombier static int 5359a747e4fSDavid du Colombier nfsreaddir(int n, Rpccall *cmd, Rpccall *reply) 5369a747e4fSDavid du Colombier { 5379a747e4fSDavid du Colombier Session *s; 5389a747e4fSDavid du Colombier Xfid *xf; 5399a747e4fSDavid du Colombier Dir dir; 5409a747e4fSDavid du Colombier char *rdata; 5419a747e4fSDavid du Colombier int k, offset, count, sfcount, entries, dsize; 5429a747e4fSDavid du Colombier uchar *argptr = cmd->args; 5439a747e4fSDavid du Colombier uchar *dataptr = reply->results; 5449a747e4fSDavid du Colombier 5459a747e4fSDavid du Colombier chat("readdir..."); 5469a747e4fSDavid du Colombier if(n != FHSIZE+8) 5479a747e4fSDavid du Colombier return garbage(reply, "bad count"); 5489a747e4fSDavid du Colombier xf = rpc2xfid(cmd, 0); 5499a747e4fSDavid du Colombier argptr += FHSIZE; 5509a747e4fSDavid du Colombier offset = GLONG(); 5519a747e4fSDavid du Colombier count = GLONG(); 5529a747e4fSDavid du Colombier if(xf == 0) 5539a747e4fSDavid du Colombier return error(reply, NFSERR_STALE); 5549a747e4fSDavid du Colombier chat("%s (%ld) %d %d...", xf->xp->name, xf->offset, offset, count); 5559a747e4fSDavid du Colombier s = xf->xp->s; 5569a747e4fSDavid du Colombier if((xf->mode & Open) && xf->offset > offset) 5579a747e4fSDavid du Colombier xfclose(xf); 5589a747e4fSDavid du Colombier if(xfopen(xf, Oread) < 0) 5599a747e4fSDavid du Colombier return error(reply, NFSERR_PERM); 5609a747e4fSDavid du Colombier while(xf->offset < offset){ /* if we reopened, xf->offset will be zero */ 5619a747e4fSDavid du Colombier sfcount = offset - xf->offset; 5629a747e4fSDavid du Colombier if(sfcount > messagesize-IOHDRSZ) 5639a747e4fSDavid du Colombier sfcount = messagesize-IOHDRSZ; 5649a747e4fSDavid du Colombier setfid(s, xf->opfid); 5659a747e4fSDavid du Colombier s->f.offset = xf->offset; 5669a747e4fSDavid du Colombier s->f.count = sfcount; 5679a747e4fSDavid du Colombier if(xmesg(s, Tread) < 0){ 5689a747e4fSDavid du Colombier xfclose(xf); 5699a747e4fSDavid du Colombier return error(reply, NFSERR_IO); 5709a747e4fSDavid du Colombier } 5719a747e4fSDavid du Colombier if(s->f.count <= BIT16SZ) 5729a747e4fSDavid du Colombier break; 5739a747e4fSDavid du Colombier xf->offset += s->f.count; 5749a747e4fSDavid du Colombier } 5759a747e4fSDavid du Colombier if(count > messagesize-IOHDRSZ) 5769a747e4fSDavid du Colombier count = messagesize-IOHDRSZ; 5779a747e4fSDavid du Colombier PLONG(NFS_OK); 5789a747e4fSDavid du Colombier entries = 0; 5799a747e4fSDavid du Colombier while(count > 16){ /* at least 16 bytes required; we don't know size of name */ 5809a747e4fSDavid du Colombier chat("top of loop\n"); 5819a747e4fSDavid du Colombier setfid(s, xf->opfid); 5829a747e4fSDavid du Colombier s->f.offset = xf->offset; 5839a747e4fSDavid du Colombier s->f.count = count; /* as good a guess as any */ 5849a747e4fSDavid du Colombier if(xmesg(s, Tread) < 0){ 5859a747e4fSDavid du Colombier xfclose(xf); 5869a747e4fSDavid du Colombier return error(reply, NFSERR_IO); 5879a747e4fSDavid du Colombier } 5889a747e4fSDavid du Colombier sfcount = s->f.count; 5899a747e4fSDavid du Colombier if(sfcount <= BIT16SZ) 5909a747e4fSDavid du Colombier break; 5919a747e4fSDavid du Colombier xf->offset += sfcount; 5929a747e4fSDavid du Colombier chat("count %d data 0x%p\n", s->f.count, s->f.data); 5939a747e4fSDavid du Colombier rdata = s->f.data; 5949a747e4fSDavid du Colombier /* now have a buffer of Plan 9 directories; unpack into NFS thingies */ 5959a747e4fSDavid du Colombier while(sfcount >= 0){ 5969a747e4fSDavid du Colombier dsize = convM2D((uchar*)rdata, sfcount, &dir, (char*)s->statbuf); 5979a747e4fSDavid du Colombier if(dsize <= BIT16SZ){ 5989a747e4fSDavid du Colombier count = 0; /* force break from outer loop */ 5999a747e4fSDavid du Colombier break; 6009a747e4fSDavid du Colombier } 6019a747e4fSDavid du Colombier offset += dsize; 6029a747e4fSDavid du Colombier k = strlen(dir.name); 6039a747e4fSDavid du Colombier if(count < 16+ROUNDUP(k)){ 6049a747e4fSDavid du Colombier count = 0; /* force break from outer loop */ 6059a747e4fSDavid du Colombier break; 6069a747e4fSDavid du Colombier } 6079a747e4fSDavid du Colombier PLONG(TRUE); 6089a747e4fSDavid du Colombier PLONG(dir.qid.path); 6099a747e4fSDavid du Colombier PLONG(k); 6109a747e4fSDavid du Colombier PPTR(dir.name, k); 6119a747e4fSDavid du Colombier PLONG(offset); 6129a747e4fSDavid du Colombier count -= 16+ROUNDUP(k); 6139a747e4fSDavid du Colombier rdata += dsize; 6149a747e4fSDavid du Colombier sfcount -= dsize; 6159a747e4fSDavid du Colombier } 6169a747e4fSDavid du Colombier } 6179a747e4fSDavid du Colombier PLONG(FALSE); 6189a747e4fSDavid du Colombier if(s->f.count <= 0){ 6199a747e4fSDavid du Colombier xfclose(xf); 6209a747e4fSDavid du Colombier chat("eof..."); 6219a747e4fSDavid du Colombier PLONG(TRUE); 6229a747e4fSDavid du Colombier }else 6239a747e4fSDavid du Colombier PLONG(FALSE); 6249a747e4fSDavid du Colombier chat("%d OK\n", entries); 6259a747e4fSDavid du Colombier return dataptr - (uchar *)reply->results; 6269a747e4fSDavid du Colombier } 6279a747e4fSDavid du Colombier 6289a747e4fSDavid du Colombier static int 6299a747e4fSDavid du Colombier nfsstatfs(int n, Rpccall *cmd, Rpccall *reply) 6309a747e4fSDavid du Colombier { 6319a747e4fSDavid du Colombier uchar *dataptr = reply->results; 632*8cd281c0SDavid du Colombier enum { 633*8cd281c0SDavid du Colombier Xfersize = 2048, 634*8cd281c0SDavid du Colombier Maxlong = (long)((1ULL<<31) - 1), 635*8cd281c0SDavid du Colombier Maxfreeblks = Maxlong / Xfersize, 636*8cd281c0SDavid du Colombier }; 6379a747e4fSDavid du Colombier 6389a747e4fSDavid du Colombier chat("statfs..."); 6399a747e4fSDavid du Colombier showauth(&cmd->cred); 6409a747e4fSDavid du Colombier if(n != FHSIZE) 6419a747e4fSDavid du Colombier return garbage(reply, "bad count"); 6429a747e4fSDavid du Colombier PLONG(NFS_OK); 643*8cd281c0SDavid du Colombier PLONG(4096); /* tsize (fs block size) */ 644*8cd281c0SDavid du Colombier PLONG(Xfersize); /* bsize (optimal transfer size) */ 645*8cd281c0SDavid du Colombier PLONG(Maxfreeblks); /* blocks in fs */ 646*8cd281c0SDavid du Colombier PLONG(Maxfreeblks); /* bfree to root*/ 647*8cd281c0SDavid du Colombier PLONG(Maxfreeblks); /* bavail (free to mortals) */ 6489a747e4fSDavid du Colombier chat("OK\n"); 6499a747e4fSDavid du Colombier /*conftime = 0; 6509a747e4fSDavid du Colombier readunixidmaps(config);*/ 6519a747e4fSDavid du Colombier return dataptr - (uchar *)reply->results; 6529a747e4fSDavid du Colombier } 653