19a747e4fSDavid du Colombier /* already in plan9.h #include <sys/types.h> *//* for struct passwd, struct group, struct stat ... */ 2*f5736e95SDavid du Colombier /* plan9.h is first to get the large file support definitions as early as possible */ 3*f5736e95SDavid du Colombier #include <plan9.h> 4*f5736e95SDavid du Colombier 59a747e4fSDavid du Colombier #include <sys/stat.h> /* for stat, umask */ 69a747e4fSDavid du Colombier #include <stdlib.h> /* for malloc */ 79a747e4fSDavid du Colombier #include <string.h> /* for strcpy, memmove */ 89a747e4fSDavid du Colombier #include <pwd.h> /* for getpwnam, getpwuid */ 99a747e4fSDavid du Colombier #include <grp.h> /* for getgrnam, getgrgid */ 109a747e4fSDavid du Colombier #include <unistd.h> /* for gethostname, pread, pwrite, read, write */ 119a747e4fSDavid du Colombier #include <utime.h> /* for utime */ 129a747e4fSDavid du Colombier #include <dirent.h> /* for readdir */ 139a747e4fSDavid du Colombier #include <errno.h> /* for errno */ 149a747e4fSDavid du Colombier #include <stdio.h> /* for remove [sic] */ 159a747e4fSDavid du Colombier #include <fcntl.h> /* for O_RDONLY, etc. */ 163e12c5d1SDavid du Colombier 179a747e4fSDavid du Colombier #include <sys/socket.h> /* various networking crud */ 18219b2ee8SDavid du Colombier #include <netinet/in.h> 19219b2ee8SDavid du Colombier #include <netdb.h> 209a747e4fSDavid du Colombier 219a747e4fSDavid du Colombier #include <fcall.h> 229a747e4fSDavid du Colombier #include <oldfcall.h> 239a747e4fSDavid du Colombier #include <u9fs.h> 249a747e4fSDavid du Colombier 259a747e4fSDavid du Colombier /* #ifndef because can be given in makefile */ 269a747e4fSDavid du Colombier #ifndef DEFAULTLOG 279a747e4fSDavid du Colombier #define DEFAULTLOG "/tmp/u9fs.log" 283e12c5d1SDavid du Colombier #endif 293e12c5d1SDavid du Colombier 309a747e4fSDavid du Colombier char *logfile = DEFAULTLOG; 313e12c5d1SDavid du Colombier 329a747e4fSDavid du Colombier #define S_ISSPECIAL(m) (S_ISCHR(m) || S_ISBLK(m) || S_ISFIFO(m)) 339a747e4fSDavid du Colombier 349a747e4fSDavid du Colombier enum { 359a747e4fSDavid du Colombier Tdot = 1, 369a747e4fSDavid du Colombier Tdotdot 373e12c5d1SDavid du Colombier }; 383e12c5d1SDavid du Colombier 399a747e4fSDavid du Colombier enum { 409a747e4fSDavid du Colombier P9P1, 419a747e4fSDavid du Colombier P9P2000 423e12c5d1SDavid du Colombier }; 433e12c5d1SDavid du Colombier 449a747e4fSDavid du Colombier typedef struct User User; 459a747e4fSDavid du Colombier struct User { 463e12c5d1SDavid du Colombier int id; 479a747e4fSDavid du Colombier gid_t defaultgid; 483e12c5d1SDavid du Colombier char *name; 499a747e4fSDavid du Colombier char **mem; /* group members */ 507dd7cddfSDavid du Colombier int nmem; 519a747e4fSDavid du Colombier User *next; 523e12c5d1SDavid du Colombier }; 533e12c5d1SDavid du Colombier 549a747e4fSDavid du Colombier struct Fid { 559a747e4fSDavid du Colombier int fid; 569a747e4fSDavid du Colombier char *path; 579a747e4fSDavid du Colombier struct stat st; 589a747e4fSDavid du Colombier User *u; 599a747e4fSDavid du Colombier int omode; 609a747e4fSDavid du Colombier DIR *dir; 619a747e4fSDavid du Colombier int diroffset; 629a747e4fSDavid du Colombier int fd; 639a747e4fSDavid du Colombier struct dirent *dirent; 649a747e4fSDavid du Colombier Fid *next; 659a747e4fSDavid du Colombier Fid *prev; 6650a9bdd4SDavid du Colombier int auth; 6750a9bdd4SDavid du Colombier void *authmagic; 689a747e4fSDavid du Colombier }; 693e12c5d1SDavid du Colombier 709a747e4fSDavid du Colombier void* emalloc(size_t); 719a747e4fSDavid du Colombier void* erealloc(void*, size_t); 723e12c5d1SDavid du Colombier char* estrdup(char*); 739a747e4fSDavid du Colombier char* estrpath(char*, char*); 749a747e4fSDavid du Colombier void sysfatal(char*, ...); 759a747e4fSDavid du Colombier int okuser(char*); 763e12c5d1SDavid du Colombier 779a747e4fSDavid du Colombier void rversion(Fcall*, Fcall*); 789a747e4fSDavid du Colombier void rauth(Fcall*, Fcall*); 799a747e4fSDavid du Colombier void rattach(Fcall*, Fcall*); 809a747e4fSDavid du Colombier void rflush(Fcall*, Fcall*); 819a747e4fSDavid du Colombier void rclone(Fcall*, Fcall*); 829a747e4fSDavid du Colombier void rwalk(Fcall*, Fcall*); 839a747e4fSDavid du Colombier void ropen(Fcall*, Fcall*); 849a747e4fSDavid du Colombier void rcreate(Fcall*, Fcall*); 859a747e4fSDavid du Colombier void rread(Fcall*, Fcall*); 869a747e4fSDavid du Colombier void rwrite(Fcall*, Fcall*); 879a747e4fSDavid du Colombier void rclunk(Fcall*, Fcall*); 889a747e4fSDavid du Colombier void rstat(Fcall*, Fcall*); 899a747e4fSDavid du Colombier void rwstat(Fcall*, Fcall*); 909a747e4fSDavid du Colombier void rclwalk(Fcall*, Fcall*); 919a747e4fSDavid du Colombier void rremove(Fcall*, Fcall*); 929a747e4fSDavid du Colombier 939a747e4fSDavid du Colombier User* uname2user(char*); 949a747e4fSDavid du Colombier User* gname2user(char*); 959a747e4fSDavid du Colombier User* uid2user(int); 969a747e4fSDavid du Colombier User* gid2user(int); 979a747e4fSDavid du Colombier 989a747e4fSDavid du Colombier Fid* newfid(int, char**); 9950a9bdd4SDavid du Colombier Fid* oldfidex(int, int, char**); 1009a747e4fSDavid du Colombier Fid* oldfid(int, char**); 1019a747e4fSDavid du Colombier int fidstat(Fid*, char**); 1029a747e4fSDavid du Colombier void freefid(Fid*); 1039a747e4fSDavid du Colombier 1049a747e4fSDavid du Colombier int userchange(User*, char**); 1059a747e4fSDavid du Colombier int userwalk(User*, char**, char*, Qid*, char**); 1069a747e4fSDavid du Colombier int useropen(Fid*, int, char**); 1079a747e4fSDavid du Colombier int usercreate(Fid*, char*, int, long, char**); 1089a747e4fSDavid du Colombier int userremove(Fid*, char**); 1099a747e4fSDavid du Colombier int userperm(User*, char*, int, int); 1109a747e4fSDavid du Colombier int useringroup(User*, User*); 1119a747e4fSDavid du Colombier 1129a747e4fSDavid du Colombier Qid stat2qid(struct stat*); 1139a747e4fSDavid du Colombier 1149a747e4fSDavid du Colombier void getfcallold(int, Fcall*, int); 1159a747e4fSDavid du Colombier void putfcallold(int, Fcall*); 1163e12c5d1SDavid du Colombier 1173e12c5d1SDavid du Colombier char Eauth[] = "authentication failed"; 1183e12c5d1SDavid du Colombier char Ebadfid[] = "fid unknown or out of range"; 1199a747e4fSDavid du Colombier char Ebadoffset[] = "bad offset in directory read"; 1209a747e4fSDavid du Colombier char Ebadusefid[] = "bad use of fid"; 1219a747e4fSDavid du Colombier char Edirchange[] = "wstat can't convert between files and directories"; 1229a747e4fSDavid du Colombier char Eexist[] = "file or directory already exists"; 1233e12c5d1SDavid du Colombier char Efidactive[] = "fid already in use"; 1249a747e4fSDavid du Colombier char Enotdir[] = "not a directory"; 1259a747e4fSDavid du Colombier char Enotingroup[] = "not a member of proposed group"; 1269a747e4fSDavid du Colombier char Enotowner[] = "only owner can change group in wstat"; 1279a747e4fSDavid du Colombier char Eperm[] = "permission denied"; 1283e12c5d1SDavid du Colombier char Especial0[] = "already attached without access to special files"; 1293e12c5d1SDavid du Colombier char Especial1[] = "already attached with access to special files"; 1309a747e4fSDavid du Colombier char Especial[] = "no access to special file"; 1313e12c5d1SDavid du Colombier char Etoolarge[] = "i/o count too large"; 1329a747e4fSDavid du Colombier char Eunknowngroup[] = "unknown group"; 1339a747e4fSDavid du Colombier char Eunknownuser[] = "unknown user"; 1349a747e4fSDavid du Colombier char Ewstatbuffer[] = "bogus wstat buffer"; 1359a747e4fSDavid du Colombier 1369a747e4fSDavid du Colombier ulong msize = IOHDRSZ+8192; 1379a747e4fSDavid du Colombier uchar* rxbuf; 1389a747e4fSDavid du Colombier uchar* txbuf; 1399a747e4fSDavid du Colombier void* databuf; 1409a747e4fSDavid du Colombier int connected; 1419a747e4fSDavid du Colombier int devallowed; 1429a747e4fSDavid du Colombier char* autharg; 1439a747e4fSDavid du Colombier char* defaultuser; 1449a747e4fSDavid du Colombier char hostname[256]; 1459a747e4fSDavid du Colombier char remotehostname[256]; 1469a747e4fSDavid du Colombier int chatty9p = 0; 1479a747e4fSDavid du Colombier int network = 1; 1489a747e4fSDavid du Colombier int old9p = -1; 1499a747e4fSDavid du Colombier int authed; 1509a747e4fSDavid du Colombier User* none; 1519a747e4fSDavid du Colombier 1529a747e4fSDavid du Colombier Auth *authmethods[] = { /* first is default */ 1539a747e4fSDavid du Colombier &authrhosts, 15450a9bdd4SDavid du Colombier &authp9any, 1559a747e4fSDavid du Colombier &authnone, 1569a747e4fSDavid du Colombier }; 1579a747e4fSDavid du Colombier 1589a747e4fSDavid du Colombier Auth *auth; 1593e12c5d1SDavid du Colombier 1607dd7cddfSDavid du Colombier void 1619a747e4fSDavid du Colombier getfcallnew(int fd, Fcall *fc, int have) 1627dd7cddfSDavid du Colombier { 1639a747e4fSDavid du Colombier int len; 1649a747e4fSDavid du Colombier 1659a747e4fSDavid du Colombier if(have > BIT32SZ) 1669a747e4fSDavid du Colombier sysfatal("cannot happen"); 1679a747e4fSDavid du Colombier 1689a747e4fSDavid du Colombier if(have < BIT32SZ && readn(fd, rxbuf+have, BIT32SZ-have) != BIT32SZ-have) 1699a747e4fSDavid du Colombier sysfatal("couldn't read message"); 1709a747e4fSDavid du Colombier 1719a747e4fSDavid du Colombier len = GBIT32(rxbuf); 1729a747e4fSDavid du Colombier if(len <= BIT32SZ) 1739a747e4fSDavid du Colombier sysfatal("bogus message"); 1749a747e4fSDavid du Colombier 1759a747e4fSDavid du Colombier len -= BIT32SZ; 1769a747e4fSDavid du Colombier if(readn(fd, rxbuf+BIT32SZ, len) != len) 1779a747e4fSDavid du Colombier sysfatal("short message"); 1789a747e4fSDavid du Colombier 1799a747e4fSDavid du Colombier if(convM2S(rxbuf, len+BIT32SZ, fc) != len+BIT32SZ) 1809a747e4fSDavid du Colombier sysfatal("badly sized message type %d", rxbuf[0]); 1819a747e4fSDavid du Colombier } 1829a747e4fSDavid du Colombier 1839a747e4fSDavid du Colombier void 1849a747e4fSDavid du Colombier getfcallold(int fd, Fcall *fc, int have) 1859a747e4fSDavid du Colombier { 1869a747e4fSDavid du Colombier int len, n; 1879a747e4fSDavid du Colombier 1889a747e4fSDavid du Colombier if(have > 3) 1899a747e4fSDavid du Colombier sysfatal("cannot happen"); 1909a747e4fSDavid du Colombier 1919a747e4fSDavid du Colombier if(have < 3 && readn(fd, rxbuf, 3-have) != 3-have) 1929a747e4fSDavid du Colombier sysfatal("couldn't read message"); 1939a747e4fSDavid du Colombier 1949a747e4fSDavid du Colombier len = oldhdrsize(rxbuf[0]); 1959a747e4fSDavid du Colombier if(len < 3) 1969a747e4fSDavid du Colombier sysfatal("bad message %d", rxbuf[0]); 1979a747e4fSDavid du Colombier if(len > 3 && readn(fd, rxbuf+3, len-3) != len-3) 1989a747e4fSDavid du Colombier sysfatal("couldn't read message"); 1999a747e4fSDavid du Colombier 2009a747e4fSDavid du Colombier n = iosize(rxbuf); 2019a747e4fSDavid du Colombier if(readn(fd, rxbuf+len, n) != n) 2029a747e4fSDavid du Colombier sysfatal("couldn't read message"); 2039a747e4fSDavid du Colombier len += n; 2049a747e4fSDavid du Colombier 2059a747e4fSDavid du Colombier if(convM2Sold(rxbuf, len, fc) != len) 2069a747e4fSDavid du Colombier sysfatal("badly sized message type %d", rxbuf[0]); 2079a747e4fSDavid du Colombier } 2089a747e4fSDavid du Colombier 2099a747e4fSDavid du Colombier void 2109a747e4fSDavid du Colombier putfcallnew(int wfd, Fcall *tx) 2119a747e4fSDavid du Colombier { 2129a747e4fSDavid du Colombier uint n; 2139a747e4fSDavid du Colombier 2149a747e4fSDavid du Colombier if((n = convS2M(tx, txbuf, msize)) == 0) 2159a747e4fSDavid du Colombier sysfatal("couldn't format message type %d", tx->type); 2169a747e4fSDavid du Colombier if(write(wfd, txbuf, n) != n) 2179a747e4fSDavid du Colombier sysfatal("couldn't send message"); 2189a747e4fSDavid du Colombier } 2199a747e4fSDavid du Colombier 2209a747e4fSDavid du Colombier void 2219a747e4fSDavid du Colombier putfcallold(int wfd, Fcall *tx) 2229a747e4fSDavid du Colombier { 2239a747e4fSDavid du Colombier uint n; 2249a747e4fSDavid du Colombier 2259a747e4fSDavid du Colombier if((n = convS2Mold(tx, txbuf, msize)) == 0) 2269a747e4fSDavid du Colombier sysfatal("couldn't format message type %d", tx->type); 2279a747e4fSDavid du Colombier if(write(wfd, txbuf, n) != n) 2289a747e4fSDavid du Colombier sysfatal("couldn't send message"); 2299a747e4fSDavid du Colombier } 2309a747e4fSDavid du Colombier 2319a747e4fSDavid du Colombier void 2329a747e4fSDavid du Colombier getfcall(int fd, Fcall *fc) 2339a747e4fSDavid du Colombier { 2349a747e4fSDavid du Colombier if(old9p == 1){ 2359a747e4fSDavid du Colombier getfcallold(fd, fc, 0); 2369a747e4fSDavid du Colombier return; 2379a747e4fSDavid du Colombier } 2389a747e4fSDavid du Colombier if(old9p == 0){ 2399a747e4fSDavid du Colombier getfcallnew(fd, fc, 0); 2409a747e4fSDavid du Colombier return; 2419a747e4fSDavid du Colombier } 2429a747e4fSDavid du Colombier 2439a747e4fSDavid du Colombier /* auto-detect */ 2449a747e4fSDavid du Colombier 2459a747e4fSDavid du Colombier if(readn(fd, rxbuf, 3) != 3) 2469a747e4fSDavid du Colombier sysfatal("couldn't read message"); 2479a747e4fSDavid du Colombier 2489a747e4fSDavid du Colombier /* is it an old (9P1) message? */ 2499a747e4fSDavid du Colombier if(50 <= rxbuf[0] && rxbuf[0] <= 87 && (rxbuf[0]&1)==0 && GBIT16(rxbuf+1) == 0xFFFF){ 2509a747e4fSDavid du Colombier old9p = 1; 2519a747e4fSDavid du Colombier getfcallold(fd, fc, 3); 2529a747e4fSDavid du Colombier return; 2539a747e4fSDavid du Colombier } 2549a747e4fSDavid du Colombier 2559a747e4fSDavid du Colombier getfcallnew(fd, fc, 3); 2569a747e4fSDavid du Colombier old9p = 0; 2579a747e4fSDavid du Colombier } 2589a747e4fSDavid du Colombier 2599a747e4fSDavid du Colombier void 2609a747e4fSDavid du Colombier seterror(Fcall *f, char *error) 2619a747e4fSDavid du Colombier { 2629a747e4fSDavid du Colombier f->type = Rerror; 2639a747e4fSDavid du Colombier f->ename = error ? error : "programmer error"; 2647dd7cddfSDavid du Colombier } 2657dd7cddfSDavid du Colombier 2663e12c5d1SDavid du Colombier int 2679a747e4fSDavid du Colombier isowner(User *u, Fid *f) 2683e12c5d1SDavid du Colombier { 2699a747e4fSDavid du Colombier return u->id == f->st.st_uid; 2703e12c5d1SDavid du Colombier } 2713e12c5d1SDavid du Colombier 2723e12c5d1SDavid du Colombier void 2739a747e4fSDavid du Colombier serve(int rfd, int wfd) 2743e12c5d1SDavid du Colombier { 2759a747e4fSDavid du Colombier Fcall rx, tx; 2763e12c5d1SDavid du Colombier 2773e12c5d1SDavid du Colombier for(;;){ 2789a747e4fSDavid du Colombier getfcall(rfd, &rx); 2793e12c5d1SDavid du Colombier 2809a747e4fSDavid du Colombier if(chatty9p) 2819a747e4fSDavid du Colombier fprint(2, "<- %F\n", &rx); 2829a747e4fSDavid du Colombier 2839a747e4fSDavid du Colombier memset(&tx, 0, sizeof tx); 2849a747e4fSDavid du Colombier tx.type = rx.type+1; 2859a747e4fSDavid du Colombier tx.tag = rx.tag; 2869a747e4fSDavid du Colombier switch(rx.type){ 2879a747e4fSDavid du Colombier case Tflush: 2883e12c5d1SDavid du Colombier break; 2899a747e4fSDavid du Colombier case Tversion: 2909a747e4fSDavid du Colombier rversion(&rx, &tx); 2919a747e4fSDavid du Colombier break; 2929a747e4fSDavid du Colombier case Tauth: 2939a747e4fSDavid du Colombier rauth(&rx, &tx); 2943e12c5d1SDavid du Colombier break; 2953e12c5d1SDavid du Colombier case Tattach: 2969a747e4fSDavid du Colombier rattach(&rx, &tx); 2973e12c5d1SDavid du Colombier break; 2983e12c5d1SDavid du Colombier case Twalk: 2999a747e4fSDavid du Colombier rwalk(&rx, &tx); 3003e12c5d1SDavid du Colombier break; 3013e12c5d1SDavid du Colombier case Tstat: 3029a747e4fSDavid du Colombier tx.stat = databuf; 3039a747e4fSDavid du Colombier rstat(&rx, &tx); 3043e12c5d1SDavid du Colombier break; 3053e12c5d1SDavid du Colombier case Twstat: 3069a747e4fSDavid du Colombier rwstat(&rx, &tx); 3073e12c5d1SDavid du Colombier break; 3083e12c5d1SDavid du Colombier case Topen: 3099a747e4fSDavid du Colombier ropen(&rx, &tx); 3103e12c5d1SDavid du Colombier break; 3113e12c5d1SDavid du Colombier case Tcreate: 3129a747e4fSDavid du Colombier rcreate(&rx, &tx); 3133e12c5d1SDavid du Colombier break; 3143e12c5d1SDavid du Colombier case Tread: 3159a747e4fSDavid du Colombier tx.data = databuf; 3169a747e4fSDavid du Colombier rread(&rx, &tx); 3173e12c5d1SDavid du Colombier break; 3183e12c5d1SDavid du Colombier case Twrite: 3199a747e4fSDavid du Colombier rwrite(&rx, &tx); 3203e12c5d1SDavid du Colombier break; 3213e12c5d1SDavid du Colombier case Tclunk: 3229a747e4fSDavid du Colombier rclunk(&rx, &tx); 3233e12c5d1SDavid du Colombier break; 3243e12c5d1SDavid du Colombier case Tremove: 3259a747e4fSDavid du Colombier rremove(&rx, &tx); 3263e12c5d1SDavid du Colombier break; 3273e12c5d1SDavid du Colombier default: 3289a747e4fSDavid du Colombier fprint(2, "unknown message %F\n", &rx); 3299a747e4fSDavid du Colombier seterror(&tx, "bad message"); 3309a747e4fSDavid du Colombier break; 3313e12c5d1SDavid du Colombier } 3329a747e4fSDavid du Colombier 3339a747e4fSDavid du Colombier if(chatty9p) 3349a747e4fSDavid du Colombier fprint(2, "-> %F\n", &tx); 3359a747e4fSDavid du Colombier 3369a747e4fSDavid du Colombier (old9p ? putfcallold : putfcallnew)(wfd, &tx); 3379a747e4fSDavid du Colombier } 3383e12c5d1SDavid du Colombier } 3393e12c5d1SDavid du Colombier 3403e12c5d1SDavid du Colombier void 3419a747e4fSDavid du Colombier rversion(Fcall *rx, Fcall *tx) 3423e12c5d1SDavid du Colombier { 3439a747e4fSDavid du Colombier if(msize > rx->msize) 3449a747e4fSDavid du Colombier msize = rx->msize; 3459a747e4fSDavid du Colombier tx->msize = msize; 3469a747e4fSDavid du Colombier if(strncmp(rx->version, "9P", 2) != 0) 3479a747e4fSDavid du Colombier tx->version = "unknown"; 3489a747e4fSDavid du Colombier else 3499a747e4fSDavid du Colombier tx->version = "9P2000"; 3503e12c5d1SDavid du Colombier } 3513e12c5d1SDavid du Colombier 3523e12c5d1SDavid du Colombier void 3539a747e4fSDavid du Colombier rauth(Fcall *rx, Fcall *tx) 3543e12c5d1SDavid du Colombier { 3559a747e4fSDavid du Colombier char *e; 3563e12c5d1SDavid du Colombier 3579a747e4fSDavid du Colombier if((e = auth->auth(rx, tx)) != nil) 3589a747e4fSDavid du Colombier seterror(tx, e); 3593e12c5d1SDavid du Colombier } 3609a747e4fSDavid du Colombier 3619a747e4fSDavid du Colombier void 3629a747e4fSDavid du Colombier rattach(Fcall *rx, Fcall *tx) 3639a747e4fSDavid du Colombier { 3649a747e4fSDavid du Colombier char *e; 3659a747e4fSDavid du Colombier Fid *fid; 3669a747e4fSDavid du Colombier User *u; 3679a747e4fSDavid du Colombier 3689a747e4fSDavid du Colombier if(rx->aname == nil) 3699a747e4fSDavid du Colombier rx->aname = ""; 3709a747e4fSDavid du Colombier 3719a747e4fSDavid du Colombier if(strcmp(rx->aname, "device") == 0){ 3729a747e4fSDavid du Colombier if(connected && !devallowed){ 3739a747e4fSDavid du Colombier seterror(tx, Especial0); 3749a747e4fSDavid du Colombier return; 3759a747e4fSDavid du Colombier } 3763e12c5d1SDavid du Colombier devallowed = 1; 3773e12c5d1SDavid du Colombier }else{ 3789a747e4fSDavid du Colombier if(connected && devallowed){ 3799a747e4fSDavid du Colombier seterror(tx, Especial1); 3809a747e4fSDavid du Colombier return; 3813e12c5d1SDavid du Colombier } 3829a747e4fSDavid du Colombier } 3839a747e4fSDavid du Colombier 3849a747e4fSDavid du Colombier if(strcmp(rx->uname, "none") == 0){ 3859a747e4fSDavid du Colombier if(authed == 0){ 3869a747e4fSDavid du Colombier seterror(tx, Eauth); 3879a747e4fSDavid du Colombier return; 3889a747e4fSDavid du Colombier } 3899a747e4fSDavid du Colombier } else { 3909a747e4fSDavid du Colombier if((e = auth->attach(rx, tx)) != nil){ 3919a747e4fSDavid du Colombier seterror(tx, e); 3929a747e4fSDavid du Colombier return; 3939a747e4fSDavid du Colombier } 3949a747e4fSDavid du Colombier authed++; 3959a747e4fSDavid du Colombier } 3969a747e4fSDavid du Colombier 3979a747e4fSDavid du Colombier if((fid = newfid(rx->fid, &e)) == nil){ 3989a747e4fSDavid du Colombier seterror(tx, e); 3999a747e4fSDavid du Colombier return; 4009a747e4fSDavid du Colombier } 4019a747e4fSDavid du Colombier fid->path = estrdup("/"); 4029a747e4fSDavid du Colombier if(fidstat(fid, &e) < 0){ 4039a747e4fSDavid du Colombier seterror(tx, e); 4049a747e4fSDavid du Colombier freefid(fid); 4059a747e4fSDavid du Colombier return; 4069a747e4fSDavid du Colombier } 4079a747e4fSDavid du Colombier 4089a747e4fSDavid du Colombier if(defaultuser) 4099a747e4fSDavid du Colombier rx->uname = defaultuser; 4109a747e4fSDavid du Colombier 411fa1160edSDavid du Colombier if((u = uname2user(rx->uname)) == nil 412fa1160edSDavid du Colombier || (!defaultuser && u->id == 0)){ 4139a747e4fSDavid du Colombier /* we don't know anyone named root... */ 4149a747e4fSDavid du Colombier seterror(tx, Eunknownuser); 4159a747e4fSDavid du Colombier freefid(fid); 4169a747e4fSDavid du Colombier return; 4179a747e4fSDavid du Colombier } 4189a747e4fSDavid du Colombier 4199a747e4fSDavid du Colombier fid->u = u; 4209a747e4fSDavid du Colombier tx->qid = stat2qid(&fid->st); 4219a747e4fSDavid du Colombier return; 4223e12c5d1SDavid du Colombier } 4233e12c5d1SDavid du Colombier 4243e12c5d1SDavid du Colombier void 4259a747e4fSDavid du Colombier rwalk(Fcall *rx, Fcall *tx) 4263e12c5d1SDavid du Colombier { 4279a747e4fSDavid du Colombier int i; 4289a747e4fSDavid du Colombier char *path, *e; 4299a747e4fSDavid du Colombier Fid *fid, *nfid; 4303e12c5d1SDavid du Colombier 4319a747e4fSDavid du Colombier e = nil; 4329a747e4fSDavid du Colombier if((fid = oldfid(rx->fid, &e)) == nil){ 4339a747e4fSDavid du Colombier seterror(tx, e); 4349a747e4fSDavid du Colombier return; 4353e12c5d1SDavid du Colombier } 4363e12c5d1SDavid du Colombier 4379a747e4fSDavid du Colombier if(fid->omode != -1){ 4389a747e4fSDavid du Colombier seterror(tx, Ebadusefid); 4399a747e4fSDavid du Colombier return; 4403e12c5d1SDavid du Colombier } 4413e12c5d1SDavid du Colombier 4429a747e4fSDavid du Colombier if(fidstat(fid, &e) < 0){ 4439a747e4fSDavid du Colombier seterror(tx, e); 4449a747e4fSDavid du Colombier return; 4459a747e4fSDavid du Colombier } 4463e12c5d1SDavid du Colombier 4479a747e4fSDavid du Colombier if(!S_ISDIR(fid->st.st_mode) && rx->nwname){ 4489a747e4fSDavid du Colombier seterror(tx, Enotdir); 4499a747e4fSDavid du Colombier return; 4509a747e4fSDavid du Colombier } 4519a747e4fSDavid du Colombier 4529a747e4fSDavid du Colombier nfid = nil; 4539a747e4fSDavid du Colombier if(rx->newfid != rx->fid && (nfid = newfid(rx->newfid, &e)) == nil){ 4549a747e4fSDavid du Colombier seterror(tx, e); 4559a747e4fSDavid du Colombier return; 4569a747e4fSDavid du Colombier } 4579a747e4fSDavid du Colombier 4589a747e4fSDavid du Colombier path = estrdup(fid->path); 4599a747e4fSDavid du Colombier e = nil; 4609a747e4fSDavid du Colombier for(i=0; i<rx->nwname; i++) 4619a747e4fSDavid du Colombier if(userwalk(fid->u, &path, rx->wname[i], &tx->wqid[i], &e) < 0) 4623e12c5d1SDavid du Colombier break; 4633e12c5d1SDavid du Colombier 4649a747e4fSDavid du Colombier if(i == rx->nwname){ /* successful clone or walk */ 4659a747e4fSDavid du Colombier tx->nwqid = i; 4669a747e4fSDavid du Colombier if(nfid){ 4679a747e4fSDavid du Colombier nfid->path = path; 4689a747e4fSDavid du Colombier nfid->u = fid->u; 4693e12c5d1SDavid du Colombier }else{ 4709a747e4fSDavid du Colombier free(fid->path); 4719a747e4fSDavid du Colombier fid->path = path; 4723e12c5d1SDavid du Colombier } 4739a747e4fSDavid du Colombier }else{ 4749a747e4fSDavid du Colombier if(i > 0) /* partial walk? */ 4759a747e4fSDavid du Colombier tx->nwqid = i; 4769a747e4fSDavid du Colombier else 4779a747e4fSDavid du Colombier seterror(tx, e); 4789a747e4fSDavid du Colombier 4799a747e4fSDavid du Colombier if(nfid) /* clone implicit new fid */ 4809a747e4fSDavid du Colombier freefid(nfid); 4819a747e4fSDavid du Colombier free(path); 4823e12c5d1SDavid du Colombier } 4839a747e4fSDavid du Colombier return; 4843e12c5d1SDavid du Colombier } 4853e12c5d1SDavid du Colombier 4863e12c5d1SDavid du Colombier void 4879a747e4fSDavid du Colombier ropen(Fcall *rx, Fcall *tx) 4883e12c5d1SDavid du Colombier { 4899a747e4fSDavid du Colombier char *e; 4909a747e4fSDavid du Colombier Fid *fid; 4913e12c5d1SDavid du Colombier 4929a747e4fSDavid du Colombier if((fid = oldfid(rx->fid, &e)) == nil){ 4939a747e4fSDavid du Colombier seterror(tx, e); 4949a747e4fSDavid du Colombier return; 4953e12c5d1SDavid du Colombier } 4969a747e4fSDavid du Colombier 4979a747e4fSDavid du Colombier if(fid->omode != -1){ 4989a747e4fSDavid du Colombier seterror(tx, Ebadusefid); 4999a747e4fSDavid du Colombier return; 5003e12c5d1SDavid du Colombier } 5019a747e4fSDavid du Colombier 5029a747e4fSDavid du Colombier if(fidstat(fid, &e) < 0){ 5039a747e4fSDavid du Colombier seterror(tx, e); 5049a747e4fSDavid du Colombier return; 5053e12c5d1SDavid du Colombier } 5069a747e4fSDavid du Colombier 5079a747e4fSDavid du Colombier if(!devallowed && S_ISSPECIAL(fid->st.st_mode)){ 5089a747e4fSDavid du Colombier seterror(tx, Especial); 5099a747e4fSDavid du Colombier return; 5103e12c5d1SDavid du Colombier } 5119a747e4fSDavid du Colombier 5129a747e4fSDavid du Colombier if(useropen(fid, rx->mode, &e) < 0){ 5139a747e4fSDavid du Colombier seterror(tx, e); 5149a747e4fSDavid du Colombier return; 5153e12c5d1SDavid du Colombier } 5169a747e4fSDavid du Colombier 5179a747e4fSDavid du Colombier tx->iounit = 0; 5189a747e4fSDavid du Colombier tx->qid = stat2qid(&fid->st); 5193e12c5d1SDavid du Colombier } 5203e12c5d1SDavid du Colombier 5213e12c5d1SDavid du Colombier void 5229a747e4fSDavid du Colombier rcreate(Fcall *rx, Fcall *tx) 5233e12c5d1SDavid du Colombier { 5249a747e4fSDavid du Colombier char *e; 5259a747e4fSDavid du Colombier Fid *fid; 5269a747e4fSDavid du Colombier 5279a747e4fSDavid du Colombier if((fid = oldfid(rx->fid, &e)) == nil){ 5289a747e4fSDavid du Colombier seterror(tx, e); 5299a747e4fSDavid du Colombier return; 5309a747e4fSDavid du Colombier } 5319a747e4fSDavid du Colombier 5329a747e4fSDavid du Colombier if(fid->omode != -1){ 5339a747e4fSDavid du Colombier seterror(tx, Ebadusefid); 5349a747e4fSDavid du Colombier return; 5359a747e4fSDavid du Colombier } 5369a747e4fSDavid du Colombier 5379a747e4fSDavid du Colombier if(fidstat(fid, &e) < 0){ 5389a747e4fSDavid du Colombier seterror(tx, e); 5399a747e4fSDavid du Colombier return; 5409a747e4fSDavid du Colombier } 5419a747e4fSDavid du Colombier 5429a747e4fSDavid du Colombier if(!S_ISDIR(fid->st.st_mode)){ 5439a747e4fSDavid du Colombier seterror(tx, Enotdir); 5449a747e4fSDavid du Colombier return; 5459a747e4fSDavid du Colombier } 5469a747e4fSDavid du Colombier 5479a747e4fSDavid du Colombier if(usercreate(fid, rx->name, rx->mode, rx->perm, &e) < 0){ 5489a747e4fSDavid du Colombier seterror(tx, e); 5499a747e4fSDavid du Colombier return; 5509a747e4fSDavid du Colombier } 5519a747e4fSDavid du Colombier 5529a747e4fSDavid du Colombier if(fidstat(fid, &e) < 0){ 5539a747e4fSDavid du Colombier seterror(tx, e); 5549a747e4fSDavid du Colombier return; 5559a747e4fSDavid du Colombier } 5569a747e4fSDavid du Colombier 5579a747e4fSDavid du Colombier tx->iounit = 0; 5589a747e4fSDavid du Colombier tx->qid = stat2qid(&fid->st); 5599a747e4fSDavid du Colombier } 5609a747e4fSDavid du Colombier 5619a747e4fSDavid du Colombier uchar 5629a747e4fSDavid du Colombier modebyte(struct stat *st) 5639a747e4fSDavid du Colombier { 5649a747e4fSDavid du Colombier uchar b; 5659a747e4fSDavid du Colombier 5669a747e4fSDavid du Colombier b = 0; 5679a747e4fSDavid du Colombier 5689a747e4fSDavid du Colombier if(S_ISDIR(st->st_mode)) 5699a747e4fSDavid du Colombier b |= QTDIR; 5709a747e4fSDavid du Colombier 5719a747e4fSDavid du Colombier /* no way to test append-only */ 5729a747e4fSDavid du Colombier /* no real way to test exclusive use, but mark devices as such */ 5739a747e4fSDavid du Colombier if(S_ISSPECIAL(st->st_mode)) 5749a747e4fSDavid du Colombier b |= QTEXCL; 5759a747e4fSDavid du Colombier 5769a747e4fSDavid du Colombier return b; 5779a747e4fSDavid du Colombier } 5789a747e4fSDavid du Colombier 5799a747e4fSDavid du Colombier ulong 5809a747e4fSDavid du Colombier plan9mode(struct stat *st) 5819a747e4fSDavid du Colombier { 5829a747e4fSDavid du Colombier return ((ulong)modebyte(st)<<24) | (st->st_mode & 0777); 5839a747e4fSDavid du Colombier } 5849a747e4fSDavid du Colombier 5859a747e4fSDavid du Colombier /* 5869a747e4fSDavid du Colombier * this is for chmod, so don't worry about S_IFDIR 5879a747e4fSDavid du Colombier */ 5889a747e4fSDavid du Colombier mode_t 5899a747e4fSDavid du Colombier unixmode(Dir *d) 5909a747e4fSDavid du Colombier { 5919a747e4fSDavid du Colombier return (mode_t)(d->mode&0777); 5929a747e4fSDavid du Colombier } 5939a747e4fSDavid du Colombier 5949a747e4fSDavid du Colombier Qid 5959a747e4fSDavid du Colombier stat2qid(struct stat *st) 5969a747e4fSDavid du Colombier { 5979a747e4fSDavid du Colombier uchar *p, *ep, *q; 5989a747e4fSDavid du Colombier Qid qid; 5999a747e4fSDavid du Colombier 6009a747e4fSDavid du Colombier /* 6019a747e4fSDavid du Colombier * For now, ignore the device number. 6029a747e4fSDavid du Colombier */ 6039a747e4fSDavid du Colombier qid.path = 0; 6049a747e4fSDavid du Colombier p = (uchar*)&qid.path; 6059a747e4fSDavid du Colombier ep = p+sizeof(qid.path); 6069a747e4fSDavid du Colombier q = p+sizeof(ino_t); 6079a747e4fSDavid du Colombier if(q > ep){ 6089a747e4fSDavid du Colombier fprint(2, "warning: inode number too big\n"); 6099a747e4fSDavid du Colombier q = ep; 6109a747e4fSDavid du Colombier } 6119a747e4fSDavid du Colombier memmove(p, &st->st_ino, q-p); 6129a747e4fSDavid du Colombier q = q+sizeof(dev_t); 6139a747e4fSDavid du Colombier if(q > ep){ 6149a747e4fSDavid du Colombier /* fprint(2, "warning: inode number + device number too big %d+%d\n", sizeof(ino_t), sizeof(dev_t)); */ 6159a747e4fSDavid du Colombier q = ep - sizeof(dev_t); 6169a747e4fSDavid du Colombier if(q < p) 6179a747e4fSDavid du Colombier fprint(2, "warning: device number too big by itself\n"); 6189a747e4fSDavid du Colombier else 6199a747e4fSDavid du Colombier *(dev_t*)q ^= st->st_dev; 6209a747e4fSDavid du Colombier } 6219a747e4fSDavid du Colombier 6229a747e4fSDavid du Colombier qid.vers = st->st_mtime ^ (st->st_size << 8); 6239a747e4fSDavid du Colombier qid.type = modebyte(st); 6249a747e4fSDavid du Colombier return qid; 6259a747e4fSDavid du Colombier } 6269a747e4fSDavid du Colombier 6279a747e4fSDavid du Colombier void 6289a747e4fSDavid du Colombier stat2dir(char *path, struct stat *st, Dir *d) 6299a747e4fSDavid du Colombier { 6309a747e4fSDavid du Colombier User *u; 6319a747e4fSDavid du Colombier char *q; 6329a747e4fSDavid du Colombier 6339a747e4fSDavid du Colombier memset(d, 0, sizeof(*d)); 6349a747e4fSDavid du Colombier d->qid = stat2qid(st); 6359a747e4fSDavid du Colombier d->mode = plan9mode(st); 6369a747e4fSDavid du Colombier d->atime = st->st_atime; 6379a747e4fSDavid du Colombier d->mtime = st->st_mtime; 6389a747e4fSDavid du Colombier d->length = st->st_size; 6399a747e4fSDavid du Colombier 6409a747e4fSDavid du Colombier d->uid = (u = uid2user(st->st_uid)) ? u->name : "???"; 6419a747e4fSDavid du Colombier d->gid = (u = gid2user(st->st_gid)) ? u->name : "???"; 6429a747e4fSDavid du Colombier d->muid = ""; 6439a747e4fSDavid du Colombier 6449a747e4fSDavid du Colombier if((q = strrchr(path, '/')) != nil) 6459a747e4fSDavid du Colombier d->name = q+1; 6469a747e4fSDavid du Colombier else 6479a747e4fSDavid du Colombier d->name = path; 6489a747e4fSDavid du Colombier } 6499a747e4fSDavid du Colombier 6509a747e4fSDavid du Colombier void 6519a747e4fSDavid du Colombier rread(Fcall *rx, Fcall *tx) 6529a747e4fSDavid du Colombier { 6539a747e4fSDavid du Colombier char *e, *path; 6549a747e4fSDavid du Colombier uchar *p, *ep; 6559a747e4fSDavid du Colombier int n; 6569a747e4fSDavid du Colombier Fid *fid; 6573e12c5d1SDavid du Colombier Dir d; 6589a747e4fSDavid du Colombier struct stat st; 6593e12c5d1SDavid du Colombier 6609a747e4fSDavid du Colombier if(rx->count > msize-IOHDRSZ){ 6619a747e4fSDavid du Colombier seterror(tx, Etoolarge); 6629a747e4fSDavid du Colombier return; 6633e12c5d1SDavid du Colombier } 6649a747e4fSDavid du Colombier 66550a9bdd4SDavid du Colombier if((fid = oldfidex(rx->fid, -1, &e)) == nil){ 66650a9bdd4SDavid du Colombier seterror(tx, e); 66750a9bdd4SDavid du Colombier return; 66850a9bdd4SDavid du Colombier } 66950a9bdd4SDavid du Colombier 67050a9bdd4SDavid du Colombier if (fid->auth) { 67150a9bdd4SDavid du Colombier char *e; 67250a9bdd4SDavid du Colombier e = auth->read(rx, tx); 67350a9bdd4SDavid du Colombier if (e) 6749a747e4fSDavid du Colombier seterror(tx, e); 6759a747e4fSDavid du Colombier return; 6763e12c5d1SDavid du Colombier } 6779a747e4fSDavid du Colombier 6789a747e4fSDavid du Colombier if(fid->omode == -1 || (fid->omode&3) == OWRITE){ 6799a747e4fSDavid du Colombier seterror(tx, Ebadusefid); 6809a747e4fSDavid du Colombier return; 6819a747e4fSDavid du Colombier } 6829a747e4fSDavid du Colombier 6839a747e4fSDavid du Colombier if(fid->dir){ 6849a747e4fSDavid du Colombier if(rx->offset != fid->diroffset){ 6859a747e4fSDavid du Colombier if(rx->offset != 0){ 6869a747e4fSDavid du Colombier seterror(tx, Ebadoffset); 6879a747e4fSDavid du Colombier return; 6889a747e4fSDavid du Colombier } 6899a747e4fSDavid du Colombier rewinddir(fid->dir); 6909a747e4fSDavid du Colombier fid->diroffset = 0; 6919a747e4fSDavid du Colombier } 6929a747e4fSDavid du Colombier 6939a747e4fSDavid du Colombier p = (uchar*)tx->data; 6949a747e4fSDavid du Colombier ep = (uchar*)tx->data+rx->count; 6959a747e4fSDavid du Colombier for(;;){ 6969a747e4fSDavid du Colombier if(p+BIT16SZ >= ep) 6973e12c5d1SDavid du Colombier break; 6989a747e4fSDavid du Colombier if(fid->dirent == nil) /* one entry cache for when convD2M fails */ 6999a747e4fSDavid du Colombier if((fid->dirent = readdir(fid->dir)) == nil) 7009a747e4fSDavid du Colombier break; 7019a747e4fSDavid du Colombier if(strcmp(fid->dirent->d_name, ".") == 0 7029a747e4fSDavid du Colombier || strcmp(fid->dirent->d_name, "..") == 0){ 7039a747e4fSDavid du Colombier fid->dirent = nil; 7043e12c5d1SDavid du Colombier continue; 7059a747e4fSDavid du Colombier } 7069a747e4fSDavid du Colombier path = estrpath(fid->path, fid->dirent->d_name); 7079a747e4fSDavid du Colombier memset(&st, 0, sizeof st); 7089a747e4fSDavid du Colombier if(stat(path, &st) < 0){ 7099a747e4fSDavid du Colombier fprint(2, "dirread: stat(%s) failed: %s\n", path, strerror(errno)); 7109a747e4fSDavid du Colombier fid->dirent = nil; 7119a747e4fSDavid du Colombier free(path); 7123e12c5d1SDavid du Colombier continue; 7133e12c5d1SDavid du Colombier } 7143e12c5d1SDavid du Colombier free(path); 7159a747e4fSDavid du Colombier stat2dir(fid->dirent->d_name, &st, &d); 7169a747e4fSDavid du Colombier if((n=(old9p ? convD2Mold : convD2M)(&d, p, ep-p)) <= BIT16SZ) 7179a747e4fSDavid du Colombier break; 7189a747e4fSDavid du Colombier p += n; 7199a747e4fSDavid du Colombier fid->dirent = nil; 7203e12c5d1SDavid du Colombier } 7219a747e4fSDavid du Colombier tx->count = p - (uchar*)tx->data; 7229a747e4fSDavid du Colombier fid->diroffset += tx->count; 7233e12c5d1SDavid du Colombier }else{ 7249a747e4fSDavid du Colombier if((n = pread(fid->fd, tx->data, rx->count, rx->offset)) < 0){ 7259a747e4fSDavid du Colombier seterror(tx, strerror(errno)); 7269a747e4fSDavid du Colombier return; 727219b2ee8SDavid du Colombier } 7289a747e4fSDavid du Colombier tx->count = n; 7293e12c5d1SDavid du Colombier } 7303e12c5d1SDavid du Colombier } 7313e12c5d1SDavid du Colombier 7323e12c5d1SDavid du Colombier void 7339a747e4fSDavid du Colombier rwrite(Fcall *rx, Fcall *tx) 7343e12c5d1SDavid du Colombier { 7359a747e4fSDavid du Colombier char *e; 7369a747e4fSDavid du Colombier Fid *fid; 7373e12c5d1SDavid du Colombier int n; 7383e12c5d1SDavid du Colombier 7399a747e4fSDavid du Colombier if(rx->count > msize-IOHDRSZ){ 7409a747e4fSDavid du Colombier seterror(tx, Etoolarge); 7417dd7cddfSDavid du Colombier return; 7427dd7cddfSDavid du Colombier } 7439a747e4fSDavid du Colombier 74450a9bdd4SDavid du Colombier if((fid = oldfidex(rx->fid, -1, &e)) == nil){ 74550a9bdd4SDavid du Colombier seterror(tx, e); 74650a9bdd4SDavid du Colombier return; 74750a9bdd4SDavid du Colombier } 74850a9bdd4SDavid du Colombier 74950a9bdd4SDavid du Colombier if (fid->auth) { 75050a9bdd4SDavid du Colombier char *e; 75150a9bdd4SDavid du Colombier e = auth->write(rx, tx); 75250a9bdd4SDavid du Colombier if (e) 7539a747e4fSDavid du Colombier seterror(tx, e); 7549a747e4fSDavid du Colombier return; 7553e12c5d1SDavid du Colombier } 7569a747e4fSDavid du Colombier 7579a747e4fSDavid du Colombier if(fid->omode == -1 || (fid->omode&3) == OREAD || (fid->omode&3) == OEXEC){ 7589a747e4fSDavid du Colombier seterror(tx, Ebadusefid); 7599a747e4fSDavid du Colombier return; 7609a747e4fSDavid du Colombier } 7619a747e4fSDavid du Colombier 7629a747e4fSDavid du Colombier if((n = pwrite(fid->fd, rx->data, rx->count, rx->offset)) < 0){ 7639a747e4fSDavid du Colombier seterror(tx, strerror(errno)); 7649a747e4fSDavid du Colombier return; 7659a747e4fSDavid du Colombier } 7669a747e4fSDavid du Colombier tx->count = n; 7673e12c5d1SDavid du Colombier } 7683e12c5d1SDavid du Colombier 7693e12c5d1SDavid du Colombier void 7709a747e4fSDavid du Colombier rclunk(Fcall *rx, Fcall *tx) 7713e12c5d1SDavid du Colombier { 7729a747e4fSDavid du Colombier char *e; 7739a747e4fSDavid du Colombier Fid *fid; 7743e12c5d1SDavid du Colombier 77550a9bdd4SDavid du Colombier if((fid = oldfidex(rx->fid, -1, &e)) == nil){ 7769a747e4fSDavid du Colombier seterror(tx, e); 7779a747e4fSDavid du Colombier return; 7789a747e4fSDavid du Colombier } 77950a9bdd4SDavid du Colombier if (fid->auth) { 78050a9bdd4SDavid du Colombier if (auth->clunk) { 78150a9bdd4SDavid du Colombier e = (*auth->clunk)(rx, tx); 78250a9bdd4SDavid du Colombier if (e) { 78350a9bdd4SDavid du Colombier seterror(tx, e); 78450a9bdd4SDavid du Colombier return; 78550a9bdd4SDavid du Colombier } 78650a9bdd4SDavid du Colombier } 78750a9bdd4SDavid du Colombier } 78850a9bdd4SDavid du Colombier else if(fid->omode != -1 && fid->omode&ORCLOSE) 7899a747e4fSDavid du Colombier remove(fid->path); 7909a747e4fSDavid du Colombier freefid(fid); 7913e12c5d1SDavid du Colombier } 792219b2ee8SDavid du Colombier 7939a747e4fSDavid du Colombier void 7949a747e4fSDavid du Colombier rremove(Fcall *rx, Fcall *tx) 7953e12c5d1SDavid du Colombier { 7969a747e4fSDavid du Colombier char *e; 7979a747e4fSDavid du Colombier Fid *fid; 7983e12c5d1SDavid du Colombier 7999a747e4fSDavid du Colombier if((fid = oldfid(rx->fid, &e)) == nil){ 8009a747e4fSDavid du Colombier seterror(tx, e); 8019a747e4fSDavid du Colombier return; 8023e12c5d1SDavid du Colombier } 8039a747e4fSDavid du Colombier if(userremove(fid, &e) < 0) 8049a747e4fSDavid du Colombier seterror(tx, e); 8059a747e4fSDavid du Colombier freefid(fid); 8069a747e4fSDavid du Colombier } 8079a747e4fSDavid du Colombier 8089a747e4fSDavid du Colombier void 8099a747e4fSDavid du Colombier rstat(Fcall *rx, Fcall *tx) 8109a747e4fSDavid du Colombier { 8119a747e4fSDavid du Colombier char *e; 8129a747e4fSDavid du Colombier Fid *fid; 8139a747e4fSDavid du Colombier Dir d; 8149a747e4fSDavid du Colombier 8159a747e4fSDavid du Colombier if((fid = oldfid(rx->fid, &e)) == nil){ 8169a747e4fSDavid du Colombier seterror(tx, e); 8179a747e4fSDavid du Colombier return; 8189a747e4fSDavid du Colombier } 8199a747e4fSDavid du Colombier 8209a747e4fSDavid du Colombier if(fidstat(fid, &e) < 0){ 8219a747e4fSDavid du Colombier seterror(tx, e); 8229a747e4fSDavid du Colombier return; 8239a747e4fSDavid du Colombier } 8249a747e4fSDavid du Colombier 8259a747e4fSDavid du Colombier stat2dir(fid->path, &fid->st, &d); 8269a747e4fSDavid du Colombier if((tx->nstat=(old9p ? convD2Mold : convD2M)(&d, tx->stat, msize)) <= BIT16SZ) 8279a747e4fSDavid du Colombier seterror(tx, "convD2M fails"); 8289a747e4fSDavid du Colombier } 8299a747e4fSDavid du Colombier 8309a747e4fSDavid du Colombier void 8319a747e4fSDavid du Colombier rwstat(Fcall *rx, Fcall *tx) 8329a747e4fSDavid du Colombier { 8339a747e4fSDavid du Colombier char *e; 8349a747e4fSDavid du Colombier char *p, *old, *new, *dir; 8359a747e4fSDavid du Colombier gid_t gid; 8369a747e4fSDavid du Colombier Dir d; 8379a747e4fSDavid du Colombier Fid *fid; 8389a747e4fSDavid du Colombier 8399a747e4fSDavid du Colombier if((fid = oldfid(rx->fid, &e)) == nil){ 8409a747e4fSDavid du Colombier seterror(tx, e); 8419a747e4fSDavid du Colombier return; 8429a747e4fSDavid du Colombier } 8439a747e4fSDavid du Colombier 8449a747e4fSDavid du Colombier /* 8459a747e4fSDavid du Colombier * wstat is supposed to be atomic. 8469a747e4fSDavid du Colombier * we check all the things we can before trying anything. 8479a747e4fSDavid du Colombier * still, if we are told to truncate a file and rename it and only 8489a747e4fSDavid du Colombier * one works, we're screwed. in such cases we leave things 8499a747e4fSDavid du Colombier * half broken and return an error. it's hardly perfect. 8509a747e4fSDavid du Colombier */ 8519a747e4fSDavid du Colombier if((old9p ? convM2Dold : convM2D)(rx->stat, rx->nstat, &d, (char*)rx->stat) <= BIT16SZ){ 8529a747e4fSDavid du Colombier seterror(tx, Ewstatbuffer); 8539a747e4fSDavid du Colombier return; 8549a747e4fSDavid du Colombier } 8559a747e4fSDavid du Colombier 8569a747e4fSDavid du Colombier if(fidstat(fid, &e) < 0){ 8579a747e4fSDavid du Colombier seterror(tx, e); 8589a747e4fSDavid du Colombier return; 8599a747e4fSDavid du Colombier } 8609a747e4fSDavid du Colombier 8619a747e4fSDavid du Colombier /* 8629a747e4fSDavid du Colombier * The casting is necessary because d.mode is ulong and might, 8639a747e4fSDavid du Colombier * on some systems, be 64 bits. We only want to compare the 8649a747e4fSDavid du Colombier * bottom 32 bits, since that's all that gets sent in the protocol. 8659a747e4fSDavid du Colombier * 8669a747e4fSDavid du Colombier * Same situation for d.mtime and d.length (although that last check 8679a747e4fSDavid du Colombier * is admittedly superfluous, given the current lack of 128-bit machines). 8689a747e4fSDavid du Colombier */ 8699a747e4fSDavid du Colombier gid = (gid_t)-1; 8709a747e4fSDavid du Colombier if(d.gid[0] != '\0'){ 8719a747e4fSDavid du Colombier User *g; 8729a747e4fSDavid du Colombier 8739a747e4fSDavid du Colombier g = gname2user(d.gid); 8749a747e4fSDavid du Colombier if(g == nil){ 8759a747e4fSDavid du Colombier seterror(tx, Eunknowngroup); 8769a747e4fSDavid du Colombier return; 8779a747e4fSDavid du Colombier } 8789a747e4fSDavid du Colombier gid = (gid_t)g->id; 8799a747e4fSDavid du Colombier 8809a747e4fSDavid du Colombier if(groupchange(fid->u, gid2user(gid), &e) < 0){ 8819a747e4fSDavid du Colombier seterror(tx, e); 8829a747e4fSDavid du Colombier return; 8839a747e4fSDavid du Colombier } 8849a747e4fSDavid du Colombier } 8859a747e4fSDavid du Colombier 8869a747e4fSDavid du Colombier if((u32int)d.mode != (u32int)~0 && (((d.mode&DMDIR)!=0) ^ (S_ISDIR(fid->st.st_mode)!=0))){ 8879a747e4fSDavid du Colombier seterror(tx, Edirchange); 8889a747e4fSDavid du Colombier return; 8899a747e4fSDavid du Colombier } 8909a747e4fSDavid du Colombier 8919a747e4fSDavid du Colombier if(strcmp(fid->path, "/") == 0){ 8929a747e4fSDavid du Colombier seterror(tx, "no wstat of root"); 8939a747e4fSDavid du Colombier return; 8949a747e4fSDavid du Colombier } 8959a747e4fSDavid du Colombier 8969a747e4fSDavid du Colombier /* 8979a747e4fSDavid du Colombier * try things in increasing order of harm to the file. 8989a747e4fSDavid du Colombier * mtime should come after truncate so that if you 8999a747e4fSDavid du Colombier * do both the mtime actually takes effect, but i'd rather 9009a747e4fSDavid du Colombier * leave truncate until last. 9019a747e4fSDavid du Colombier * (see above comment about atomicity). 9029a747e4fSDavid du Colombier */ 9039a747e4fSDavid du Colombier if((u32int)d.mode != (u32int)~0 && chmod(fid->path, unixmode(&d)) < 0){ 9049a747e4fSDavid du Colombier if(chatty9p) 9059a747e4fSDavid du Colombier fprint(2, "chmod(%s, 0%luo) failed\n", fid->path, unixmode(&d)); 9069a747e4fSDavid du Colombier seterror(tx, strerror(errno)); 9079a747e4fSDavid du Colombier return; 9089a747e4fSDavid du Colombier } 9099a747e4fSDavid du Colombier 9109a747e4fSDavid du Colombier if((u32int)d.mtime != (u32int)~0){ 9119a747e4fSDavid du Colombier struct utimbuf t; 9129a747e4fSDavid du Colombier 9139a747e4fSDavid du Colombier t.actime = 0; 9149a747e4fSDavid du Colombier t.modtime = d.mtime; 9159a747e4fSDavid du Colombier if(utime(fid->path, &t) < 0){ 9169a747e4fSDavid du Colombier if(chatty9p) 9179a747e4fSDavid du Colombier fprint(2, "utime(%s) failed\n", fid->path); 9189a747e4fSDavid du Colombier seterror(tx, strerror(errno)); 9199a747e4fSDavid du Colombier return; 9209a747e4fSDavid du Colombier } 9219a747e4fSDavid du Colombier } 9229a747e4fSDavid du Colombier 9239a747e4fSDavid du Colombier if(gid != (gid_t)-1 && gid != fid->st.st_gid){ 9249a747e4fSDavid du Colombier if(chown(fid->path, (uid_t)-1, gid) < 0){ 9259a747e4fSDavid du Colombier if(chatty9p) 9269a747e4fSDavid du Colombier fprint(2, "chgrp(%s, %d) failed\n", fid->path, gid); 9279a747e4fSDavid du Colombier seterror(tx, strerror(errno)); 9289a747e4fSDavid du Colombier return; 9299a747e4fSDavid du Colombier } 9309a747e4fSDavid du Colombier } 9319a747e4fSDavid du Colombier 9329a747e4fSDavid du Colombier if(d.name[0]){ 9339a747e4fSDavid du Colombier old = fid->path; 9349a747e4fSDavid du Colombier dir = estrdup(fid->path); 9359a747e4fSDavid du Colombier if((p = strrchr(dir, '/')) > dir) 9369a747e4fSDavid du Colombier *p = '\0'; 9373e12c5d1SDavid du Colombier else{ 9389a747e4fSDavid du Colombier seterror(tx, "whoops: can't happen in u9fs"); 9399a747e4fSDavid du Colombier return; 9403e12c5d1SDavid du Colombier } 9413e12c5d1SDavid du Colombier 9429a747e4fSDavid du Colombier new = estrpath(dir, d.name); 9439a747e4fSDavid du Colombier if(strcmp(old, new) != 0 && rename(old, new) < 0){ 9449a747e4fSDavid du Colombier if(chatty9p) 9459a747e4fSDavid du Colombier fprint(2, "rename(%s, %s) failed\n", old, new); 9469a747e4fSDavid du Colombier seterror(tx, strerror(errno)); 9479a747e4fSDavid du Colombier free(new); 9489a747e4fSDavid du Colombier free(dir); 9499a747e4fSDavid du Colombier return; 9509a747e4fSDavid du Colombier } 9519a747e4fSDavid du Colombier fid->path = new; 9529a747e4fSDavid du Colombier free(old); 9539a747e4fSDavid du Colombier free(dir); 9549a747e4fSDavid du Colombier } 9559a747e4fSDavid du Colombier 9569a747e4fSDavid du Colombier if((u64int)d.length != (u64int)~0 && truncate(fid->path, d.length) < 0){ 9579a747e4fSDavid du Colombier fprint(2, "truncate(%s, %lld) failed\n", fid->path, d.length); 9589a747e4fSDavid du Colombier seterror(tx, strerror(errno)); 9599a747e4fSDavid du Colombier return; 9609a747e4fSDavid du Colombier } 9619a747e4fSDavid du Colombier } 9629a747e4fSDavid du Colombier 9639a747e4fSDavid du Colombier /* 9649a747e4fSDavid du Colombier * we keep a table by numeric id. by name lookups happen infrequently 9659a747e4fSDavid du Colombier * while by-number lookups happen once for every directory entry read 9669a747e4fSDavid du Colombier * and every stat request. 9679a747e4fSDavid du Colombier */ 9689a747e4fSDavid du Colombier User *utab[64]; 9699a747e4fSDavid du Colombier User *gtab[64]; 9709a747e4fSDavid du Colombier 9719a747e4fSDavid du Colombier User* 9729a747e4fSDavid du Colombier adduser(struct passwd *p) 9733e12c5d1SDavid du Colombier { 9749a747e4fSDavid du Colombier User *u; 9753e12c5d1SDavid du Colombier 9769a747e4fSDavid du Colombier u = emalloc(sizeof(*u)); 9779a747e4fSDavid du Colombier u->id = p->pw_uid; 9789a747e4fSDavid du Colombier u->name = estrdup(p->pw_name); 9799a747e4fSDavid du Colombier u->next = utab[p->pw_uid%nelem(utab)]; 9809a747e4fSDavid du Colombier u->defaultgid = p->pw_gid; 9819a747e4fSDavid du Colombier utab[p->pw_uid%nelem(utab)] = u; 9829a747e4fSDavid du Colombier return u; 9833e12c5d1SDavid du Colombier } 9843e12c5d1SDavid du Colombier 9853e12c5d1SDavid du Colombier int 9869a747e4fSDavid du Colombier useringroup(User *u, User *g) 9873e12c5d1SDavid du Colombier { 9889a747e4fSDavid du Colombier int i; 9899a747e4fSDavid du Colombier 9909a747e4fSDavid du Colombier for(i=0; i<g->nmem; i++) 9919a747e4fSDavid du Colombier if(strcmp(g->mem[i], u->name) == 0) 9923e12c5d1SDavid du Colombier return 1; 9939a747e4fSDavid du Colombier 9949a747e4fSDavid du Colombier /* 9959a747e4fSDavid du Colombier * Hack around common Unix problem that everyone has 9969a747e4fSDavid du Colombier * default group "user" but /etc/group lists no members. 9979a747e4fSDavid du Colombier */ 9989a747e4fSDavid du Colombier if(u->defaultgid == g->id) 9999a747e4fSDavid du Colombier return 1; 10003e12c5d1SDavid du Colombier return 0; 10013e12c5d1SDavid du Colombier } 10023e12c5d1SDavid du Colombier 10039a747e4fSDavid du Colombier User* 10049a747e4fSDavid du Colombier addgroup(struct group *g) 10053e12c5d1SDavid du Colombier { 10069a747e4fSDavid du Colombier User *u; 10079a747e4fSDavid du Colombier char **p; 10083e12c5d1SDavid du Colombier int n; 10093e12c5d1SDavid du Colombier 10109a747e4fSDavid du Colombier u = emalloc(sizeof(*u)); 10119a747e4fSDavid du Colombier n = 0; 10129a747e4fSDavid du Colombier for(p=g->gr_mem; *p; p++) 10139a747e4fSDavid du Colombier n++; 10149a747e4fSDavid du Colombier u->mem = emalloc(sizeof(u->mem[0])*n); 10159a747e4fSDavid du Colombier n = 0; 10169a747e4fSDavid du Colombier for(p=g->gr_mem; *p; p++) 10179a747e4fSDavid du Colombier u->mem[n++] = estrdup(*p); 10189a747e4fSDavid du Colombier u->nmem = n; 10199a747e4fSDavid du Colombier u->id = g->gr_gid; 10209a747e4fSDavid du Colombier u->name = estrdup(g->gr_name); 10219a747e4fSDavid du Colombier u->next = gtab[g->gr_gid%nelem(gtab)]; 10229a747e4fSDavid du Colombier gtab[g->gr_gid%nelem(gtab)] = u; 10239a747e4fSDavid du Colombier return u; 10243e12c5d1SDavid du Colombier } 10253e12c5d1SDavid du Colombier 10269a747e4fSDavid du Colombier User* 10279a747e4fSDavid du Colombier uname2user(char *name) 10287dd7cddfSDavid du Colombier { 10297dd7cddfSDavid du Colombier int i; 10309a747e4fSDavid du Colombier User *u; 10319a747e4fSDavid du Colombier struct passwd *p; 10327dd7cddfSDavid du Colombier 10339a747e4fSDavid du Colombier for(i=0; i<nelem(utab); i++) 10349a747e4fSDavid du Colombier for(u=utab[i]; u; u=u->next) 10359a747e4fSDavid du Colombier if(strcmp(u->name, name) == 0) 10369a747e4fSDavid du Colombier return u; 10379a747e4fSDavid du Colombier 10389a747e4fSDavid du Colombier if((p = getpwnam(name)) == nil) 10399a747e4fSDavid du Colombier return nil; 10409a747e4fSDavid du Colombier return adduser(p); 10417dd7cddfSDavid du Colombier } 10427dd7cddfSDavid du Colombier 10439a747e4fSDavid du Colombier User* 10449a747e4fSDavid du Colombier uid2user(int id) 10459a747e4fSDavid du Colombier { 10469a747e4fSDavid du Colombier User *u; 10479a747e4fSDavid du Colombier struct passwd *p; 10489a747e4fSDavid du Colombier 10499a747e4fSDavid du Colombier for(u=utab[id%nelem(utab)]; u; u=u->next) 10509a747e4fSDavid du Colombier if(u->id == id) 10519a747e4fSDavid du Colombier return u; 10529a747e4fSDavid du Colombier 10539a747e4fSDavid du Colombier if((p = getpwuid(id)) == nil) 10549a747e4fSDavid du Colombier return nil; 10559a747e4fSDavid du Colombier return adduser(p); 10569a747e4fSDavid du Colombier } 10579a747e4fSDavid du Colombier 10589a747e4fSDavid du Colombier User* 10599a747e4fSDavid du Colombier gname2user(char *name) 10603e12c5d1SDavid du Colombier { 10613e12c5d1SDavid du Colombier int i; 10629a747e4fSDavid du Colombier User *u; 10639a747e4fSDavid du Colombier struct group *g; 10643e12c5d1SDavid du Colombier 10659a747e4fSDavid du Colombier for(i=0; i<nelem(gtab); i++) 10669a747e4fSDavid du Colombier for(u=gtab[i]; u; u=u->next) 10679a747e4fSDavid du Colombier if(strcmp(u->name, name) == 0) 10689a747e4fSDavid du Colombier return u; 10699a747e4fSDavid du Colombier 10709a747e4fSDavid du Colombier if((g = getgrnam(name)) == nil) 10719a747e4fSDavid du Colombier return nil; 10729a747e4fSDavid du Colombier return addgroup(g); 10739a747e4fSDavid du Colombier } 10749a747e4fSDavid du Colombier 10759a747e4fSDavid du Colombier User* 10769a747e4fSDavid du Colombier gid2user(int id) 10779a747e4fSDavid du Colombier { 10789a747e4fSDavid du Colombier User *u; 10799a747e4fSDavid du Colombier struct group *g; 10809a747e4fSDavid du Colombier 10819a747e4fSDavid du Colombier for(u=gtab[id%nelem(gtab)]; u; u=u->next) 10829a747e4fSDavid du Colombier if(u->id == id) 10839a747e4fSDavid du Colombier return u; 10849a747e4fSDavid du Colombier 10859a747e4fSDavid du Colombier if((g = getgrgid(id)) == nil) 10869a747e4fSDavid du Colombier return nil; 10879a747e4fSDavid du Colombier return addgroup(g); 10883e12c5d1SDavid du Colombier } 10893e12c5d1SDavid du Colombier 10903e12c5d1SDavid du Colombier void 10919a747e4fSDavid du Colombier sysfatal(char *fmt, ...) 10923e12c5d1SDavid du Colombier { 10939a747e4fSDavid du Colombier char buf[1024]; 10949a747e4fSDavid du Colombier va_list va; 10953e12c5d1SDavid du Colombier 10969a747e4fSDavid du Colombier va_start(va, fmt); 10979a747e4fSDavid du Colombier doprint(buf, buf+sizeof buf, fmt, va); 10989a747e4fSDavid du Colombier va_end(va); 10999a747e4fSDavid du Colombier fprint(2, "u9fs: %s\n", buf); 11009a747e4fSDavid du Colombier fprint(2, "last unix error: %s\n", strerror(errno)); 11013e12c5d1SDavid du Colombier exit(1); 11023e12c5d1SDavid du Colombier } 11033e12c5d1SDavid du Colombier 11043e12c5d1SDavid du Colombier void* 11059a747e4fSDavid du Colombier emalloc(size_t n) 11069a747e4fSDavid du Colombier { 11079a747e4fSDavid du Colombier void *p; 11089a747e4fSDavid du Colombier 1109d9306527SDavid du Colombier if(n == 0) 1110d9306527SDavid du Colombier n = 1; 11119a747e4fSDavid du Colombier p = malloc(n); 11129a747e4fSDavid du Colombier if(p == 0) 11139a747e4fSDavid du Colombier sysfatal("malloc(%ld) fails", (long)n); 11149a747e4fSDavid du Colombier memset(p, 0, n); 11159a747e4fSDavid du Colombier return p; 11169a747e4fSDavid du Colombier } 11179a747e4fSDavid du Colombier 11189a747e4fSDavid du Colombier void* 11199a747e4fSDavid du Colombier erealloc(void *p, size_t n) 11203e12c5d1SDavid du Colombier { 11213e12c5d1SDavid du Colombier if(p == 0) 11223e12c5d1SDavid du Colombier p = malloc(n); 11233e12c5d1SDavid du Colombier else 11243e12c5d1SDavid du Colombier p = realloc(p, n); 11253e12c5d1SDavid du Colombier if(p == 0) 11269a747e4fSDavid du Colombier sysfatal("realloc(..., %ld) fails", (long)n); 11273e12c5d1SDavid du Colombier return p; 11283e12c5d1SDavid du Colombier } 11293e12c5d1SDavid du Colombier 11303e12c5d1SDavid du Colombier char* 11313e12c5d1SDavid du Colombier estrdup(char *p) 11323e12c5d1SDavid du Colombier { 11333e12c5d1SDavid du Colombier p = strdup(p); 11343e12c5d1SDavid du Colombier if(p == 0) 11359a747e4fSDavid du Colombier sysfatal("strdup(%.20s) fails", p); 11363e12c5d1SDavid du Colombier return p; 11373e12c5d1SDavid du Colombier } 1138219b2ee8SDavid du Colombier 11399a747e4fSDavid du Colombier char* 11409a747e4fSDavid du Colombier estrpath(char *p, char *q) 1141219b2ee8SDavid du Colombier { 11429a747e4fSDavid du Colombier char *r, *s; 1143219b2ee8SDavid du Colombier 11449a747e4fSDavid du Colombier if(strcmp(q, "..") == 0){ 11459a747e4fSDavid du Colombier r = estrdup(p); 11469a747e4fSDavid du Colombier if((s = strrchr(r, '/')) && s > r) 11479a747e4fSDavid du Colombier *s = '\0'; 11489a747e4fSDavid du Colombier else if(s == r) 11499a747e4fSDavid du Colombier s[1] = '\0'; 11509a747e4fSDavid du Colombier return r; 1151219b2ee8SDavid du Colombier } 11529a747e4fSDavid du Colombier 11539a747e4fSDavid du Colombier r = emalloc(strlen(p)+1+strlen(q)+1); 11549a747e4fSDavid du Colombier strcpy(r, p); 11559a747e4fSDavid du Colombier if(r[0]=='\0' || r[strlen(r)-1] != '/') 11569a747e4fSDavid du Colombier strcat(r, "/"); 11579a747e4fSDavid du Colombier strcat(r, q); 11589a747e4fSDavid du Colombier return r; 11599a747e4fSDavid du Colombier } 11609a747e4fSDavid du Colombier 11619a747e4fSDavid du Colombier Fid *fidtab[1]; 11629a747e4fSDavid du Colombier 11639a747e4fSDavid du Colombier Fid* 11649a747e4fSDavid du Colombier lookupfid(int fid) 11659a747e4fSDavid du Colombier { 11669a747e4fSDavid du Colombier Fid *f; 11679a747e4fSDavid du Colombier 11689a747e4fSDavid du Colombier for(f=fidtab[fid%nelem(fidtab)]; f; f=f->next) 11699a747e4fSDavid du Colombier if(f->fid == fid) 11709a747e4fSDavid du Colombier return f; 11719a747e4fSDavid du Colombier return nil; 11729a747e4fSDavid du Colombier } 11739a747e4fSDavid du Colombier 11749a747e4fSDavid du Colombier Fid* 11759a747e4fSDavid du Colombier newfid(int fid, char **ep) 11769a747e4fSDavid du Colombier { 11779a747e4fSDavid du Colombier Fid *f; 11789a747e4fSDavid du Colombier 11799a747e4fSDavid du Colombier if(lookupfid(fid) != nil){ 11809a747e4fSDavid du Colombier *ep = Efidactive; 11819a747e4fSDavid du Colombier return nil; 11829a747e4fSDavid du Colombier } 11839a747e4fSDavid du Colombier 11849a747e4fSDavid du Colombier f = emalloc(sizeof(*f)); 11859a747e4fSDavid du Colombier f->next = fidtab[fid%nelem(fidtab)]; 11869a747e4fSDavid du Colombier if(f->next) 11879a747e4fSDavid du Colombier f->next->prev = f; 11889a747e4fSDavid du Colombier fidtab[fid%nelem(fidtab)] = f; 11899a747e4fSDavid du Colombier f->fid = fid; 11909a747e4fSDavid du Colombier f->fd = -1; 11919a747e4fSDavid du Colombier f->omode = -1; 11929a747e4fSDavid du Colombier return f; 11939a747e4fSDavid du Colombier } 11949a747e4fSDavid du Colombier 11959a747e4fSDavid du Colombier Fid* 119650a9bdd4SDavid du Colombier newauthfid(int fid, void *magic, char **ep) 119750a9bdd4SDavid du Colombier { 119850a9bdd4SDavid du Colombier Fid *af; 119950a9bdd4SDavid du Colombier af = newfid(fid, ep); 120050a9bdd4SDavid du Colombier if (af == nil) 120150a9bdd4SDavid du Colombier return nil; 120250a9bdd4SDavid du Colombier af->auth = 1; 120350a9bdd4SDavid du Colombier af->authmagic = magic; 120450a9bdd4SDavid du Colombier return af; 120550a9bdd4SDavid du Colombier } 120650a9bdd4SDavid du Colombier 120750a9bdd4SDavid du Colombier Fid* 120850a9bdd4SDavid du Colombier oldfidex(int fid, int auth, char **ep) 12099a747e4fSDavid du Colombier { 12109a747e4fSDavid du Colombier Fid *f; 12119a747e4fSDavid du Colombier 12129a747e4fSDavid du Colombier if((f = lookupfid(fid)) == nil){ 12139a747e4fSDavid du Colombier *ep = Ebadfid; 12149a747e4fSDavid du Colombier return nil; 12159a747e4fSDavid du Colombier } 12169a747e4fSDavid du Colombier 121750a9bdd4SDavid du Colombier if (auth != -1 && f->auth != auth) { 121850a9bdd4SDavid du Colombier *ep = Ebadfid; 121950a9bdd4SDavid du Colombier return nil; 122050a9bdd4SDavid du Colombier } 122150a9bdd4SDavid du Colombier 122250a9bdd4SDavid du Colombier if (!f->auth) { 12239a747e4fSDavid du Colombier if(userchange(f->u, ep) < 0) 12249a747e4fSDavid du Colombier return nil; 122550a9bdd4SDavid du Colombier } 12269a747e4fSDavid du Colombier 12279a747e4fSDavid du Colombier return f; 12289a747e4fSDavid du Colombier } 12299a747e4fSDavid du Colombier 123050a9bdd4SDavid du Colombier Fid* 123150a9bdd4SDavid du Colombier oldfid(int fid, char **ep) 123250a9bdd4SDavid du Colombier { 123350a9bdd4SDavid du Colombier return oldfidex(fid, 0, ep); 123450a9bdd4SDavid du Colombier } 123550a9bdd4SDavid du Colombier 123650a9bdd4SDavid du Colombier Fid* 123750a9bdd4SDavid du Colombier oldauthfid(int fid, void **magic, char **ep) 123850a9bdd4SDavid du Colombier { 123950a9bdd4SDavid du Colombier Fid *af; 124050a9bdd4SDavid du Colombier af = oldfidex(fid, 1, ep); 124150a9bdd4SDavid du Colombier if (af == nil) 124250a9bdd4SDavid du Colombier return nil; 124350a9bdd4SDavid du Colombier *magic = af->authmagic; 124450a9bdd4SDavid du Colombier return af; 124550a9bdd4SDavid du Colombier } 124650a9bdd4SDavid du Colombier 12479a747e4fSDavid du Colombier void 12489a747e4fSDavid du Colombier freefid(Fid *f) 12499a747e4fSDavid du Colombier { 12509a747e4fSDavid du Colombier if(f->prev) 12519a747e4fSDavid du Colombier f->prev->next = f->next; 12529a747e4fSDavid du Colombier else 12539a747e4fSDavid du Colombier fidtab[f->fid%nelem(fidtab)] = f->next; 12549a747e4fSDavid du Colombier if(f->next) 12559a747e4fSDavid du Colombier f->next->prev = f->prev; 12569a747e4fSDavid du Colombier if(f->dir) 12579a747e4fSDavid du Colombier closedir(f->dir); 12589a747e4fSDavid du Colombier if(f->fd) 12599a747e4fSDavid du Colombier close(f->fd); 12609a747e4fSDavid du Colombier free(f->path); 12619a747e4fSDavid du Colombier free(f); 12629a747e4fSDavid du Colombier } 12639a747e4fSDavid du Colombier 12649a747e4fSDavid du Colombier int 12659a747e4fSDavid du Colombier fidstat(Fid *fid, char **ep) 12669a747e4fSDavid du Colombier { 12679a747e4fSDavid du Colombier if(stat(fid->path, &fid->st) < 0){ 12689a747e4fSDavid du Colombier fprint(2, "fidstat(%s) failed\n", fid->path); 12699a747e4fSDavid du Colombier if(ep) 12709a747e4fSDavid du Colombier *ep = strerror(errno); 12719a747e4fSDavid du Colombier return -1; 12729a747e4fSDavid du Colombier } 12739a747e4fSDavid du Colombier if(S_ISDIR(fid->st.st_mode)) 12749a747e4fSDavid du Colombier fid->st.st_size = 0; 12759a747e4fSDavid du Colombier return 0; 12769a747e4fSDavid du Colombier } 12779a747e4fSDavid du Colombier 12789a747e4fSDavid du Colombier int 12799a747e4fSDavid du Colombier userchange(User *u, char **ep) 12809a747e4fSDavid du Colombier { 1281d9306527SDavid du Colombier if(defaultuser) 1282d9306527SDavid du Colombier return 0; 1283d9306527SDavid du Colombier 1284d9306527SDavid du Colombier if(setreuid(0, 0) < 0){ 12859a747e4fSDavid du Colombier fprint(2, "setreuid(0, 0) failed\n"); 12869a747e4fSDavid du Colombier *ep = "cannot setuid back to root"; 12879a747e4fSDavid du Colombier return -1; 12889a747e4fSDavid du Colombier } 12899a747e4fSDavid du Colombier 12909a747e4fSDavid du Colombier /* 12919a747e4fSDavid du Colombier * Initgroups does not appear to be SUSV standard. 12929a747e4fSDavid du Colombier * But it exists on SGI and on Linux, which makes me 12939a747e4fSDavid du Colombier * think it's standard enough. We have to do something 12949a747e4fSDavid du Colombier * like this, and the closest other function I can find is 12959a747e4fSDavid du Colombier * setgroups (which initgroups eventually calls). 12969a747e4fSDavid du Colombier * Setgroups is the same as far as standardization though, 12979a747e4fSDavid du Colombier * so we're stuck using a non-SUSV call. Sigh. 12989a747e4fSDavid du Colombier */ 12999a747e4fSDavid du Colombier if(initgroups(u->name, u->defaultgid) < 0) 13009a747e4fSDavid du Colombier fprint(2, "initgroups(%s) failed: %s\n", u->name, strerror(errno)); 13019a747e4fSDavid du Colombier 13029a747e4fSDavid du Colombier if(setreuid(-1, u->id) < 0){ 13039a747e4fSDavid du Colombier fprint(2, "setreuid(-1, %s) failed\n", u->name); 13049a747e4fSDavid du Colombier *ep = strerror(errno); 13059a747e4fSDavid du Colombier return -1; 13069a747e4fSDavid du Colombier } 13079a747e4fSDavid du Colombier 13089a747e4fSDavid du Colombier return 0; 13099a747e4fSDavid du Colombier } 13109a747e4fSDavid du Colombier 13119a747e4fSDavid du Colombier /* 13129a747e4fSDavid du Colombier * We do our own checking here, then switch to root temporarily 13139a747e4fSDavid du Colombier * to set our gid. In a perfect world, you'd be allowed to set your 13149a747e4fSDavid du Colombier * egid to any of the supplemental groups of your euid, but this 13159a747e4fSDavid du Colombier * is not the case on Linux 2.2.14 (and perhaps others). 13169a747e4fSDavid du Colombier * 13179a747e4fSDavid du Colombier * This is a race, of course, but it's a race against processes 13189a747e4fSDavid du Colombier * that can edit the group lists. If you can do that, you can 13199a747e4fSDavid du Colombier * change your own group without our help. 13209a747e4fSDavid du Colombier */ 13219a747e4fSDavid du Colombier int 13229a747e4fSDavid du Colombier groupchange(User *u, User *g, char **ep) 13239a747e4fSDavid du Colombier { 1324dc5a79c1SDavid du Colombier if(g == nil) 1325dc5a79c1SDavid du Colombier return -1; 13269a747e4fSDavid du Colombier if(!useringroup(u, g)){ 13279a747e4fSDavid du Colombier if(chatty9p) 13289a747e4fSDavid du Colombier fprint(2, "%s not in group %s\n", u->name, g->name); 13299a747e4fSDavid du Colombier *ep = Enotingroup; 13309a747e4fSDavid du Colombier return -1; 13319a747e4fSDavid du Colombier } 13329a747e4fSDavid du Colombier 13339a747e4fSDavid du Colombier setreuid(0,0); 13349a747e4fSDavid du Colombier if(setregid(-1, g->id) < 0){ 13359a747e4fSDavid du Colombier fprint(2, "setegid(%s/%d) failed in groupchange\n", g->name, g->id); 13369a747e4fSDavid du Colombier *ep = strerror(errno); 13379a747e4fSDavid du Colombier return -1; 13389a747e4fSDavid du Colombier } 13399a747e4fSDavid du Colombier if(userchange(u, ep) < 0) 13409a747e4fSDavid du Colombier return -1; 13419a747e4fSDavid du Colombier 13429a747e4fSDavid du Colombier return 0; 13439a747e4fSDavid du Colombier } 13449a747e4fSDavid du Colombier 13459a747e4fSDavid du Colombier 13469a747e4fSDavid du Colombier /* 13479a747e4fSDavid du Colombier * An attempt to enforce permissions by looking at the 13489a747e4fSDavid du Colombier * file system. Separation of checking permission and 13499a747e4fSDavid du Colombier * actually performing the action is a terrible idea, of 13509a747e4fSDavid du Colombier * course, so we use setreuid for most of the permission 13519a747e4fSDavid du Colombier * enforcement. This is here only so we can give errors 13529a747e4fSDavid du Colombier * on open(ORCLOSE) in some cases. 13539a747e4fSDavid du Colombier */ 13549a747e4fSDavid du Colombier int 13559a747e4fSDavid du Colombier userperm(User *u, char *path, int type, int need) 13569a747e4fSDavid du Colombier { 13579a747e4fSDavid du Colombier char *p, *q; 13589a747e4fSDavid du Colombier int i, have; 13599a747e4fSDavid du Colombier struct stat st; 13609a747e4fSDavid du Colombier User *g; 13619a747e4fSDavid du Colombier 13629a747e4fSDavid du Colombier switch(type){ 13639a747e4fSDavid du Colombier default: 13649a747e4fSDavid du Colombier fprint(2, "bad type %d in userperm\n", type); 13659a747e4fSDavid du Colombier return -1; 13669a747e4fSDavid du Colombier case Tdot: 13679a747e4fSDavid du Colombier if(stat(path, &st) < 0){ 13689a747e4fSDavid du Colombier fprint(2, "userperm: stat(%s) failed\n", path); 13699a747e4fSDavid du Colombier return -1; 13709a747e4fSDavid du Colombier } 13719a747e4fSDavid du Colombier break; 13729a747e4fSDavid du Colombier case Tdotdot: 13739a747e4fSDavid du Colombier p = estrdup(path); 13749a747e4fSDavid du Colombier if((q = strrchr(p, '/'))==nil){ 13759a747e4fSDavid du Colombier fprint(2, "userperm(%s, ..): bad path\n", p); 13769a747e4fSDavid du Colombier free(p); 13779a747e4fSDavid du Colombier return -1; 13789a747e4fSDavid du Colombier } 13799a747e4fSDavid du Colombier if(q > p) 13809a747e4fSDavid du Colombier *q = '\0'; 13819a747e4fSDavid du Colombier else 13829a747e4fSDavid du Colombier *(q+1) = '\0'; 13839a747e4fSDavid du Colombier if(stat(p, &st) < 0){ 13849a747e4fSDavid du Colombier fprint(2, "userperm: stat(%s) (dotdot of %s) failed\n", 13859a747e4fSDavid du Colombier p, path); 13869a747e4fSDavid du Colombier free(p); 13879a747e4fSDavid du Colombier return -1; 13889a747e4fSDavid du Colombier } 13899a747e4fSDavid du Colombier free(p); 13909a747e4fSDavid du Colombier break; 13919a747e4fSDavid du Colombier } 13929a747e4fSDavid du Colombier 13939a747e4fSDavid du Colombier if(u == none){ 13949a747e4fSDavid du Colombier fprint(2, "userperm: none wants %d in 0%luo\n", need, st.st_mode); 13959a747e4fSDavid du Colombier have = st.st_mode&7; 13969a747e4fSDavid du Colombier if((have&need)==need) 13979a747e4fSDavid du Colombier return 0; 13989a747e4fSDavid du Colombier return -1; 13999a747e4fSDavid du Colombier } 14009a747e4fSDavid du Colombier have = st.st_mode&7; 14019a747e4fSDavid du Colombier if((uid_t)u->id == st.st_uid) 14029a747e4fSDavid du Colombier have |= (st.st_mode>>6)&7; 14039a747e4fSDavid du Colombier if((have&need)==need) 14049a747e4fSDavid du Colombier return 0; 14059a747e4fSDavid du Colombier if(((have|((st.st_mode>>3)&7))&need) != need) /* group won't help */ 14069a747e4fSDavid du Colombier return -1; 14079a747e4fSDavid du Colombier g = gid2user(st.st_gid); 14089a747e4fSDavid du Colombier for(i=0; i<g->nmem; i++){ 14099a747e4fSDavid du Colombier if(strcmp(g->mem[i], u->name) == 0){ 14109a747e4fSDavid du Colombier have |= (st.st_mode>>3)&7; 14119a747e4fSDavid du Colombier break; 14129a747e4fSDavid du Colombier } 14139a747e4fSDavid du Colombier } 14149a747e4fSDavid du Colombier if((have&need)==need) 14159a747e4fSDavid du Colombier return 0; 14169a747e4fSDavid du Colombier return -1; 14179a747e4fSDavid du Colombier } 14189a747e4fSDavid du Colombier 14199a747e4fSDavid du Colombier int 14209a747e4fSDavid du Colombier userwalk(User *u, char **path, char *elem, Qid *qid, char **ep) 14219a747e4fSDavid du Colombier { 14229a747e4fSDavid du Colombier char *npath; 14239a747e4fSDavid du Colombier struct stat st; 14249a747e4fSDavid du Colombier 14259a747e4fSDavid du Colombier npath = estrpath(*path, elem); 14269a747e4fSDavid du Colombier if(stat(npath, &st) < 0){ 14279a747e4fSDavid du Colombier free(npath); 14289a747e4fSDavid du Colombier *ep = strerror(errno); 14299a747e4fSDavid du Colombier return -1; 14309a747e4fSDavid du Colombier } 14319a747e4fSDavid du Colombier *qid = stat2qid(&st); 14329a747e4fSDavid du Colombier free(*path); 14339a747e4fSDavid du Colombier *path = npath; 14349a747e4fSDavid du Colombier return 0; 14359a747e4fSDavid du Colombier } 14369a747e4fSDavid du Colombier 14379a747e4fSDavid du Colombier int 14389a747e4fSDavid du Colombier useropen(Fid *fid, int omode, char **ep) 14399a747e4fSDavid du Colombier { 14409a747e4fSDavid du Colombier int a, o; 14419a747e4fSDavid du Colombier 14429a747e4fSDavid du Colombier /* 14439a747e4fSDavid du Colombier * Check this anyway, to try to head off problems later. 14449a747e4fSDavid du Colombier */ 14459a747e4fSDavid du Colombier if((omode&ORCLOSE) && userperm(fid->u, fid->path, Tdotdot, W_OK) < 0){ 14469a747e4fSDavid du Colombier *ep = Eperm; 14479a747e4fSDavid du Colombier return -1; 14489a747e4fSDavid du Colombier } 14499a747e4fSDavid du Colombier 14509a747e4fSDavid du Colombier switch(omode&3){ 14519a747e4fSDavid du Colombier default: 14529a747e4fSDavid du Colombier *ep = "programmer error"; 14539a747e4fSDavid du Colombier return -1; 14549a747e4fSDavid du Colombier case OREAD: 14551118d624SDavid du Colombier a = R_OK; 14569a747e4fSDavid du Colombier o = O_RDONLY; 14579a747e4fSDavid du Colombier break; 14589a747e4fSDavid du Colombier case ORDWR: 14599a747e4fSDavid du Colombier a = R_OK|W_OK; 14609a747e4fSDavid du Colombier o = O_RDWR; 14619a747e4fSDavid du Colombier break; 14629a747e4fSDavid du Colombier case OWRITE: 1463e5495c06SDavid du Colombier a = W_OK; 14649a747e4fSDavid du Colombier o = O_WRONLY; 14659a747e4fSDavid du Colombier break; 14669a747e4fSDavid du Colombier case OEXEC: 14679a747e4fSDavid du Colombier a = X_OK; 14689a747e4fSDavid du Colombier o = O_RDONLY; 14699a747e4fSDavid du Colombier break; 14709a747e4fSDavid du Colombier } 14719a747e4fSDavid du Colombier if(omode & OTRUNC){ 14729a747e4fSDavid du Colombier a |= W_OK; 14739a747e4fSDavid du Colombier o |= O_TRUNC; 14749a747e4fSDavid du Colombier } 14759a747e4fSDavid du Colombier 14769a747e4fSDavid du Colombier if(S_ISDIR(fid->st.st_mode)){ 14779a747e4fSDavid du Colombier if(a != R_OK){ 14789a747e4fSDavid du Colombier fprint(2, "attempt by %s to open dir %d\n", fid->u->name, omode); 14799a747e4fSDavid du Colombier *ep = Eperm; 14809a747e4fSDavid du Colombier return -1; 14819a747e4fSDavid du Colombier } 14829a747e4fSDavid du Colombier if((fid->dir = opendir(fid->path)) == nil){ 14839a747e4fSDavid du Colombier *ep = strerror(errno); 14849a747e4fSDavid du Colombier return -1; 14859a747e4fSDavid du Colombier } 14869a747e4fSDavid du Colombier }else{ 14870c0e9c72SDavid du Colombier /* 14880c0e9c72SDavid du Colombier * This is wrong because access used the real uid 14890c0e9c72SDavid du Colombier * and not the effective uid. Let the open sort it out. 14900c0e9c72SDavid du Colombier * 14919a747e4fSDavid du Colombier if(access(fid->path, a) < 0){ 14929a747e4fSDavid du Colombier *ep = strerror(errno); 14939a747e4fSDavid du Colombier return -1; 14949a747e4fSDavid du Colombier } 14950c0e9c72SDavid du Colombier * 14960c0e9c72SDavid du Colombier */ 14979a747e4fSDavid du Colombier if((fid->fd = open(fid->path, o)) < 0){ 14989a747e4fSDavid du Colombier *ep = strerror(errno); 14999a747e4fSDavid du Colombier return -1; 15009a747e4fSDavid du Colombier } 15019a747e4fSDavid du Colombier } 15029a747e4fSDavid du Colombier fid->omode = omode; 15039a747e4fSDavid du Colombier return 0; 15049a747e4fSDavid du Colombier } 15059a747e4fSDavid du Colombier 15069a747e4fSDavid du Colombier int 15079a747e4fSDavid du Colombier usercreate(Fid *fid, char *elem, int omode, long perm, char **ep) 15089a747e4fSDavid du Colombier { 15099a747e4fSDavid du Colombier int o, m; 15109a747e4fSDavid du Colombier char *opath, *npath; 15119a747e4fSDavid du Colombier struct stat st, parent; 15129a747e4fSDavid du Colombier 15139a747e4fSDavid du Colombier if(stat(fid->path, &parent) < 0){ 15149a747e4fSDavid du Colombier *ep = strerror(errno); 15159a747e4fSDavid du Colombier return -1; 15169a747e4fSDavid du Colombier } 15179a747e4fSDavid du Colombier 15189a747e4fSDavid du Colombier /* 15199a747e4fSDavid du Colombier * Change group so that created file has expected group 15209a747e4fSDavid du Colombier * by Plan 9 semantics. If that fails, might as well go 15219a747e4fSDavid du Colombier * with the user's default group. 15229a747e4fSDavid du Colombier */ 15239a747e4fSDavid du Colombier if(groupchange(fid->u, gid2user(parent.st_gid), ep) < 0 15249a747e4fSDavid du Colombier && groupchange(fid->u, gid2user(fid->u->defaultgid), ep) < 0) 15259a747e4fSDavid du Colombier return -1; 15269a747e4fSDavid du Colombier 15279a747e4fSDavid du Colombier m = (perm & DMDIR) ? 0777 : 0666; 15289a747e4fSDavid du Colombier perm = perm & (~m | (fid->st.st_mode & m)); 15299a747e4fSDavid du Colombier 15309a747e4fSDavid du Colombier npath = estrpath(fid->path, elem); 15319a747e4fSDavid du Colombier if(perm & DMDIR){ 15329a747e4fSDavid du Colombier if((omode&~ORCLOSE) != OREAD){ 15339a747e4fSDavid du Colombier *ep = Eperm; 15349a747e4fSDavid du Colombier free(npath); 15359a747e4fSDavid du Colombier return -1; 15369a747e4fSDavid du Colombier } 15379a747e4fSDavid du Colombier if(stat(npath, &st) >= 0 || errno != ENOENT){ 15389a747e4fSDavid du Colombier *ep = Eexist; 15399a747e4fSDavid du Colombier free(npath); 15409a747e4fSDavid du Colombier return -1; 15419a747e4fSDavid du Colombier } 15429a747e4fSDavid du Colombier /* race */ 15439a747e4fSDavid du Colombier if(mkdir(npath, perm&0777) < 0){ 15449a747e4fSDavid du Colombier *ep = strerror(errno); 15459a747e4fSDavid du Colombier free(npath); 15469a747e4fSDavid du Colombier return -1; 15479a747e4fSDavid du Colombier } 15489a747e4fSDavid du Colombier if((fid->dir = opendir(npath)) == nil){ 15499a747e4fSDavid du Colombier *ep = strerror(errno); 15509a747e4fSDavid du Colombier remove(npath); /* race */ 15519a747e4fSDavid du Colombier free(npath); 15529a747e4fSDavid du Colombier return -1; 15539a747e4fSDavid du Colombier } 15549a747e4fSDavid du Colombier }else{ 15559a747e4fSDavid du Colombier o = O_CREAT|O_EXCL; 15569a747e4fSDavid du Colombier switch(omode&3){ 15579a747e4fSDavid du Colombier default: 15589a747e4fSDavid du Colombier *ep = "programmer error"; 15599a747e4fSDavid du Colombier return -1; 15609a747e4fSDavid du Colombier case OREAD: 15619a747e4fSDavid du Colombier case OEXEC: 15629a747e4fSDavid du Colombier o |= O_RDONLY; 15639a747e4fSDavid du Colombier break; 15649a747e4fSDavid du Colombier case ORDWR: 15659a747e4fSDavid du Colombier o |= O_RDWR; 15669a747e4fSDavid du Colombier break; 15679a747e4fSDavid du Colombier case OWRITE: 15689a747e4fSDavid du Colombier o |= O_WRONLY; 15699a747e4fSDavid du Colombier break; 15709a747e4fSDavid du Colombier } 15719a747e4fSDavid du Colombier if(omode & OTRUNC) 15729a747e4fSDavid du Colombier o |= O_TRUNC; 15739a747e4fSDavid du Colombier if((fid->fd = open(npath, o, perm&0777)) < 0){ 15749a747e4fSDavid du Colombier if(chatty9p) 15759a747e4fSDavid du Colombier fprint(2, "create(%s, 0x%x, 0%o) failed\n", npath, o, perm&0777); 15769a747e4fSDavid du Colombier *ep = strerror(errno); 15779a747e4fSDavid du Colombier free(npath); 15789a747e4fSDavid du Colombier return -1; 15799a747e4fSDavid du Colombier } 15809a747e4fSDavid du Colombier } 15819a747e4fSDavid du Colombier 15829a747e4fSDavid du Colombier opath = fid->path; 15839a747e4fSDavid du Colombier fid->path = npath; 15849a747e4fSDavid du Colombier if(fidstat(fid, ep) < 0){ 15859a747e4fSDavid du Colombier fprint(2, "stat after create on %s failed\n", npath); 15869a747e4fSDavid du Colombier remove(npath); /* race */ 15879a747e4fSDavid du Colombier free(npath); 15889a747e4fSDavid du Colombier fid->path = opath; 15899a747e4fSDavid du Colombier if(fid->fd >= 0){ 15909a747e4fSDavid du Colombier close(fid->fd); 15919a747e4fSDavid du Colombier fid->fd = -1; 15929a747e4fSDavid du Colombier }else{ 15939a747e4fSDavid du Colombier closedir(fid->dir); 15949a747e4fSDavid du Colombier fid->dir = nil; 15959a747e4fSDavid du Colombier } 15969a747e4fSDavid du Colombier return -1; 15979a747e4fSDavid du Colombier } 15989a747e4fSDavid du Colombier fid->omode = omode; 15999a747e4fSDavid du Colombier free(opath); 16009a747e4fSDavid du Colombier return 0; 16019a747e4fSDavid du Colombier } 16029a747e4fSDavid du Colombier 16039a747e4fSDavid du Colombier int 16049a747e4fSDavid du Colombier userremove(Fid *fid, char **ep) 16059a747e4fSDavid du Colombier { 16069a747e4fSDavid du Colombier if(remove(fid->path) < 0){ 16079a747e4fSDavid du Colombier *ep = strerror(errno); 16089a747e4fSDavid du Colombier return -1; 16099a747e4fSDavid du Colombier } 16109a747e4fSDavid du Colombier return 0; 16119a747e4fSDavid du Colombier } 16129a747e4fSDavid du Colombier 16139a747e4fSDavid du Colombier void 16149a747e4fSDavid du Colombier usage(void) 16159a747e4fSDavid du Colombier { 16169a747e4fSDavid du Colombier fprint(2, "usage: u9fs [-Dnz] [-a authmethod] [-m msize] [-u user] [root]\n"); 16179a747e4fSDavid du Colombier exit(1); 16189a747e4fSDavid du Colombier } 16199a747e4fSDavid du Colombier 16209a747e4fSDavid du Colombier int 16219a747e4fSDavid du Colombier main(int argc, char **argv) 16229a747e4fSDavid du Colombier { 16239a747e4fSDavid du Colombier char *authtype; 16249a747e4fSDavid du Colombier int i; 16259a747e4fSDavid du Colombier int fd; 16269a747e4fSDavid du Colombier int logflag; 16279a747e4fSDavid du Colombier 16289a747e4fSDavid du Colombier auth = authmethods[0]; 16299a747e4fSDavid du Colombier logflag = O_WRONLY|O_APPEND|O_CREAT; 16309a747e4fSDavid du Colombier ARGBEGIN{ 16319a747e4fSDavid du Colombier case 'D': 16329a747e4fSDavid du Colombier chatty9p = 1; 16339a747e4fSDavid du Colombier break; 16349a747e4fSDavid du Colombier case 'a': 16359a747e4fSDavid du Colombier authtype = EARGF(usage()); 16369a747e4fSDavid du Colombier auth = nil; 16379a747e4fSDavid du Colombier for(i=0; i<nelem(authmethods); i++) 16389a747e4fSDavid du Colombier if(strcmp(authmethods[i]->name, authtype)==0) 16399a747e4fSDavid du Colombier auth = authmethods[i]; 16409a747e4fSDavid du Colombier if(auth == nil) 16419a747e4fSDavid du Colombier sysfatal("unknown auth type '%s'", authtype); 16429a747e4fSDavid du Colombier break; 16439a747e4fSDavid du Colombier case 'A': 16449a747e4fSDavid du Colombier autharg = EARGF(usage()); 16459a747e4fSDavid du Colombier break; 16469a747e4fSDavid du Colombier case 'l': 16479a747e4fSDavid du Colombier logfile = EARGF(usage()); 16489a747e4fSDavid du Colombier break; 16499a747e4fSDavid du Colombier case 'm': 16509a747e4fSDavid du Colombier msize = strtol(EARGF(usage()), 0, 0); 16519a747e4fSDavid du Colombier break; 16529a747e4fSDavid du Colombier case 'n': 16539a747e4fSDavid du Colombier network = 0; 16549a747e4fSDavid du Colombier break; 16559a747e4fSDavid du Colombier case 'u': 16569a747e4fSDavid du Colombier defaultuser = EARGF(usage()); 16579a747e4fSDavid du Colombier break; 16589a747e4fSDavid du Colombier case 'z': 16599a747e4fSDavid du Colombier logflag |= O_TRUNC; 16609a747e4fSDavid du Colombier }ARGEND 16619a747e4fSDavid du Colombier 16629a747e4fSDavid du Colombier if(argc > 1) 16639a747e4fSDavid du Colombier usage(); 16649a747e4fSDavid du Colombier 16659a747e4fSDavid du Colombier fd = open(logfile, logflag, 0666); 16669a747e4fSDavid du Colombier if(fd < 0) 16679a747e4fSDavid du Colombier sysfatal("cannot open log '%s'", logfile); 16689a747e4fSDavid du Colombier 16699a747e4fSDavid du Colombier if(dup2(fd, 2) < 0) 16709a747e4fSDavid du Colombier sysfatal("cannot dup fd onto stderr"); 16719a747e4fSDavid du Colombier fprint(2, "u9fs\nkill %d\n", (int)getpid()); 16729a747e4fSDavid du Colombier 16739a747e4fSDavid du Colombier fmtinstall('F', fcallconv); 16749a747e4fSDavid du Colombier fmtinstall('D', dirconv); 16759a747e4fSDavid du Colombier fmtinstall('M', dirmodeconv); 16769a747e4fSDavid du Colombier 16779a747e4fSDavid du Colombier rxbuf = emalloc(msize); 16789a747e4fSDavid du Colombier txbuf = emalloc(msize); 16799a747e4fSDavid du Colombier databuf = emalloc(msize); 16809a747e4fSDavid du Colombier 16819a747e4fSDavid du Colombier if(auth->init) 16829a747e4fSDavid du Colombier auth->init(); 16839a747e4fSDavid du Colombier 16849a747e4fSDavid du Colombier if(network) 16859a747e4fSDavid du Colombier getremotehostname(remotehostname, sizeof remotehostname); 16869a747e4fSDavid du Colombier 16879a747e4fSDavid du Colombier if(gethostname(hostname, sizeof hostname) < 0) 16889a747e4fSDavid du Colombier strcpy(hostname, "gnot"); 16899a747e4fSDavid du Colombier 16909a747e4fSDavid du Colombier umask(0); 16919a747e4fSDavid du Colombier 16929a747e4fSDavid du Colombier if(argc == 1) 16939a747e4fSDavid du Colombier if(chroot(argv[0]) < 0) 16949a747e4fSDavid du Colombier sysfatal("chroot '%s' failed", argv[0]); 16959a747e4fSDavid du Colombier 16969a747e4fSDavid du Colombier none = uname2user("none"); 16979a747e4fSDavid du Colombier serve(0, 1); 16989a747e4fSDavid du Colombier return 0; 16999a747e4fSDavid du Colombier } 1700