13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 3*219b2ee8SDavid du Colombier #include <auth.h> 43e12c5d1SDavid du Colombier #include <fcall.h> 53e12c5d1SDavid du Colombier 63e12c5d1SDavid du Colombier #include "cformat.h" 73e12c5d1SDavid du Colombier #include "lru.h" 83e12c5d1SDavid du Colombier #include "bcache.h" 93e12c5d1SDavid du Colombier #include "disk.h" 103e12c5d1SDavid du Colombier #include "inode.h" 113e12c5d1SDavid du Colombier #include "file.h" 123e12c5d1SDavid du Colombier 133e12c5d1SDavid du Colombier enum 143e12c5d1SDavid du Colombier { 153e12c5d1SDavid du Colombier Nfid= 1024, 163e12c5d1SDavid du Colombier }; 173e12c5d1SDavid du Colombier 183e12c5d1SDavid du Colombier 193e12c5d1SDavid du Colombier typedef struct Mfile Mfile; 203e12c5d1SDavid du Colombier typedef struct Ram Ram; 213e12c5d1SDavid du Colombier typedef struct P9fs P9fs; 223e12c5d1SDavid du Colombier 233e12c5d1SDavid du Colombier struct Mfile 243e12c5d1SDavid du Colombier { 253e12c5d1SDavid du Colombier Qid qid; 263e12c5d1SDavid du Colombier short oldfid; 273e12c5d1SDavid du Colombier char needclone; 283e12c5d1SDavid du Colombier char busy; 293e12c5d1SDavid du Colombier }; 303e12c5d1SDavid du Colombier 313e12c5d1SDavid du Colombier Mfile mfile[Nfid]; 323e12c5d1SDavid du Colombier char user[NAMELEN]; 333e12c5d1SDavid du Colombier Icache ic; 343e12c5d1SDavid du Colombier int debug; 353e12c5d1SDavid du Colombier 363e12c5d1SDavid du Colombier struct P9fs 373e12c5d1SDavid du Colombier { 383e12c5d1SDavid du Colombier int fd[2]; 393e12c5d1SDavid du Colombier Fcall rhdr; 403e12c5d1SDavid du Colombier Fcall thdr; 413e12c5d1SDavid du Colombier long len; 423e12c5d1SDavid du Colombier char *name; 433e12c5d1SDavid du Colombier }; 443e12c5d1SDavid du Colombier 453e12c5d1SDavid du Colombier P9fs c; /* client conversation */ 463e12c5d1SDavid du Colombier P9fs s; /* server conversation */ 473e12c5d1SDavid du Colombier 483e12c5d1SDavid du Colombier char datasnd[MAXFDATA + MAXMSG]; 493e12c5d1SDavid du Colombier char datarcv[MAXFDATA + MAXMSG]; 503e12c5d1SDavid du Colombier 51*219b2ee8SDavid du Colombier void rsession(void); 523e12c5d1SDavid du Colombier void rflush(void); 533e12c5d1SDavid du Colombier void rattach(Mfile*); 543e12c5d1SDavid du Colombier void rclone(Mfile*); 553e12c5d1SDavid du Colombier void rwalk(Mfile*); 563e12c5d1SDavid du Colombier void rclwalk(Mfile*); 573e12c5d1SDavid du Colombier void ropen(Mfile*); 583e12c5d1SDavid du Colombier void rcreate(Mfile*); 593e12c5d1SDavid du Colombier void rread(Mfile*); 603e12c5d1SDavid du Colombier void rwrite(Mfile*); 613e12c5d1SDavid du Colombier void rclunk(Mfile*); 623e12c5d1SDavid du Colombier void rremove(Mfile*); 633e12c5d1SDavid du Colombier void rstat(Mfile*); 643e12c5d1SDavid du Colombier void rwstat(Mfile*); 653e12c5d1SDavid du Colombier void error(char*); 663e12c5d1SDavid du Colombier void warning(char*); 673e12c5d1SDavid du Colombier void mountinit(char*, char*); 683e12c5d1SDavid du Colombier void io(void); 693e12c5d1SDavid du Colombier void sendreply(char*); 703e12c5d1SDavid du Colombier void sendmsg(P9fs*, Fcall*); 713e12c5d1SDavid du Colombier void rcvmsg(P9fs*, Fcall*); 723e12c5d1SDavid du Colombier int delegate(void); 733e12c5d1SDavid du Colombier int askserver(void); 743e12c5d1SDavid du Colombier void cachesetup(int, char*); 753e12c5d1SDavid du Colombier int doclone(Mfile*); 763e12c5d1SDavid du Colombier void doclwalk(Mfile*, char*); 773e12c5d1SDavid du Colombier 783e12c5d1SDavid du Colombier #define PREFACE(m) if(doclone(m) < 0) return 793e12c5d1SDavid du Colombier 803e12c5d1SDavid du Colombier char *mname[]={ 813e12c5d1SDavid du Colombier [Tnop] "Tnop", 823e12c5d1SDavid du Colombier [Tsession] "Tsession", 833e12c5d1SDavid du Colombier [Tflush] "Tflush", 843e12c5d1SDavid du Colombier [Tattach] "Tattach", 853e12c5d1SDavid du Colombier [Tclone] "Tclone", 863e12c5d1SDavid du Colombier [Twalk] "Twalk", 873e12c5d1SDavid du Colombier [Topen] "Topen", 883e12c5d1SDavid du Colombier [Tcreate] "Tcreate", 893e12c5d1SDavid du Colombier [Tclunk] "Tclunk", 903e12c5d1SDavid du Colombier [Tread] "Tread", 913e12c5d1SDavid du Colombier [Twrite] "Twrite", 923e12c5d1SDavid du Colombier [Tremove] "Tremove", 933e12c5d1SDavid du Colombier [Tstat] "Tstat", 943e12c5d1SDavid du Colombier [Twstat] "Twstat", 953e12c5d1SDavid du Colombier [Tclwalk] "Tclwalk", 963e12c5d1SDavid du Colombier [Rnop] "Rnop", 973e12c5d1SDavid du Colombier [Rsession] "Rsession", 983e12c5d1SDavid du Colombier [Rerror] "Rerror", 993e12c5d1SDavid du Colombier [Rflush] "Rflush", 1003e12c5d1SDavid du Colombier [Rattach] "Rattach", 1013e12c5d1SDavid du Colombier [Rclone] "Rclone", 1023e12c5d1SDavid du Colombier [Rwalk] "Rwalk", 1033e12c5d1SDavid du Colombier [Ropen] "Ropen", 1043e12c5d1SDavid du Colombier [Rcreate] "Rcreate", 1053e12c5d1SDavid du Colombier [Rclunk] "Rclunk", 1063e12c5d1SDavid du Colombier [Rread] "Rread", 1073e12c5d1SDavid du Colombier [Rwrite] "Rwrite", 1083e12c5d1SDavid du Colombier [Rremove] "Rremove", 1093e12c5d1SDavid du Colombier [Rstat] "Rstat", 1103e12c5d1SDavid du Colombier [Rwstat] "Rwstat", 1113e12c5d1SDavid du Colombier [Rclwalk] "Rclwalk", 1123e12c5d1SDavid du Colombier [Rauth] "Rauth", 1133e12c5d1SDavid du Colombier 0, 1143e12c5d1SDavid du Colombier }; 1153e12c5d1SDavid du Colombier 1163e12c5d1SDavid du Colombier void 1173e12c5d1SDavid du Colombier usage(void) 1183e12c5d1SDavid du Colombier { 1193e12c5d1SDavid du Colombier fprint(2, "usage:\tcfs -s [-rd] [-f partition]"); 1203e12c5d1SDavid du Colombier fprint(2, "\tcfs [-rd] [-f partition] [-a netaddr] [mt-pt]\n"); 1213e12c5d1SDavid du Colombier } 1223e12c5d1SDavid du Colombier 1233e12c5d1SDavid du Colombier void 1243e12c5d1SDavid du Colombier main(int argc, char *argv[]) 1253e12c5d1SDavid du Colombier { 1263e12c5d1SDavid du Colombier int std; 1273e12c5d1SDavid du Colombier int format; 1283e12c5d1SDavid du Colombier char *part; 1293e12c5d1SDavid du Colombier char *server; 1303e12c5d1SDavid du Colombier char *mtpt; 1313e12c5d1SDavid du Colombier 1323e12c5d1SDavid du Colombier std = 0; 1333e12c5d1SDavid du Colombier format = 0; 1343e12c5d1SDavid du Colombier part = "/dev/hd0cache"; 1353e12c5d1SDavid du Colombier server = "dk!bootes"; 1363e12c5d1SDavid du Colombier mtpt = "/tmp"; 1373e12c5d1SDavid du Colombier 1383e12c5d1SDavid du Colombier ARGBEGIN{ 1393e12c5d1SDavid du Colombier case 'a': 1403e12c5d1SDavid du Colombier server = ARGF(); 1413e12c5d1SDavid du Colombier if(server == 0) 1423e12c5d1SDavid du Colombier usage(); 1433e12c5d1SDavid du Colombier break; 1443e12c5d1SDavid du Colombier case 's': 1453e12c5d1SDavid du Colombier std = 1; 1463e12c5d1SDavid du Colombier break; 1473e12c5d1SDavid du Colombier case 'r': 1483e12c5d1SDavid du Colombier format = 1; 1493e12c5d1SDavid du Colombier break; 1503e12c5d1SDavid du Colombier case 'f': 1513e12c5d1SDavid du Colombier part = ARGF(); 1523e12c5d1SDavid du Colombier if(part == 0) 1533e12c5d1SDavid du Colombier usage(); 1543e12c5d1SDavid du Colombier break; 1553e12c5d1SDavid du Colombier case 'd': 1563e12c5d1SDavid du Colombier debug = 1; 1573e12c5d1SDavid du Colombier break; 1583e12c5d1SDavid du Colombier default: 1593e12c5d1SDavid du Colombier usage(); 1603e12c5d1SDavid du Colombier }ARGEND 1613e12c5d1SDavid du Colombier if(argc && *argv) 1623e12c5d1SDavid du Colombier mtpt = *argv; 1633e12c5d1SDavid du Colombier 1643e12c5d1SDavid du Colombier cachesetup(format, part); 1653e12c5d1SDavid du Colombier 1663e12c5d1SDavid du Colombier c.name = "client"; 1673e12c5d1SDavid du Colombier s.name = "server"; 1683e12c5d1SDavid du Colombier if(std){ 1693e12c5d1SDavid du Colombier c.fd[0] = c.fd[1] = 1; 1703e12c5d1SDavid du Colombier s.fd[0] = s.fd[1] = 0; 1713e12c5d1SDavid du Colombier }else 1723e12c5d1SDavid du Colombier mountinit(server, mtpt); 1733e12c5d1SDavid du Colombier 1743e12c5d1SDavid du Colombier switch(fork()){ 1753e12c5d1SDavid du Colombier case 0: 1763e12c5d1SDavid du Colombier io(); 1773e12c5d1SDavid du Colombier exits(""); 1783e12c5d1SDavid du Colombier case -1: 1793e12c5d1SDavid du Colombier error("fork"); 1803e12c5d1SDavid du Colombier default: 1813e12c5d1SDavid du Colombier exits(""); 1823e12c5d1SDavid du Colombier } 1833e12c5d1SDavid du Colombier } 1843e12c5d1SDavid du Colombier 1853e12c5d1SDavid du Colombier void 1863e12c5d1SDavid du Colombier cachesetup(int format, char *partition) 1873e12c5d1SDavid du Colombier { 1883e12c5d1SDavid du Colombier int f; 1893e12c5d1SDavid du Colombier int secsize; 1903e12c5d1SDavid du Colombier int inodes; 1913e12c5d1SDavid du Colombier int blocksize; 1923e12c5d1SDavid du Colombier 1933e12c5d1SDavid du Colombier secsize = 512; 1943e12c5d1SDavid du Colombier inodes = 1024; 1953e12c5d1SDavid du Colombier blocksize = 4*1024; 1963e12c5d1SDavid du Colombier 1973e12c5d1SDavid du Colombier f = open(partition, ORDWR); 1983e12c5d1SDavid du Colombier if(f < 0) 1993e12c5d1SDavid du Colombier error("opening partition"); 2003e12c5d1SDavid du Colombier 2013e12c5d1SDavid du Colombier if(format || iinit(&ic, f, secsize)<0){ 2023e12c5d1SDavid du Colombier if(iformat(&ic, f, inodes, "bootes", blocksize, secsize) < 0) 2033e12c5d1SDavid du Colombier error("formatting failed"); 2043e12c5d1SDavid du Colombier } 2053e12c5d1SDavid du Colombier } 2063e12c5d1SDavid du Colombier 2073e12c5d1SDavid du Colombier void 2083e12c5d1SDavid du Colombier mountinit(char *server, char *mountpoint) 2093e12c5d1SDavid du Colombier { 2103e12c5d1SDavid du Colombier int p[2]; 2113e12c5d1SDavid du Colombier 2123e12c5d1SDavid du Colombier /* 2133e12c5d1SDavid du Colombier * grab a channel and call up the file server 2143e12c5d1SDavid du Colombier */ 2153e12c5d1SDavid du Colombier s.fd[0] = s.fd[1] = dial(netmkaddr(server, 0, 0), 0, 0, 0); 2163e12c5d1SDavid du Colombier if(s.fd[0] < 0) 2173e12c5d1SDavid du Colombier error("opening data"); 2183e12c5d1SDavid du Colombier 2193e12c5d1SDavid du Colombier /* 2203e12c5d1SDavid du Colombier * mount onto name space 2213e12c5d1SDavid du Colombier */ 2223e12c5d1SDavid du Colombier if(pipe(p) < 0) 2233e12c5d1SDavid du Colombier error("pipe failed"); 2243e12c5d1SDavid du Colombier switch(fork()){ 2253e12c5d1SDavid du Colombier case 0: 226*219b2ee8SDavid du Colombier break; 227*219b2ee8SDavid du Colombier default: 228*219b2ee8SDavid du Colombier if(amount(p[1], mountpoint, MREPL|MCREATE, "") < 0) 2293e12c5d1SDavid du Colombier error("mount failed"); 2303e12c5d1SDavid du Colombier exits(0); 2313e12c5d1SDavid du Colombier case -1: 2323e12c5d1SDavid du Colombier error("fork failed\n"); 2333e12c5d1SDavid du Colombier /*BUG: no wait!*/ 2343e12c5d1SDavid du Colombier } 2353e12c5d1SDavid du Colombier c.fd[0] = c.fd[1] = p[0]; 2363e12c5d1SDavid du Colombier } 2373e12c5d1SDavid du Colombier 2383e12c5d1SDavid du Colombier void 2393e12c5d1SDavid du Colombier io(void) 2403e12c5d1SDavid du Colombier { 2413e12c5d1SDavid du Colombier Mfile *mf; 2423e12c5d1SDavid du Colombier loop: 2433e12c5d1SDavid du Colombier rcvmsg(&c, &c.thdr); 2443e12c5d1SDavid du Colombier mf = &mfile[c.thdr.fid]; 2453e12c5d1SDavid du Colombier switch(c.thdr.type){ 2463e12c5d1SDavid du Colombier default: 2473e12c5d1SDavid du Colombier error("type"); 2483e12c5d1SDavid du Colombier break; 2493e12c5d1SDavid du Colombier case Tsession: 250*219b2ee8SDavid du Colombier rsession(); 2513e12c5d1SDavid du Colombier break; 2523e12c5d1SDavid du Colombier case Tnop: 2533e12c5d1SDavid du Colombier rflush(); 2543e12c5d1SDavid du Colombier break; 2553e12c5d1SDavid du Colombier case Tflush: 2563e12c5d1SDavid du Colombier rflush(); 2573e12c5d1SDavid du Colombier break; 2583e12c5d1SDavid du Colombier case Tattach: 2593e12c5d1SDavid du Colombier rattach(mf); 2603e12c5d1SDavid du Colombier break; 2613e12c5d1SDavid du Colombier case Tclone: 2623e12c5d1SDavid du Colombier rclone(mf); 2633e12c5d1SDavid du Colombier break; 2643e12c5d1SDavid du Colombier case Twalk: 2653e12c5d1SDavid du Colombier rwalk(mf); 2663e12c5d1SDavid du Colombier break; 2673e12c5d1SDavid du Colombier case Topen: 2683e12c5d1SDavid du Colombier ropen(mf); 2693e12c5d1SDavid du Colombier break; 2703e12c5d1SDavid du Colombier case Tcreate: 2713e12c5d1SDavid du Colombier rcreate(mf); 2723e12c5d1SDavid du Colombier break; 2733e12c5d1SDavid du Colombier case Tread: 2743e12c5d1SDavid du Colombier rread(mf); 2753e12c5d1SDavid du Colombier break; 2763e12c5d1SDavid du Colombier case Twrite: 2773e12c5d1SDavid du Colombier rwrite(mf); 2783e12c5d1SDavid du Colombier break; 2793e12c5d1SDavid du Colombier case Tclunk: 2803e12c5d1SDavid du Colombier rclunk(mf); 2813e12c5d1SDavid du Colombier break; 2823e12c5d1SDavid du Colombier case Tremove: 2833e12c5d1SDavid du Colombier rremove(mf); 2843e12c5d1SDavid du Colombier break; 2853e12c5d1SDavid du Colombier case Tstat: 2863e12c5d1SDavid du Colombier rstat(mf); 2873e12c5d1SDavid du Colombier break; 2883e12c5d1SDavid du Colombier case Twstat: 2893e12c5d1SDavid du Colombier rwstat(mf); 2903e12c5d1SDavid du Colombier break; 2913e12c5d1SDavid du Colombier } 2923e12c5d1SDavid du Colombier goto loop; 2933e12c5d1SDavid du Colombier } 2943e12c5d1SDavid du Colombier 2953e12c5d1SDavid du Colombier void 296*219b2ee8SDavid du Colombier rsession(void) 297*219b2ee8SDavid du Colombier { 298*219b2ee8SDavid du Colombier delegate(); 299*219b2ee8SDavid du Colombier } 300*219b2ee8SDavid du Colombier 301*219b2ee8SDavid du Colombier void 3023e12c5d1SDavid du Colombier rflush(void) /* synchronous so easy */ 3033e12c5d1SDavid du Colombier { 3043e12c5d1SDavid du Colombier sendreply(0); 3053e12c5d1SDavid du Colombier } 3063e12c5d1SDavid du Colombier 3073e12c5d1SDavid du Colombier void 3083e12c5d1SDavid du Colombier rattach(Mfile *mf) 3093e12c5d1SDavid du Colombier { 3103e12c5d1SDavid du Colombier if(delegate() == 0){ 3113e12c5d1SDavid du Colombier mf->qid = s.rhdr.qid; 3123e12c5d1SDavid du Colombier mf->busy = 1; 3133e12c5d1SDavid du Colombier mf->needclone = 0; 3143e12c5d1SDavid du Colombier } 3153e12c5d1SDavid du Colombier } 3163e12c5d1SDavid du Colombier 3173e12c5d1SDavid du Colombier /* 3183e12c5d1SDavid du Colombier * check consistency and perform a delayed clone 3193e12c5d1SDavid du Colombier */ 3203e12c5d1SDavid du Colombier int 3213e12c5d1SDavid du Colombier doclone(Mfile *mf) 3223e12c5d1SDavid du Colombier { 3233e12c5d1SDavid du Colombier Mfile *omf; 3243e12c5d1SDavid du Colombier 3253e12c5d1SDavid du Colombier if(!mf->busy) 3263e12c5d1SDavid du Colombier error("bad fid"); 3273e12c5d1SDavid du Colombier if(!mf->needclone) 3283e12c5d1SDavid du Colombier return 0; 3293e12c5d1SDavid du Colombier omf = &mfile[mf->oldfid]; 3303e12c5d1SDavid du Colombier if(!omf->busy) 3313e12c5d1SDavid du Colombier error("bad old fid"); 3323e12c5d1SDavid du Colombier 3333e12c5d1SDavid du Colombier s.thdr.type = Tclone; 3343e12c5d1SDavid du Colombier s.thdr.fid = mf->oldfid; 3353e12c5d1SDavid du Colombier s.thdr.newfid = mf - mfile; 3363e12c5d1SDavid du Colombier mf->needclone = 0; 3373e12c5d1SDavid du Colombier if(askserver() == 0) 3383e12c5d1SDavid du Colombier return 0; 3393e12c5d1SDavid du Colombier sendreply(s.rhdr.ename); 3403e12c5d1SDavid du Colombier return -1; 3413e12c5d1SDavid du Colombier } 3423e12c5d1SDavid du Colombier 3433e12c5d1SDavid du Colombier /* 3443e12c5d1SDavid du Colombier * don't send clone to server, just reply to client 3453e12c5d1SDavid du Colombier */ 3463e12c5d1SDavid du Colombier void 3473e12c5d1SDavid du Colombier rclone(Mfile *mf) 3483e12c5d1SDavid du Colombier { 3493e12c5d1SDavid du Colombier Mfile *nmf; 3503e12c5d1SDavid du Colombier 3513e12c5d1SDavid du Colombier PREFACE(mf); 3523e12c5d1SDavid du Colombier if(c.thdr.newfid<0 || Nfid<=c.thdr.newfid) 3533e12c5d1SDavid du Colombier error("clone nfid out of range"); 3543e12c5d1SDavid du Colombier nmf = &mfile[c.thdr.newfid]; 3553e12c5d1SDavid du Colombier if(nmf->busy) 3563e12c5d1SDavid du Colombier error("clone to used channel"); 3573e12c5d1SDavid du Colombier nmf = &mfile[c.thdr.newfid]; 3583e12c5d1SDavid du Colombier nmf->qid = mf->qid; 3593e12c5d1SDavid du Colombier nmf->needclone = 1; 3603e12c5d1SDavid du Colombier nmf->oldfid = mf - mfile; 3613e12c5d1SDavid du Colombier nmf->busy = 1; 3623e12c5d1SDavid du Colombier sendreply(0); 3633e12c5d1SDavid du Colombier } 3643e12c5d1SDavid du Colombier 3653e12c5d1SDavid du Colombier /* 3663e12c5d1SDavid du Colombier * do a combined clone and walk. An error implies a clunk. A reply with 3673e12c5d1SDavid du Colombier * the wrong fid implies a "directory entry not found". 3683e12c5d1SDavid du Colombier */ 3693e12c5d1SDavid du Colombier void 3703e12c5d1SDavid du Colombier doclwalk(Mfile *mf, char *name) 3713e12c5d1SDavid du Colombier { 3723e12c5d1SDavid du Colombier s.thdr.type = Tclwalk; 3733e12c5d1SDavid du Colombier s.thdr.fid = mf->oldfid; 3743e12c5d1SDavid du Colombier s.thdr.newfid = mf - mfile; 3753e12c5d1SDavid du Colombier memmove(s.thdr.name, name, sizeof s.thdr.name); 3763e12c5d1SDavid du Colombier if(askserver() == 0){ 3773e12c5d1SDavid du Colombier if(s.rhdr.fid == s.thdr.fid){ 3783e12c5d1SDavid du Colombier /* 3793e12c5d1SDavid du Colombier * this is really a short form of 3803e12c5d1SDavid du Colombier * Terror "directory entry not found" 3813e12c5d1SDavid du Colombier */ 3823e12c5d1SDavid du Colombier mf->busy = 0; 3833e12c5d1SDavid du Colombier sendreply("directory entry not found"); 3843e12c5d1SDavid du Colombier return; 3853e12c5d1SDavid du Colombier } 3863e12c5d1SDavid du Colombier mf->qid = s.rhdr.qid; 3873e12c5d1SDavid du Colombier c.rhdr.qid = s.rhdr.qid; 3883e12c5d1SDavid du Colombier mf->needclone = 0; 3893e12c5d1SDavid du Colombier sendreply(0); 3903e12c5d1SDavid du Colombier } else { 3913e12c5d1SDavid du Colombier mf->busy = 0; 3923e12c5d1SDavid du Colombier sendreply(s.rhdr.ename); 3933e12c5d1SDavid du Colombier } 3943e12c5d1SDavid du Colombier } 3953e12c5d1SDavid du Colombier 3963e12c5d1SDavid du Colombier void 3973e12c5d1SDavid du Colombier rwalk(Mfile *mf) 3983e12c5d1SDavid du Colombier { 3993e12c5d1SDavid du Colombier if(mf->needclone){ 4003e12c5d1SDavid du Colombier doclwalk(mf, c.thdr.name); 4013e12c5d1SDavid du Colombier return; 4023e12c5d1SDavid du Colombier } 4033e12c5d1SDavid du Colombier if(delegate() == 0) 4043e12c5d1SDavid du Colombier mf->qid = s.rhdr.qid; 4053e12c5d1SDavid du Colombier } 4063e12c5d1SDavid du Colombier 4073e12c5d1SDavid du Colombier void 4083e12c5d1SDavid du Colombier rclwalk(Mfile *mf) 4093e12c5d1SDavid du Colombier { 4103e12c5d1SDavid du Colombier if(delegate() == 0) 4113e12c5d1SDavid du Colombier mf->qid = s.rhdr.qid; 4123e12c5d1SDavid du Colombier } 4133e12c5d1SDavid du Colombier 4143e12c5d1SDavid du Colombier void 4153e12c5d1SDavid du Colombier ropen(Mfile *mf) 4163e12c5d1SDavid du Colombier { 4173e12c5d1SDavid du Colombier PREFACE(mf); 4183e12c5d1SDavid du Colombier if(delegate() == 0){ 4193e12c5d1SDavid du Colombier mf->qid = s.rhdr.qid; 4203e12c5d1SDavid du Colombier if(c.thdr.mode & OTRUNC){ 4213e12c5d1SDavid du Colombier mf->qid.vers++; 4223e12c5d1SDavid du Colombier iget(&ic, mf->qid); 4233e12c5d1SDavid du Colombier } 4243e12c5d1SDavid du Colombier } 4253e12c5d1SDavid du Colombier } 4263e12c5d1SDavid du Colombier 4273e12c5d1SDavid du Colombier void 4283e12c5d1SDavid du Colombier rcreate(Mfile *mf) 4293e12c5d1SDavid du Colombier { 4303e12c5d1SDavid du Colombier PREFACE(mf); 4313e12c5d1SDavid du Colombier if(delegate() == 0){ 4323e12c5d1SDavid du Colombier mf->qid = s.rhdr.qid; 4333e12c5d1SDavid du Colombier mf->qid.vers++; 4343e12c5d1SDavid du Colombier } 4353e12c5d1SDavid du Colombier } 4363e12c5d1SDavid du Colombier 4373e12c5d1SDavid du Colombier void 4383e12c5d1SDavid du Colombier rclunk(Mfile *mf) 4393e12c5d1SDavid du Colombier { 4403e12c5d1SDavid du Colombier if(!mf->busy){ 4413e12c5d1SDavid du Colombier sendreply(0); 4423e12c5d1SDavid du Colombier return; 4433e12c5d1SDavid du Colombier } 4443e12c5d1SDavid du Colombier mf->busy = 0; 4453e12c5d1SDavid du Colombier mf->needclone = 0; 4463e12c5d1SDavid du Colombier delegate(); 4473e12c5d1SDavid du Colombier } 4483e12c5d1SDavid du Colombier 4493e12c5d1SDavid du Colombier void 4503e12c5d1SDavid du Colombier rremove(Mfile *mf) 4513e12c5d1SDavid du Colombier { 4523e12c5d1SDavid du Colombier PREFACE(mf); 4533e12c5d1SDavid du Colombier mf->busy = 0; 4543e12c5d1SDavid du Colombier delegate(); 4553e12c5d1SDavid du Colombier } 4563e12c5d1SDavid du Colombier 4573e12c5d1SDavid du Colombier void 4583e12c5d1SDavid du Colombier rread(Mfile *mf) 4593e12c5d1SDavid du Colombier { 4603e12c5d1SDavid du Colombier int cnt; 4613e12c5d1SDavid du Colombier long off, first; 4623e12c5d1SDavid du Colombier char *cp; 4633e12c5d1SDavid du Colombier Ibuf *b; 4643e12c5d1SDavid du Colombier long n; 4653e12c5d1SDavid du Colombier char data[MAXFDATA]; 4663e12c5d1SDavid du Colombier int done; 4673e12c5d1SDavid du Colombier 4683e12c5d1SDavid du Colombier PREFACE(mf); 4693e12c5d1SDavid du Colombier first = off = c.thdr.offset; 4703e12c5d1SDavid du Colombier cnt = c.thdr.count; 4713e12c5d1SDavid du Colombier 4723e12c5d1SDavid du Colombier if(mf->qid.path & CHDIR){ 4733e12c5d1SDavid du Colombier delegate(); 4743e12c5d1SDavid du Colombier return; 4753e12c5d1SDavid du Colombier } 4763e12c5d1SDavid du Colombier 4773e12c5d1SDavid du Colombier b = iget(&ic, mf->qid); 4783e12c5d1SDavid du Colombier if(b == 0){ 4793e12c5d1SDavid du Colombier delegate(); 4803e12c5d1SDavid du Colombier return; 4813e12c5d1SDavid du Colombier } 4823e12c5d1SDavid du Colombier 4833e12c5d1SDavid du Colombier cp = data; 4843e12c5d1SDavid du Colombier done = 0; 4853e12c5d1SDavid du Colombier while(cnt>0 && !done){ 4863e12c5d1SDavid du Colombier n = fread(&ic, b, cp, off, cnt); 4873e12c5d1SDavid du Colombier if(n <= 0){ 4883e12c5d1SDavid du Colombier n = -n; 4893e12c5d1SDavid du Colombier if(n==0 || n>cnt) 4903e12c5d1SDavid du Colombier n = cnt; 4913e12c5d1SDavid du Colombier s.thdr.type = c.thdr.type; 4923e12c5d1SDavid du Colombier s.thdr.fid = c.thdr.fid; 4933e12c5d1SDavid du Colombier s.thdr.tag = c.thdr.tag; 4943e12c5d1SDavid du Colombier s.thdr.offset = off; 4953e12c5d1SDavid du Colombier s.thdr.count = n; 4963e12c5d1SDavid du Colombier if(askserver() < 0) 4973e12c5d1SDavid du Colombier sendreply(s.rhdr.ename); 4983e12c5d1SDavid du Colombier if(s.rhdr.count != n) 4993e12c5d1SDavid du Colombier done = 1; 5003e12c5d1SDavid du Colombier n = s.rhdr.count; 5013e12c5d1SDavid du Colombier memmove(cp, s.rhdr.data, n); 5023e12c5d1SDavid du Colombier fwrite(&ic, b, cp, off, n); 5033e12c5d1SDavid du Colombier } 5043e12c5d1SDavid du Colombier cnt -= n; 5053e12c5d1SDavid du Colombier off += n; 5063e12c5d1SDavid du Colombier cp += n; 5073e12c5d1SDavid du Colombier } 5083e12c5d1SDavid du Colombier c.rhdr.data = data; 5093e12c5d1SDavid du Colombier c.rhdr.count = off - first; 5103e12c5d1SDavid du Colombier sendreply(0); 5113e12c5d1SDavid du Colombier } 5123e12c5d1SDavid du Colombier 5133e12c5d1SDavid du Colombier void 5143e12c5d1SDavid du Colombier rwrite(Mfile *mf) 5153e12c5d1SDavid du Colombier { 5163e12c5d1SDavid du Colombier Ibuf *b; 5173e12c5d1SDavid du Colombier char buf[MAXFDATA]; 5183e12c5d1SDavid du Colombier 5193e12c5d1SDavid du Colombier PREFACE(mf); 5203e12c5d1SDavid du Colombier if(mf->qid.path & CHDIR){ 5213e12c5d1SDavid du Colombier delegate(); 5223e12c5d1SDavid du Colombier return; 5233e12c5d1SDavid du Colombier } 5243e12c5d1SDavid du Colombier 5253e12c5d1SDavid du Colombier memmove(buf, c.thdr.data, c.thdr.count); 5263e12c5d1SDavid du Colombier if(delegate() < 0) 5273e12c5d1SDavid du Colombier return; 5283e12c5d1SDavid du Colombier 5293e12c5d1SDavid du Colombier b = iget(&ic, mf->qid); 5303e12c5d1SDavid du Colombier if(b == 0) 5313e12c5d1SDavid du Colombier return; 5323e12c5d1SDavid du Colombier mf->qid.vers++; 5333e12c5d1SDavid du Colombier if(fwrite(&ic, b, buf, c.thdr.offset, c.thdr.count) == c.thdr.count) 5343e12c5d1SDavid du Colombier iinc(&ic, b); 5353e12c5d1SDavid du Colombier } 5363e12c5d1SDavid du Colombier 5373e12c5d1SDavid du Colombier void 5383e12c5d1SDavid du Colombier rstat(Mfile *mf) 5393e12c5d1SDavid du Colombier { 5403e12c5d1SDavid du Colombier PREFACE(mf); 5413e12c5d1SDavid du Colombier delegate(); 5423e12c5d1SDavid du Colombier } 5433e12c5d1SDavid du Colombier 5443e12c5d1SDavid du Colombier void 5453e12c5d1SDavid du Colombier rwstat(Mfile *mf) 5463e12c5d1SDavid du Colombier { 5473e12c5d1SDavid du Colombier PREFACE(mf); 5483e12c5d1SDavid du Colombier delegate(); 5493e12c5d1SDavid du Colombier } 5503e12c5d1SDavid du Colombier 5513e12c5d1SDavid du Colombier void 5523e12c5d1SDavid du Colombier error(char *s) 5533e12c5d1SDavid du Colombier { 5543e12c5d1SDavid du Colombier fprint(2, "cfs: %s: ", s); 5553e12c5d1SDavid du Colombier perror(""); 5563e12c5d1SDavid du Colombier exits(s); 5573e12c5d1SDavid du Colombier } 5583e12c5d1SDavid du Colombier 5593e12c5d1SDavid du Colombier void 5603e12c5d1SDavid du Colombier warning(char *s) 5613e12c5d1SDavid du Colombier { 5623e12c5d1SDavid du Colombier char buf[ERRLEN]; 5633e12c5d1SDavid du Colombier 5643e12c5d1SDavid du Colombier errstr(buf); 5653e12c5d1SDavid du Colombier fprint(2, "cfs: %s: %s\n", s, buf); 5663e12c5d1SDavid du Colombier if(strstr(buf, "illegal network address")) 5673e12c5d1SDavid du Colombier exits("death"); 5683e12c5d1SDavid du Colombier } 5693e12c5d1SDavid du Colombier 5703e12c5d1SDavid du Colombier /* 5713e12c5d1SDavid du Colombier * send a reply to the client 5723e12c5d1SDavid du Colombier */ 5733e12c5d1SDavid du Colombier void 5743e12c5d1SDavid du Colombier sendreply(char *err) 5753e12c5d1SDavid du Colombier { 5763e12c5d1SDavid du Colombier 5773e12c5d1SDavid du Colombier if(err){ 5783e12c5d1SDavid du Colombier c.rhdr.type = Rerror; 5793e12c5d1SDavid du Colombier strncpy(c.rhdr.ename, err, ERRLEN); 5803e12c5d1SDavid du Colombier }else{ 5813e12c5d1SDavid du Colombier c.rhdr.type = c.thdr.type+1; 5823e12c5d1SDavid du Colombier c.rhdr.fid = c.thdr.fid; 5833e12c5d1SDavid du Colombier } 5843e12c5d1SDavid du Colombier c.rhdr.tag = c.thdr.tag; 5853e12c5d1SDavid du Colombier sendmsg(&c, &c.rhdr); 5863e12c5d1SDavid du Colombier } 5873e12c5d1SDavid du Colombier 5883e12c5d1SDavid du Colombier /* 5893e12c5d1SDavid du Colombier * send a request to the server, get the reply, and send that to 5903e12c5d1SDavid du Colombier * the client 5913e12c5d1SDavid du Colombier */ 5923e12c5d1SDavid du Colombier int 5933e12c5d1SDavid du Colombier delegate(void) 5943e12c5d1SDavid du Colombier { 5953e12c5d1SDavid du Colombier sendmsg(&s, &c.thdr); 5963e12c5d1SDavid du Colombier rcvmsg(&s, &s.rhdr); 5973e12c5d1SDavid du Colombier sendmsg(&c, &s.rhdr); 5983e12c5d1SDavid du Colombier return c.thdr.type+1 == s.rhdr.type ? 0 : -1; 5993e12c5d1SDavid du Colombier } 6003e12c5d1SDavid du Colombier 6013e12c5d1SDavid du Colombier /* 6023e12c5d1SDavid du Colombier * send a request to the server and get a reply 6033e12c5d1SDavid du Colombier */ 6043e12c5d1SDavid du Colombier int 6053e12c5d1SDavid du Colombier askserver(void) 6063e12c5d1SDavid du Colombier { 6073e12c5d1SDavid du Colombier s.thdr.tag = c.thdr.tag; 6083e12c5d1SDavid du Colombier sendmsg(&s, &s.thdr); 6093e12c5d1SDavid du Colombier rcvmsg(&s, &s.rhdr); 6103e12c5d1SDavid du Colombier return s.thdr.type+1 == s.rhdr.type ? 0 : -1; 6113e12c5d1SDavid du Colombier } 6123e12c5d1SDavid du Colombier 6133e12c5d1SDavid du Colombier /* 6143e12c5d1SDavid du Colombier * send/receive messages with logging 6153e12c5d1SDavid du Colombier */ 6163e12c5d1SDavid du Colombier void 6173e12c5d1SDavid du Colombier sendmsg(P9fs *p, Fcall *f) 6183e12c5d1SDavid du Colombier { 6193e12c5d1SDavid du Colombier DPRINT(2, "->%s: %d %s on %d\n", p->name, f->type, 6203e12c5d1SDavid du Colombier mname[f->type]? mname[f->type] : "mystery", 6213e12c5d1SDavid du Colombier f->fid); 6223e12c5d1SDavid du Colombier 6233e12c5d1SDavid du Colombier p->len = convS2M(f, datasnd); 624*219b2ee8SDavid du Colombier if(write9p(p->fd[1], datasnd, p->len)!=p->len) 6253e12c5d1SDavid du Colombier error("smdmsg"); 6263e12c5d1SDavid du Colombier } 6273e12c5d1SDavid du Colombier 6283e12c5d1SDavid du Colombier void 6293e12c5d1SDavid du Colombier dump(uchar *p, int len) 6303e12c5d1SDavid du Colombier { 6313e12c5d1SDavid du Colombier fprint(2, "%d bytes", len); 6323e12c5d1SDavid du Colombier while(len > 0){ 6333e12c5d1SDavid du Colombier fprint(2, " %.2ux", *p++); 6343e12c5d1SDavid du Colombier len--; 6353e12c5d1SDavid du Colombier } 6363e12c5d1SDavid du Colombier fprint(2, "\n"); 6373e12c5d1SDavid du Colombier } 6383e12c5d1SDavid du Colombier 6393e12c5d1SDavid du Colombier void 6403e12c5d1SDavid du Colombier rcvmsg(P9fs *p, Fcall *f) 6413e12c5d1SDavid du Colombier { 6423e12c5d1SDavid du Colombier int olen; 6433e12c5d1SDavid du Colombier 6443e12c5d1SDavid du Colombier olen = p->len; 6453e12c5d1SDavid du Colombier retry: 646*219b2ee8SDavid du Colombier p->len = read9p(p->fd[0], datarcv, sizeof(datarcv)); 6473e12c5d1SDavid du Colombier if(p->len <= 0) 6483e12c5d1SDavid du Colombier error("rcvmsg"); 6493e12c5d1SDavid du Colombier if(p->len==2 && datarcv[0]=='O' && datarcv[1]=='K') 6503e12c5d1SDavid du Colombier goto retry; 6513e12c5d1SDavid du Colombier if(convM2S(datarcv, f, p->len) == 0) 6523e12c5d1SDavid du Colombier error("rcvmsg format error"); 6533e12c5d1SDavid du Colombier if(f->type != Rauth && (f->fid<0 || Nfid<=f->fid)){ 6543e12c5d1SDavid du Colombier fprint(2, "<-%s: %d %s on %d\n", p->name, f->type, 6553e12c5d1SDavid du Colombier mname[f->type]? mname[f->type] : "mystery", 6563e12c5d1SDavid du Colombier f->fid); 6573e12c5d1SDavid du Colombier dump((uchar*)datasnd, olen); 6583e12c5d1SDavid du Colombier dump((uchar*)datarcv, p->len); 6593e12c5d1SDavid du Colombier error("rcvmsg fid out of range"); 6603e12c5d1SDavid du Colombier } 6613e12c5d1SDavid du Colombier DPRINT(2, "<-%s: %d %s on %d\n", p->name, f->type, 6623e12c5d1SDavid du Colombier mname[f->type]? mname[f->type] : "mystery", 6633e12c5d1SDavid du Colombier f->fid); 6643e12c5d1SDavid du Colombier } 665