13e12c5d1SDavid du Colombier #include "u.h" 23e12c5d1SDavid du Colombier #include <sys/types.h> 33e12c5d1SDavid du Colombier #include <sys/stat.h> 43e12c5d1SDavid du Colombier #include "libc.h" 53e12c5d1SDavid du Colombier #include "9p.h" 63e12c5d1SDavid du Colombier #include "stdio.h" 73e12c5d1SDavid du Colombier #include "setjmp.h" 83e12c5d1SDavid du Colombier #include "pwd.h" 93e12c5d1SDavid du Colombier #include "grp.h" 103e12c5d1SDavid du Colombier 113e12c5d1SDavid du Colombier #define DBG(f) 123e12c5d1SDavid du Colombier 133e12c5d1SDavid du Colombier struct group *getgrent(void); 143e12c5d1SDavid du Colombier struct passwd *getpwent(void); 153e12c5d1SDavid du Colombier 163e12c5d1SDavid du Colombier #ifdef SYSV 173e12c5d1SDavid du Colombier # include <dirent.h> 183e12c5d1SDavid du Colombier # define DTYPE struct dirent 19219b2ee8SDavid du Colombier # define SOCKETS 203e12c5d1SDavid du Colombier #endif 213e12c5d1SDavid du Colombier #ifdef V10 223e12c5d1SDavid du Colombier # include <ndir.h> 233e12c5d1SDavid du Colombier # define DTYPE struct direct 243e12c5d1SDavid du Colombier #endif 253e12c5d1SDavid du Colombier #ifdef BSD 263e12c5d1SDavid du Colombier # include <sys/dir.h> 273e12c5d1SDavid du Colombier # define DTYPE struct direct 28219b2ee8SDavid du Colombier # define SOCKETS 29219b2ee8SDavid du Colombier #endif 30219b2ee8SDavid du Colombier #ifdef SOCKETS 31219b2ee8SDavid du Colombier # define sendmsg __sendmsg 32219b2ee8SDavid du Colombier # include <sys/socket.h> 33219b2ee8SDavid du Colombier # include <netinet/in.h> 34219b2ee8SDavid du Colombier # include <netdb.h> 35*7dd7cddfSDavid du Colombier # include <arpa/inet.h> 36219b2ee8SDavid du Colombier # undef sendmsg 37219b2ee8SDavid du Colombier char bsdhost[256]; 38219b2ee8SDavid du Colombier void remotehostname(void); 39*7dd7cddfSDavid du Colombier char ipaddr[20]; 403e12c5d1SDavid du Colombier #endif 413e12c5d1SDavid du Colombier 423e12c5d1SDavid du Colombier typedef struct File File; 433e12c5d1SDavid du Colombier typedef struct Rfile Rfile; 443e12c5d1SDavid du Colombier typedef struct Fd Fd; 453e12c5d1SDavid du Colombier typedef struct Pass Pass; 463e12c5d1SDavid du Colombier 473e12c5d1SDavid du Colombier struct Fd{ 483e12c5d1SDavid du Colombier int ref; 493e12c5d1SDavid du Colombier Ulong offset; 503e12c5d1SDavid du Colombier int fd; 513e12c5d1SDavid du Colombier DIR *dir; 523e12c5d1SDavid du Colombier }; 533e12c5d1SDavid du Colombier 543e12c5d1SDavid du Colombier struct Rfile{ 553e12c5d1SDavid du Colombier int busy; 563e12c5d1SDavid du Colombier int uid; 57219b2ee8SDavid du Colombier int rclose; 583e12c5d1SDavid du Colombier File *file; 593e12c5d1SDavid du Colombier Fd *fd; 603e12c5d1SDavid du Colombier }; 613e12c5d1SDavid du Colombier 623e12c5d1SDavid du Colombier struct File{ 633e12c5d1SDavid du Colombier int ref; 643e12c5d1SDavid du Colombier char *path; 653e12c5d1SDavid du Colombier char *name; 663e12c5d1SDavid du Colombier Qid qid; 673e12c5d1SDavid du Colombier struct stat stbuf; 683e12c5d1SDavid du Colombier }; 693e12c5d1SDavid du Colombier 703e12c5d1SDavid du Colombier struct Pass{ 713e12c5d1SDavid du Colombier int id; 723e12c5d1SDavid du Colombier int gid; 733e12c5d1SDavid du Colombier char *name; 743e12c5d1SDavid du Colombier Pass *next; 75*7dd7cddfSDavid du Colombier Pass *nnext; 76*7dd7cddfSDavid du Colombier int nmem; 77*7dd7cddfSDavid du Colombier gid_t *mem; 783e12c5d1SDavid du Colombier }; 793e12c5d1SDavid du Colombier 803e12c5d1SDavid du Colombier char data[2][MAXMSG+MAXFDATA]; 813e12c5d1SDavid du Colombier char tdata[MAXMSG+MAXFDATA]; 823e12c5d1SDavid du Colombier char rdata[MAXFDATA]; 833e12c5d1SDavid du Colombier Fcall rhdr; 843e12c5d1SDavid du Colombier Fcall thdr; 853e12c5d1SDavid du Colombier Rfile *rfile; 863e12c5d1SDavid du Colombier File *file0; 873e12c5d1SDavid du Colombier int nrfilealloc; 883e12c5d1SDavid du Colombier jmp_buf loopjmp; 893e12c5d1SDavid du Colombier Pass* uid[256]; 903e12c5d1SDavid du Colombier Pass* gid[256]; 91*7dd7cddfSDavid du Colombier Pass* uidname[256]; 92*7dd7cddfSDavid du Colombier Pass* gidname[256]; 93*7dd7cddfSDavid du Colombier int curuid; 943e12c5d1SDavid du Colombier int devallowed; 953e12c5d1SDavid du Colombier int connected; 96*7dd7cddfSDavid du Colombier int readonly; 97*7dd7cddfSDavid du Colombier int myuid; 98*7dd7cddfSDavid du Colombier char *onlyuser; 993e12c5d1SDavid du Colombier 1003e12c5d1SDavid du Colombier void io(void); 1013e12c5d1SDavid du Colombier void error(char*); 1023e12c5d1SDavid du Colombier char *mfmt(Fcall*); 103*7dd7cddfSDavid du Colombier void sendmsg(const char*); 1043e12c5d1SDavid du Colombier int okfid(int); 1053e12c5d1SDavid du Colombier Rfile* rfilefid(void); 1063e12c5d1SDavid du Colombier File* newfile(void); 1073e12c5d1SDavid du Colombier void* erealloc(void*, unsigned); 1083e12c5d1SDavid du Colombier char* estrdup(char*); 109*7dd7cddfSDavid du Colombier const char* dostat(File*, char*); 1103e12c5d1SDavid du Colombier char* bldpath(char*, char*, char*); 1113e12c5d1SDavid du Colombier Ulong qid(struct stat*); 112219b2ee8SDavid du Colombier Ulong vers(struct stat*); 113*7dd7cddfSDavid du Colombier void errjmp(const char*); 1143e12c5d1SDavid du Colombier int omode(int); 1153e12c5d1SDavid du Colombier char* id2name(Pass**, int); 116*7dd7cddfSDavid du Colombier Pass* id2pass(Pass**, int); 1173e12c5d1SDavid du Colombier Pass* name2pass(Pass**, char*); 1183e12c5d1SDavid du Colombier void getpwdf(void); 1193e12c5d1SDavid du Colombier void getgrpf(void); 120*7dd7cddfSDavid du Colombier int hash(char*); 121*7dd7cddfSDavid du Colombier void setupuser(int); 1223e12c5d1SDavid du Colombier 123219b2ee8SDavid du Colombier void rsession(void); 1243e12c5d1SDavid du Colombier void rattach(void); 1253e12c5d1SDavid du Colombier void rflush(void); 1263e12c5d1SDavid du Colombier void rclone(void); 1273e12c5d1SDavid du Colombier void rwalk(void); 1283e12c5d1SDavid du Colombier void ropen(void); 1293e12c5d1SDavid du Colombier void rcreate(void); 1303e12c5d1SDavid du Colombier void rread(void); 1313e12c5d1SDavid du Colombier void rwrite(void); 1323e12c5d1SDavid du Colombier void rclunk(int); 1333e12c5d1SDavid du Colombier void rstat(void); 1343e12c5d1SDavid du Colombier void rwstat(void); 1353e12c5d1SDavid du Colombier void rclwalk(void); 1363e12c5d1SDavid du Colombier 1373e12c5d1SDavid du Colombier char Eauth[] = "authentication failed"; 1383e12c5d1SDavid du Colombier char Eperm[] = "permission denied"; 1393e12c5d1SDavid du Colombier char Ebadfid[] = "fid unknown or out of range"; 1403e12c5d1SDavid du Colombier char Efidactive[] = "fid already in use"; 1413e12c5d1SDavid du Colombier char Eopen[] = "file is open"; 1423e12c5d1SDavid du Colombier char Emode[] = "invalid open mode"; 1433e12c5d1SDavid du Colombier char Especial[] = "no access to special file"; 1443e12c5d1SDavid du Colombier char Especial0[] = "already attached without access to special files"; 1453e12c5d1SDavid du Colombier char Especial1[] = "already attached with access to special files"; 1463e12c5d1SDavid du Colombier char Enotopen[] = "file is not open"; 1473e12c5d1SDavid du Colombier char Etoolarge[] = "i/o count too large"; 1483e12c5d1SDavid du Colombier char Ebaddir[] = "i/o error on directory"; 1493e12c5d1SDavid du Colombier char Eunknown[] = "unknown user or group"; 1503e12c5d1SDavid du Colombier char Euid[] = "can't set uid"; 1513e12c5d1SDavid du Colombier char Egid[] = "can't set gid"; 1523e12c5d1SDavid du Colombier char Eowner[] = "not owner"; 1533e12c5d1SDavid du Colombier 154*7dd7cddfSDavid du Colombier void 155*7dd7cddfSDavid du Colombier usage(void) 156*7dd7cddfSDavid du Colombier { 157*7dd7cddfSDavid du Colombier fprintf(stderr, "u9fs [-r] [-u user uid]\n"); 158*7dd7cddfSDavid du Colombier exit(1); 159*7dd7cddfSDavid du Colombier } 160*7dd7cddfSDavid du Colombier 1613e12c5d1SDavid du Colombier int 1623e12c5d1SDavid du Colombier main(int argc, char *argv[]) 1633e12c5d1SDavid du Colombier { 164*7dd7cddfSDavid du Colombier char *s; 165*7dd7cddfSDavid du Colombier int onlyuid; 166*7dd7cddfSDavid du Colombier 167*7dd7cddfSDavid du Colombier # ifdef LOG 1683e12c5d1SDavid du Colombier freopen(LOG, "a", stderr); 169*7dd7cddfSDavid du Colombier # endif 170*7dd7cddfSDavid du Colombier 1713e12c5d1SDavid du Colombier setbuf(stderr, (void*)0); 1723e12c5d1SDavid du Colombier DBG(fprintf(stderr, "u9fs\nkill %d\n", getpid())); 173*7dd7cddfSDavid du Colombier 174*7dd7cddfSDavid du Colombier onlyuid = -1; 175*7dd7cddfSDavid du Colombier ARGBEGIN{ 176*7dd7cddfSDavid du Colombier case 'r': 177*7dd7cddfSDavid du Colombier readonly++; 178*7dd7cddfSDavid du Colombier break; 179*7dd7cddfSDavid du Colombier case 'u': 180*7dd7cddfSDavid du Colombier onlyuser = ARGF(); 181*7dd7cddfSDavid du Colombier if(onlyuser == 0) 182*7dd7cddfSDavid du Colombier usage(); 183*7dd7cddfSDavid du Colombier s = ARGF(); 184*7dd7cddfSDavid du Colombier if(s == 0) 185*7dd7cddfSDavid du Colombier usage(); 186*7dd7cddfSDavid du Colombier onlyuid = atoi(s); 187*7dd7cddfSDavid du Colombier break; 188*7dd7cddfSDavid du Colombier default: 189*7dd7cddfSDavid du Colombier usage(); 190*7dd7cddfSDavid du Colombier break; 191*7dd7cddfSDavid du Colombier }ARGEND 192*7dd7cddfSDavid du Colombier 193*7dd7cddfSDavid du Colombier if(argc) 194*7dd7cddfSDavid du Colombier usage(); 195219b2ee8SDavid du Colombier 196219b2ee8SDavid du Colombier # ifdef SOCKETS 197*7dd7cddfSDavid du Colombier if(!onlyuser) 198219b2ee8SDavid du Colombier remotehostname(); 199219b2ee8SDavid du Colombier # endif 200219b2ee8SDavid du Colombier 201*7dd7cddfSDavid du Colombier setreuid(0, 0); 202*7dd7cddfSDavid du Colombier myuid = geteuid(); 203*7dd7cddfSDavid du Colombier if(onlyuser && myuid != onlyuid) 204*7dd7cddfSDavid du Colombier error("invalid uid"); 205*7dd7cddfSDavid du Colombier 2063e12c5d1SDavid du Colombier io(); 2073e12c5d1SDavid du Colombier return 0; 2083e12c5d1SDavid du Colombier } 2093e12c5d1SDavid du Colombier 2103e12c5d1SDavid du Colombier void 2113e12c5d1SDavid du Colombier io(void) 2123e12c5d1SDavid du Colombier { 2133e12c5d1SDavid du Colombier int m; 2143e12c5d1SDavid du Colombier static int toggle, ndata; 2153e12c5d1SDavid du Colombier char *datap; 2163e12c5d1SDavid du Colombier 2173e12c5d1SDavid du Colombier /* 2183e12c5d1SDavid du Colombier * TCP does not preserve record boundaries; this dance works around 2193e12c5d1SDavid du Colombier * the problem. 2203e12c5d1SDavid du Colombier */ 2213e12c5d1SDavid du Colombier setjmp(loopjmp); 2223e12c5d1SDavid du Colombier 2233e12c5d1SDavid du Colombier /* 2243e12c5d1SDavid du Colombier * Invariant: data[toggle] has ndata bytes already 2253e12c5d1SDavid du Colombier */ 2263e12c5d1SDavid du Colombier loop: 2273e12c5d1SDavid du Colombier datap = data[toggle]; 2283e12c5d1SDavid du Colombier toggle ^= 1; 2293e12c5d1SDavid du Colombier for(;;){ 2303e12c5d1SDavid du Colombier if(ndata){ 2313e12c5d1SDavid du Colombier m = convM2S(datap, &rhdr, ndata); 2323e12c5d1SDavid du Colombier /* m is number of bytes more than a full message */ 2333e12c5d1SDavid du Colombier if(m >= 0){ 2343e12c5d1SDavid du Colombier memmove(data[toggle], datap+(ndata-m), m); 2353e12c5d1SDavid du Colombier ndata = m; 2363e12c5d1SDavid du Colombier break; 2373e12c5d1SDavid du Colombier } 2383e12c5d1SDavid du Colombier } 2393e12c5d1SDavid du Colombier m = read(0, datap+ndata, (MAXMSG+MAXFDATA)-ndata); 240*7dd7cddfSDavid du Colombier if(m == 0){ 241*7dd7cddfSDavid du Colombier fprintf(stderr, "u9fs: eof\n"); 242*7dd7cddfSDavid du Colombier exit(1); 243*7dd7cddfSDavid du Colombier } 244*7dd7cddfSDavid du Colombier if(m < 0) 2453e12c5d1SDavid du Colombier error("read"); 2463e12c5d1SDavid du Colombier ndata += m; 2473e12c5d1SDavid du Colombier } 2483e12c5d1SDavid du Colombier 2493e12c5d1SDavid du Colombier thdr.type = rhdr.type+1; 2503e12c5d1SDavid du Colombier thdr.tag = rhdr.tag; 2513e12c5d1SDavid du Colombier thdr.fid = rhdr.fid; 2523e12c5d1SDavid du Colombier DBG(fprintf(stderr, ">> %s\n", mfmt(&rhdr))); 2533e12c5d1SDavid du Colombier switch(rhdr.type){ 2543e12c5d1SDavid du Colombier case Tnop: 2553e12c5d1SDavid du Colombier case Tflush: /* this is a synchronous fs; easy */ 2563e12c5d1SDavid du Colombier break; 257219b2ee8SDavid du Colombier case Tsession: 258219b2ee8SDavid du Colombier rsession(); 2593e12c5d1SDavid du Colombier break; 2603e12c5d1SDavid du Colombier case Tattach: 2613e12c5d1SDavid du Colombier rattach(); 2623e12c5d1SDavid du Colombier break; 2633e12c5d1SDavid du Colombier case Tclone: 2643e12c5d1SDavid du Colombier rclone(); 2653e12c5d1SDavid du Colombier break; 2663e12c5d1SDavid du Colombier case Twalk: 2673e12c5d1SDavid du Colombier rwalk(); 2683e12c5d1SDavid du Colombier break; 2693e12c5d1SDavid du Colombier case Tstat: 2703e12c5d1SDavid du Colombier rstat(); 2713e12c5d1SDavid du Colombier break; 2723e12c5d1SDavid du Colombier case Twstat: 2733e12c5d1SDavid du Colombier rwstat(); 2743e12c5d1SDavid du Colombier break; 2753e12c5d1SDavid du Colombier case Topen: 2763e12c5d1SDavid du Colombier ropen(); 2773e12c5d1SDavid du Colombier break; 2783e12c5d1SDavid du Colombier case Tcreate: 2793e12c5d1SDavid du Colombier rcreate(); 2803e12c5d1SDavid du Colombier break; 2813e12c5d1SDavid du Colombier case Tread: 2823e12c5d1SDavid du Colombier rread(); 2833e12c5d1SDavid du Colombier break; 2843e12c5d1SDavid du Colombier case Twrite: 2853e12c5d1SDavid du Colombier rwrite(); 2863e12c5d1SDavid du Colombier break; 2873e12c5d1SDavid du Colombier case Tclunk: 2883e12c5d1SDavid du Colombier rclunk(0); 2893e12c5d1SDavid du Colombier break; 2903e12c5d1SDavid du Colombier case Tremove: 2913e12c5d1SDavid du Colombier rclunk(1); 2923e12c5d1SDavid du Colombier break; 2933e12c5d1SDavid du Colombier default: 2943e12c5d1SDavid du Colombier fprintf(stderr, "unknown message %s\n", mfmt(&rhdr)); 2953e12c5d1SDavid du Colombier error("bad message"); 2963e12c5d1SDavid du Colombier } 2973e12c5d1SDavid du Colombier sendmsg(0); 2983e12c5d1SDavid du Colombier goto loop; 2993e12c5d1SDavid du Colombier } 3003e12c5d1SDavid du Colombier 3013e12c5d1SDavid du Colombier void 302219b2ee8SDavid du Colombier rsession(void) 3033e12c5d1SDavid du Colombier { 304219b2ee8SDavid du Colombier memset(thdr.authid, 0, sizeof(thdr.authid)); 305219b2ee8SDavid du Colombier memset(thdr.authdom, 0, sizeof(thdr.authdom)); 306219b2ee8SDavid du Colombier memset(thdr.chal, 0, sizeof(thdr.chal)); 3073e12c5d1SDavid du Colombier } 3083e12c5d1SDavid du Colombier 3093e12c5d1SDavid du Colombier void 3103e12c5d1SDavid du Colombier rattach(void) 3113e12c5d1SDavid du Colombier { 3123e12c5d1SDavid du Colombier Rfile *rf; 3133e12c5d1SDavid du Colombier Pass *p; 3143e12c5d1SDavid du Colombier 3153e12c5d1SDavid du Colombier if(file0 == 0){ 3163e12c5d1SDavid du Colombier file0 = newfile(); 3173e12c5d1SDavid du Colombier file0->ref++; /* one extra to hold it up */ 3183e12c5d1SDavid du Colombier file0->path = estrdup("/"); 3193e12c5d1SDavid du Colombier file0->name = estrdup("/"); 3203e12c5d1SDavid du Colombier errjmp(dostat(file0, 0)); 3213e12c5d1SDavid du Colombier } 3223e12c5d1SDavid du Colombier if(!okfid(rhdr.fid)) 3233e12c5d1SDavid du Colombier errjmp(Ebadfid); 3243e12c5d1SDavid du Colombier if(strncmp(rhdr.aname, "device", 6) == 0){ 3253e12c5d1SDavid du Colombier if(connected && !devallowed) 3263e12c5d1SDavid du Colombier errjmp(Especial0); 3273e12c5d1SDavid du Colombier devallowed = 1; 3283e12c5d1SDavid du Colombier }else{ 3293e12c5d1SDavid du Colombier if(connected && devallowed) 3303e12c5d1SDavid du Colombier errjmp(Especial1); 3313e12c5d1SDavid du Colombier } 3323e12c5d1SDavid du Colombier getpwdf(); 3333e12c5d1SDavid du Colombier getgrpf(); 3343e12c5d1SDavid du Colombier rf = &rfile[rhdr.fid]; 3353e12c5d1SDavid du Colombier if(rf->busy) 3363e12c5d1SDavid du Colombier errjmp(Efidactive); 337*7dd7cddfSDavid du Colombier p = name2pass(uidname, rhdr.uname); 3383e12c5d1SDavid du Colombier if(p == 0) 3393e12c5d1SDavid du Colombier errjmp(Eunknown); 340*7dd7cddfSDavid du Colombier if(p->id == 0 || (uid_t)p->id == (uid_t)-1 341*7dd7cddfSDavid du Colombier || myuid && p->id != myuid) 342219b2ee8SDavid du Colombier errjmp(Eperm); 343219b2ee8SDavid du Colombier # ifdef SOCKETS 344*7dd7cddfSDavid du Colombier if(!myuid && ruserok(bsdhost, 0, rhdr.uname, rhdr.uname) < 0) 345219b2ee8SDavid du Colombier errjmp(Eperm); 346219b2ee8SDavid du Colombier # endif 347219b2ee8SDavid du Colombier /* mark busy & inc ref cnt only after committed to succeed */ 348219b2ee8SDavid du Colombier rf->busy = 1; 349219b2ee8SDavid du Colombier rf->file = file0; 350219b2ee8SDavid du Colombier file0->ref++; 351219b2ee8SDavid du Colombier rf->rclose = 0; 3523e12c5d1SDavid du Colombier rf->uid = p->id; 3533e12c5d1SDavid du Colombier thdr.qid = file0->qid; 3543e12c5d1SDavid du Colombier connected = 1; 3553e12c5d1SDavid du Colombier } 3563e12c5d1SDavid du Colombier 3573e12c5d1SDavid du Colombier void 3583e12c5d1SDavid du Colombier rclone(void) 3593e12c5d1SDavid du Colombier { 3603e12c5d1SDavid du Colombier Rfile *rf, *nrf; 3613e12c5d1SDavid du Colombier File *f; 3623e12c5d1SDavid du Colombier 3633e12c5d1SDavid du Colombier rfilefid(); 3643e12c5d1SDavid du Colombier if(!okfid(rhdr.newfid)) 3653e12c5d1SDavid du Colombier errjmp(Ebadfid); 3663e12c5d1SDavid du Colombier rf = &rfile[rhdr.fid]; 3673e12c5d1SDavid du Colombier nrf = &rfile[rhdr.newfid]; 3683e12c5d1SDavid du Colombier f = rf->file; 3693e12c5d1SDavid du Colombier if(nrf->busy) 3703e12c5d1SDavid du Colombier errjmp(Efidactive); 3713e12c5d1SDavid du Colombier nrf->busy = 1; 3723e12c5d1SDavid du Colombier nrf->file = f; 3733e12c5d1SDavid du Colombier f->ref++; 3743e12c5d1SDavid du Colombier nrf->fd = rf->fd; 3753e12c5d1SDavid du Colombier nrf->uid = rf->uid; 376219b2ee8SDavid du Colombier nrf->rclose = rf->rclose; 3773e12c5d1SDavid du Colombier if(nrf->fd){ 3783e12c5d1SDavid du Colombier if(nrf->fd->ref == 0) 3793e12c5d1SDavid du Colombier error("clone fd count"); 3803e12c5d1SDavid du Colombier nrf->fd->ref++; 3813e12c5d1SDavid du Colombier } 3823e12c5d1SDavid du Colombier } 3833e12c5d1SDavid du Colombier 3843e12c5d1SDavid du Colombier void 3853e12c5d1SDavid du Colombier rwalk(void) 3863e12c5d1SDavid du Colombier { 387*7dd7cddfSDavid du Colombier const char *err; 3883e12c5d1SDavid du Colombier Rfile *rf; 3893e12c5d1SDavid du Colombier File *of, *f; 3903e12c5d1SDavid du Colombier 3913e12c5d1SDavid du Colombier rf = rfilefid(); 3923e12c5d1SDavid du Colombier if(rf->fd) 3933e12c5d1SDavid du Colombier errjmp(Eopen); 3943e12c5d1SDavid du Colombier of = rf->file; 3953e12c5d1SDavid du Colombier f = newfile(); 3963e12c5d1SDavid du Colombier f->path = estrdup(of->path); 3973e12c5d1SDavid du Colombier err = dostat(f, rhdr.name); 3983e12c5d1SDavid du Colombier if(err){ 3993e12c5d1SDavid du Colombier free(f->path); 400*7dd7cddfSDavid du Colombier free(f->name); 401*7dd7cddfSDavid du Colombier free(f); 4023e12c5d1SDavid du Colombier errjmp(err); 4033e12c5d1SDavid du Colombier } 4043e12c5d1SDavid du Colombier if(of->ref <= 0) 4053e12c5d1SDavid du Colombier error("walk ref count"); 4063e12c5d1SDavid du Colombier if(--of->ref == 0){ 4073e12c5d1SDavid du Colombier free(of->path); 4083e12c5d1SDavid du Colombier free(of->name); 4093e12c5d1SDavid du Colombier free(of); 4103e12c5d1SDavid du Colombier } 4113e12c5d1SDavid du Colombier rf->file = f; 4123e12c5d1SDavid du Colombier thdr.qid = f->qid; 4133e12c5d1SDavid du Colombier } 4143e12c5d1SDavid du Colombier 4153e12c5d1SDavid du Colombier void 4163e12c5d1SDavid du Colombier ropen(void) 4173e12c5d1SDavid du Colombier { 4183e12c5d1SDavid du Colombier Rfile *rf; 4193e12c5d1SDavid du Colombier File *f; 4203e12c5d1SDavid du Colombier int fd; 4213e12c5d1SDavid du Colombier DIR *dir; 4223e12c5d1SDavid du Colombier int m, trunc; 4233e12c5d1SDavid du Colombier 4243e12c5d1SDavid du Colombier rf = rfilefid(); 4253e12c5d1SDavid du Colombier f = rf->file; 4263e12c5d1SDavid du Colombier if(rf->fd) 4273e12c5d1SDavid du Colombier error("open already open"); 4283e12c5d1SDavid du Colombier if(!devallowed && (f->stbuf.st_mode & S_IFCHR)) 4293e12c5d1SDavid du Colombier errjmp(Especial); 4303e12c5d1SDavid du Colombier m = rhdr.mode & (16|3); 4313e12c5d1SDavid du Colombier trunc = m & 16; /* OTRUNC */ 4323e12c5d1SDavid du Colombier switch(m){ 4333e12c5d1SDavid du Colombier case 0: 4343e12c5d1SDavid du Colombier case 1: 4353e12c5d1SDavid du Colombier case 1|16: 4363e12c5d1SDavid du Colombier case 2: 4373e12c5d1SDavid du Colombier case 0|16: 4383e12c5d1SDavid du Colombier case 2|16: 4393e12c5d1SDavid du Colombier case 3: 4403e12c5d1SDavid du Colombier break; 4413e12c5d1SDavid du Colombier default: 4423e12c5d1SDavid du Colombier errjmp(Emode); 4433e12c5d1SDavid du Colombier } 4443e12c5d1SDavid du Colombier 445bd389b36SDavid du Colombier m = omode(m & 3); 4463e12c5d1SDavid du Colombier errno = 0; 4473e12c5d1SDavid du Colombier if(f->qid.path & CHDIR){ 4483e12c5d1SDavid du Colombier if(rhdr.mode != 0) /* OREAD */ 4493e12c5d1SDavid du Colombier errjmp(Eperm); 4503e12c5d1SDavid du Colombier dir = opendir(f->path); 4513e12c5d1SDavid du Colombier if(dir == 0) 4523e12c5d1SDavid du Colombier errjmp(sys_errlist[errno]); 4533e12c5d1SDavid du Colombier fd = 0; 4543e12c5d1SDavid du Colombier }else{ 4553e12c5d1SDavid du Colombier if(trunc){ 456*7dd7cddfSDavid du Colombier if(readonly) errjmp("trunc disallowed"); 4573e12c5d1SDavid du Colombier fd = creat(f->path, 0666); 4583e12c5d1SDavid du Colombier if(fd >= 0) 4593e12c5d1SDavid du Colombier if(m != 1){ 4603e12c5d1SDavid du Colombier close(fd); 4613e12c5d1SDavid du Colombier fd = open(f->path, m); 4623e12c5d1SDavid du Colombier } 4633e12c5d1SDavid du Colombier }else 4643e12c5d1SDavid du Colombier fd = open(f->path, m); 4653e12c5d1SDavid du Colombier if(fd < 0) 4663e12c5d1SDavid du Colombier errjmp(sys_errlist[errno]); 4673e12c5d1SDavid du Colombier dir = 0; 4683e12c5d1SDavid du Colombier } 469219b2ee8SDavid du Colombier rf->rclose = rhdr.mode & 64; /* ORCLOSE */ 4703e12c5d1SDavid du Colombier rf->fd = erealloc(0, sizeof(Fd)); 4713e12c5d1SDavid du Colombier rf->fd->ref = 1; 4723e12c5d1SDavid du Colombier rf->fd->fd = fd; 4733e12c5d1SDavid du Colombier rf->fd->dir = dir; 4743e12c5d1SDavid du Colombier rf->fd->offset = 0; 4753e12c5d1SDavid du Colombier thdr.qid = f->qid; 4763e12c5d1SDavid du Colombier } 4773e12c5d1SDavid du Colombier 4783e12c5d1SDavid du Colombier void 4793e12c5d1SDavid du Colombier rcreate(void) 4803e12c5d1SDavid du Colombier { 4813e12c5d1SDavid du Colombier Rfile *rf; 4823e12c5d1SDavid du Colombier File *f, *of; 483*7dd7cddfSDavid du Colombier char *path; 484*7dd7cddfSDavid du Colombier const char *err; 485*7dd7cddfSDavid du Colombier int fd, m; 4863e12c5d1SDavid du Colombier char name[NAMELEN]; 4873e12c5d1SDavid du Colombier 488*7dd7cddfSDavid du Colombier if(readonly) errjmp("write disallowed"); 4893e12c5d1SDavid du Colombier rf = rfilefid(); 4903e12c5d1SDavid du Colombier if(rf->fd) 4913e12c5d1SDavid du Colombier errjmp(Eopen); 4923e12c5d1SDavid du Colombier path = bldpath(rf->file->path, rhdr.name, name); 493bd389b36SDavid du Colombier m = omode(rhdr.mode&3); 4943e12c5d1SDavid du Colombier errno = 0; 495*7dd7cddfSDavid du Colombier /* plan 9 group sematics: always inherit from directory */ 4963e12c5d1SDavid du Colombier if(rhdr.perm & CHDIR){ 4973e12c5d1SDavid du Colombier if(m){ 4983e12c5d1SDavid du Colombier free(path); 4993e12c5d1SDavid du Colombier errjmp(Eperm); 5003e12c5d1SDavid du Colombier } 5013e12c5d1SDavid du Colombier fd = mkdir(path, 0777); 5023e12c5d1SDavid du Colombier if(fd < 0){ 5033e12c5d1SDavid du Colombier free(path); 5043e12c5d1SDavid du Colombier errjmp(sys_errlist[errno]); 5053e12c5d1SDavid du Colombier } 5063e12c5d1SDavid du Colombier fd = open(path, 0); 5073e12c5d1SDavid du Colombier free(path); 508*7dd7cddfSDavid du Colombier if(fd >= 0) 509*7dd7cddfSDavid du Colombier fchmod(fd, S_ISGID|(rhdr.perm&rf->file->stbuf.st_mode&0777)); 5103e12c5d1SDavid du Colombier }else{ 5113e12c5d1SDavid du Colombier fd = creat(path, 0666); 5123e12c5d1SDavid du Colombier if(fd >= 0){ 5133e12c5d1SDavid du Colombier if(m != 1){ 5143e12c5d1SDavid du Colombier close(fd); 5153e12c5d1SDavid du Colombier fd = open(path, m); 5163e12c5d1SDavid du Colombier } 517*7dd7cddfSDavid du Colombier fchmod(fd, rhdr.perm&rf->file->stbuf.st_mode&0777); 5183e12c5d1SDavid du Colombier } 5193e12c5d1SDavid du Colombier free(path); 5203e12c5d1SDavid du Colombier if(fd < 0) 5213e12c5d1SDavid du Colombier errjmp(sys_errlist[errno]); 5223e12c5d1SDavid du Colombier } 5233e12c5d1SDavid du Colombier f = newfile(); 5243e12c5d1SDavid du Colombier of = rf->file; 5253e12c5d1SDavid du Colombier f->path = estrdup(of->path); 5263e12c5d1SDavid du Colombier err = dostat(f, rhdr.name); 5273e12c5d1SDavid du Colombier if(err){ 5283e12c5d1SDavid du Colombier free(f->path); 5293e12c5d1SDavid du Colombier free(f->name); 5303e12c5d1SDavid du Colombier free(f); 5313e12c5d1SDavid du Colombier errjmp(err); 5323e12c5d1SDavid du Colombier } 5333e12c5d1SDavid du Colombier if(!devallowed && (f->stbuf.st_mode & S_IFCHR)){ 5343e12c5d1SDavid du Colombier free(f->path); 5353e12c5d1SDavid du Colombier free(f->name); 5363e12c5d1SDavid du Colombier free(f); 5373e12c5d1SDavid du Colombier errjmp(Especial); 5383e12c5d1SDavid du Colombier } 5393e12c5d1SDavid du Colombier if(--of->ref == 0){ 5403e12c5d1SDavid du Colombier free(of->path); 5413e12c5d1SDavid du Colombier free(of->name); 5423e12c5d1SDavid du Colombier free(of); 5433e12c5d1SDavid du Colombier } 5443e12c5d1SDavid du Colombier rf->file = f; 545219b2ee8SDavid du Colombier rf->rclose = rhdr.mode & 64; /* ORCLOSE */ 5463e12c5d1SDavid du Colombier rf->fd = erealloc(0, sizeof(Fd)); 5473e12c5d1SDavid du Colombier rf->fd->ref = 1; 5483e12c5d1SDavid du Colombier rf->fd->fd = fd; 5493e12c5d1SDavid du Colombier rf->fd->dir = 0; 5503e12c5d1SDavid du Colombier rf->fd->offset = 0; 5513e12c5d1SDavid du Colombier thdr.qid = f->qid; 5523e12c5d1SDavid du Colombier } 5533e12c5d1SDavid du Colombier 5543e12c5d1SDavid du Colombier void 5553e12c5d1SDavid du Colombier rread(void) 5563e12c5d1SDavid du Colombier { 5573e12c5d1SDavid du Colombier Rfile *rf; 5583e12c5d1SDavid du Colombier File *f; 5593e12c5d1SDavid du Colombier long n; 5603e12c5d1SDavid du Colombier DTYPE *de; 5613e12c5d1SDavid du Colombier Dir d; 5623e12c5d1SDavid du Colombier struct stat stbuf; 5633e12c5d1SDavid du Colombier char *path; 5643e12c5d1SDavid du Colombier 5653e12c5d1SDavid du Colombier rf = rfilefid(); 5663e12c5d1SDavid du Colombier if(rf->fd == 0) 5673e12c5d1SDavid du Colombier errjmp(Enotopen); 5683e12c5d1SDavid du Colombier if(rhdr.count > sizeof rdata) 5693e12c5d1SDavid du Colombier errjmp(Etoolarge); 5703e12c5d1SDavid du Colombier f = rf->file; 5713e12c5d1SDavid du Colombier if(rf->fd->dir){ 5723e12c5d1SDavid du Colombier errno = 0; 573219b2ee8SDavid du Colombier rhdr.count = (rhdr.count/DIRLEN)*DIRLEN; 5743e12c5d1SDavid du Colombier if(rf->fd->offset != rhdr.offset){ 575219b2ee8SDavid du Colombier rf->fd->offset = rhdr.offset; /* sync offset */ 5763e12c5d1SDavid du Colombier seekdir(rf->fd->dir, 0); 5773e12c5d1SDavid du Colombier for(n=0; n<rhdr.offset; ){ 5783e12c5d1SDavid du Colombier de = readdir(rf->fd->dir); 5793e12c5d1SDavid du Colombier if(de == 0) 5803e12c5d1SDavid du Colombier break; 5813e12c5d1SDavid du Colombier if(de->d_ino==0 || de->d_name[0]==0) 5823e12c5d1SDavid du Colombier continue; 5833e12c5d1SDavid du Colombier if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) 5843e12c5d1SDavid du Colombier continue; 5853e12c5d1SDavid du Colombier n += DIRLEN; 5863e12c5d1SDavid du Colombier } 5873e12c5d1SDavid du Colombier } 5883e12c5d1SDavid du Colombier for(n=0; n<rhdr.count; ){ 5893e12c5d1SDavid du Colombier de = readdir(rf->fd->dir); 5903e12c5d1SDavid du Colombier if(de == 0) 5913e12c5d1SDavid du Colombier break; 5923e12c5d1SDavid du Colombier if(de->d_ino==0 || de->d_name[0]==0) 5933e12c5d1SDavid du Colombier continue; 5943e12c5d1SDavid du Colombier if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) 5953e12c5d1SDavid du Colombier continue; 5963e12c5d1SDavid du Colombier strncpy(d.name, de->d_name, NAMELEN-1); 5973e12c5d1SDavid du Colombier d.name[NAMELEN-1] = 0; 5983e12c5d1SDavid du Colombier path = erealloc(0, strlen(f->path)+1+strlen(de->d_name)+1); 5993e12c5d1SDavid du Colombier sprintf(path, "%s/%s", f->path, de->d_name); 6003e12c5d1SDavid du Colombier memset(&stbuf, 0, sizeof stbuf); 6013e12c5d1SDavid du Colombier if(stat(path, &stbuf) < 0){ 6023e12c5d1SDavid du Colombier fprintf(stderr, "dir: bad path %s\n", path); 6033e12c5d1SDavid du Colombier /* but continue... probably a bad symlink */ 6043e12c5d1SDavid du Colombier } 6053e12c5d1SDavid du Colombier free(path); 6063e12c5d1SDavid du Colombier strncpy(d.uid, id2name(uid, stbuf.st_uid), NAMELEN); 6073e12c5d1SDavid du Colombier strncpy(d.gid, id2name(gid, stbuf.st_gid), NAMELEN); 6083e12c5d1SDavid du Colombier d.qid.path = qid(&stbuf); 609219b2ee8SDavid du Colombier d.qid.vers = vers(&stbuf); 6103e12c5d1SDavid du Colombier d.mode = (d.qid.path&CHDIR)|(stbuf.st_mode&0777); 6113e12c5d1SDavid du Colombier d.atime = stbuf.st_atime; 6123e12c5d1SDavid du Colombier d.mtime = stbuf.st_mtime; 613*7dd7cddfSDavid du Colombier d.len.hlength = 0; 614*7dd7cddfSDavid du Colombier d.len.length = stbuf.st_size; 6153e12c5d1SDavid du Colombier convD2M(&d, rdata+n); 6163e12c5d1SDavid du Colombier n += DIRLEN; 6173e12c5d1SDavid du Colombier } 6183e12c5d1SDavid du Colombier }else{ 6193e12c5d1SDavid du Colombier errno = 0; 620219b2ee8SDavid du Colombier if(rf->fd->offset != rhdr.offset){ 621219b2ee8SDavid du Colombier rf->fd->offset = rhdr.offset; 6223e12c5d1SDavid du Colombier if(lseek(rf->fd->fd, rhdr.offset, 0) < 0) 6233e12c5d1SDavid du Colombier errjmp(sys_errlist[errno]); 624219b2ee8SDavid du Colombier } 6253e12c5d1SDavid du Colombier n = read(rf->fd->fd, rdata, rhdr.count); 6263e12c5d1SDavid du Colombier if(n < 0) 6273e12c5d1SDavid du Colombier errjmp(sys_errlist[errno]); 6283e12c5d1SDavid du Colombier } 6293e12c5d1SDavid du Colombier rf->fd->offset += n; 6303e12c5d1SDavid du Colombier thdr.count = n; 6313e12c5d1SDavid du Colombier thdr.data = rdata; 6323e12c5d1SDavid du Colombier } 6333e12c5d1SDavid du Colombier 6343e12c5d1SDavid du Colombier void 6353e12c5d1SDavid du Colombier rwrite(void) 6363e12c5d1SDavid du Colombier { 6373e12c5d1SDavid du Colombier Rfile *rf; 6383e12c5d1SDavid du Colombier int n; 6393e12c5d1SDavid du Colombier 640*7dd7cddfSDavid du Colombier if(readonly) errjmp("write disallowed"); 6413e12c5d1SDavid du Colombier rf = rfilefid(); 6423e12c5d1SDavid du Colombier if(rf->fd == 0) 6433e12c5d1SDavid du Colombier errjmp(Enotopen); 6443e12c5d1SDavid du Colombier if(rhdr.count > sizeof rdata) 6453e12c5d1SDavid du Colombier errjmp(Etoolarge); 6463e12c5d1SDavid du Colombier errno = 0; 647219b2ee8SDavid du Colombier if(rf->fd->offset != rhdr.offset){ 648219b2ee8SDavid du Colombier rf->fd->offset = rhdr.offset; 6493e12c5d1SDavid du Colombier if(lseek(rf->fd->fd, rhdr.offset, 0) < 0) 6503e12c5d1SDavid du Colombier errjmp(sys_errlist[errno]); 651219b2ee8SDavid du Colombier } 6523e12c5d1SDavid du Colombier n = write(rf->fd->fd, rhdr.data, rhdr.count); 6533e12c5d1SDavid du Colombier if(n < 0) 6543e12c5d1SDavid du Colombier errjmp(sys_errlist[errno]); 6553e12c5d1SDavid du Colombier rf->fd->offset += n; 6563e12c5d1SDavid du Colombier thdr.count = n; 6573e12c5d1SDavid du Colombier } 6583e12c5d1SDavid du Colombier 6593e12c5d1SDavid du Colombier void 6603e12c5d1SDavid du Colombier rstat(void) 6613e12c5d1SDavid du Colombier { 6623e12c5d1SDavid du Colombier Rfile *rf; 6633e12c5d1SDavid du Colombier File *f; 6643e12c5d1SDavid du Colombier Dir d; 6653e12c5d1SDavid du Colombier 6663e12c5d1SDavid du Colombier rf = rfilefid(); 6673e12c5d1SDavid du Colombier f = rf->file; 6683e12c5d1SDavid du Colombier errjmp(dostat(f, 0)); 6693e12c5d1SDavid du Colombier strncpy(d.name, f->name, NAMELEN); 6703e12c5d1SDavid du Colombier strncpy(d.uid, id2name(uid, f->stbuf.st_uid), NAMELEN); 6713e12c5d1SDavid du Colombier strncpy(d.gid, id2name(gid, f->stbuf.st_gid), NAMELEN); 6723e12c5d1SDavid du Colombier d.qid = f->qid; 6733e12c5d1SDavid du Colombier d.mode = (f->qid.path&CHDIR)|(f->stbuf.st_mode&0777); 6743e12c5d1SDavid du Colombier d.atime = f->stbuf.st_atime; 6753e12c5d1SDavid du Colombier d.mtime = f->stbuf.st_mtime; 676*7dd7cddfSDavid du Colombier d.len.hlength = 0; 677*7dd7cddfSDavid du Colombier d.len.length = f->stbuf.st_size; 6783e12c5d1SDavid du Colombier convD2M(&d, thdr.stat); 6793e12c5d1SDavid du Colombier } 6803e12c5d1SDavid du Colombier 6813e12c5d1SDavid du Colombier void 6823e12c5d1SDavid du Colombier rwstat(void) 6833e12c5d1SDavid du Colombier { 6843e12c5d1SDavid du Colombier Rfile *rf; 6853e12c5d1SDavid du Colombier File *f; 6863e12c5d1SDavid du Colombier Dir d; 6873e12c5d1SDavid du Colombier Pass *p; 688*7dd7cddfSDavid du Colombier char *path, *dir, name[NAMELEN], *e; 6893e12c5d1SDavid du Colombier 690*7dd7cddfSDavid du Colombier if(readonly) errjmp("write disallowed"); 6913e12c5d1SDavid du Colombier rf = rfilefid(); 6923e12c5d1SDavid du Colombier f = rf->file; 6933e12c5d1SDavid du Colombier errjmp(dostat(f, 0)); 6943e12c5d1SDavid du Colombier convM2D(rhdr.stat, &d); 6953e12c5d1SDavid du Colombier errno = 0; 6963e12c5d1SDavid du Colombier if(strcmp(d.name, f->name) != 0){ 6973e12c5d1SDavid du Colombier dir = bldpath(f->path, "..", name); 6983e12c5d1SDavid du Colombier path = erealloc(0, strlen(dir)+1+strlen(d.name)+1); 6993e12c5d1SDavid du Colombier sprintf(path, "%s/%s", dir, d.name); 700*7dd7cddfSDavid du Colombier if(rename(f->path, path) < 0){ 7013e12c5d1SDavid du Colombier free(path); 7023e12c5d1SDavid du Colombier errjmp(sys_errlist[errno]); 7033e12c5d1SDavid du Colombier } 7043e12c5d1SDavid du Colombier free(f->path); 7053e12c5d1SDavid du Colombier free(f->name); 7063e12c5d1SDavid du Colombier f->path = path; 7073e12c5d1SDavid du Colombier f->name = estrdup(d.name); 7083e12c5d1SDavid du Colombier } 7093e12c5d1SDavid du Colombier if((d.mode&0777) != (f->stbuf.st_mode&0777)){ 710*7dd7cddfSDavid du Colombier f->stbuf.st_mode = (f->stbuf.st_mode&~0777) | (d.mode&0777); 711*7dd7cddfSDavid du Colombier if(chmod(f->path, f->stbuf.st_mode) < 0) 7123e12c5d1SDavid du Colombier errjmp(sys_errlist[errno]); 7133e12c5d1SDavid du Colombier } 714*7dd7cddfSDavid du Colombier p = name2pass(gidname, d.gid); 715*7dd7cddfSDavid du Colombier if(p == 0){ 716*7dd7cddfSDavid du Colombier if(strtol(d.gid, &e, 10) == f->stbuf.st_gid && *e == 0) 717*7dd7cddfSDavid du Colombier return; 7183e12c5d1SDavid du Colombier errjmp(Eunknown); 719*7dd7cddfSDavid du Colombier } 7203e12c5d1SDavid du Colombier if(p->id != f->stbuf.st_gid){ 7213e12c5d1SDavid du Colombier if(chown(f->path, f->stbuf.st_uid, p->id) < 0) 7223e12c5d1SDavid du Colombier errjmp(sys_errlist[errno]); 7233e12c5d1SDavid du Colombier f->stbuf.st_gid = p->id; 7243e12c5d1SDavid du Colombier } 7253e12c5d1SDavid du Colombier } 7263e12c5d1SDavid du Colombier 7273e12c5d1SDavid du Colombier void 7283e12c5d1SDavid du Colombier rclunk(int rm) 7293e12c5d1SDavid du Colombier { 7303e12c5d1SDavid du Colombier int ret; 731*7dd7cddfSDavid du Colombier const char *err; 7323e12c5d1SDavid du Colombier Rfile *rf; 7333e12c5d1SDavid du Colombier File *f; 7343e12c5d1SDavid du Colombier Fd *fd; 7353e12c5d1SDavid du Colombier 7363e12c5d1SDavid du Colombier err = 0; 7373e12c5d1SDavid du Colombier rf = rfilefid(); 7383e12c5d1SDavid du Colombier f = rf->file; 7393e12c5d1SDavid du Colombier if(rm){ 7403e12c5d1SDavid du Colombier if(f->qid.path & CHDIR) 7413e12c5d1SDavid du Colombier ret = rmdir(f->path); 7423e12c5d1SDavid du Colombier else 7433e12c5d1SDavid du Colombier ret = unlink(f->path); 7443e12c5d1SDavid du Colombier if(ret) 7453e12c5d1SDavid du Colombier err = sys_errlist[errno]; 746219b2ee8SDavid du Colombier }else if(rf->rclose){ /* ignore errors */ 747219b2ee8SDavid du Colombier if(f->qid.path & CHDIR) 748219b2ee8SDavid du Colombier rmdir(f->path); 749219b2ee8SDavid du Colombier else 750219b2ee8SDavid du Colombier unlink(f->path); 7513e12c5d1SDavid du Colombier } 752219b2ee8SDavid du Colombier 7533e12c5d1SDavid du Colombier rf->busy = 0; 7543e12c5d1SDavid du Colombier if(--f->ref == 0){ 7553e12c5d1SDavid du Colombier free(f->path); 7563e12c5d1SDavid du Colombier free(f->name); 7573e12c5d1SDavid du Colombier free(f); 7583e12c5d1SDavid du Colombier } 7593e12c5d1SDavid du Colombier fd = rf->fd; 7603e12c5d1SDavid du Colombier if(fd){ 7613e12c5d1SDavid du Colombier if(fd->ref <= 0) 7623e12c5d1SDavid du Colombier error("clunk fd count"); 7633e12c5d1SDavid du Colombier if(--fd->ref == 0){ 7643e12c5d1SDavid du Colombier if(fd->fd) 7653e12c5d1SDavid du Colombier close(fd->fd); 7663e12c5d1SDavid du Colombier if(fd->dir) 7673e12c5d1SDavid du Colombier closedir(fd->dir); 7683e12c5d1SDavid du Colombier free(fd); 7693e12c5d1SDavid du Colombier } 7703e12c5d1SDavid du Colombier rf->fd = 0; 7713e12c5d1SDavid du Colombier } 7723e12c5d1SDavid du Colombier if(err) 7733e12c5d1SDavid du Colombier errjmp(err); 7743e12c5d1SDavid du Colombier } 7753e12c5d1SDavid du Colombier 7763e12c5d1SDavid du Colombier char* 7773e12c5d1SDavid du Colombier bldpath(char *a, char *elem, char *name) 7783e12c5d1SDavid du Colombier { 7793e12c5d1SDavid du Colombier char *path, *p; 7803e12c5d1SDavid du Colombier 7813e12c5d1SDavid du Colombier if(strcmp(elem, "..") == 0){ 7823e12c5d1SDavid du Colombier if(strcmp(a, "/") == 0){ 7833e12c5d1SDavid du Colombier path = estrdup(a); 7843e12c5d1SDavid du Colombier strcpy(name, a); 7853e12c5d1SDavid du Colombier }else{ 7863e12c5d1SDavid du Colombier p = strrchr(a, '/'); 7873e12c5d1SDavid du Colombier if(p == 0){ 7883e12c5d1SDavid du Colombier fprintf(stderr, "path: '%s'\n", path); 7893e12c5d1SDavid du Colombier error("malformed path 1"); 7903e12c5d1SDavid du Colombier } 7913e12c5d1SDavid du Colombier if(p == a) /* reduced to "/" */ 7923e12c5d1SDavid du Colombier p++; 7933e12c5d1SDavid du Colombier path = erealloc(0, (p-a)+1); 7943e12c5d1SDavid du Colombier memmove(path, a, (p-a)); 7953e12c5d1SDavid du Colombier path[(p-a)] = 0; 7963e12c5d1SDavid du Colombier if(strcmp(path, "/") == 0) 7973e12c5d1SDavid du Colombier p = path; 7983e12c5d1SDavid du Colombier else{ 7993e12c5d1SDavid du Colombier p = strrchr(path, '/'); 8003e12c5d1SDavid du Colombier if(p == 0){ 8013e12c5d1SDavid du Colombier fprintf(stderr, "path: '%s'\n", path); 8023e12c5d1SDavid du Colombier error("malformed path 2"); 8033e12c5d1SDavid du Colombier } 8043e12c5d1SDavid du Colombier p++; 8053e12c5d1SDavid du Colombier } 806*7dd7cddfSDavid du Colombier if(strlen(p) >= NAMELEN) 807*7dd7cddfSDavid du Colombier error("bldpath: name too long"); 8083e12c5d1SDavid du Colombier strcpy(name, p); 8093e12c5d1SDavid du Colombier } 8103e12c5d1SDavid du Colombier }else{ 8113e12c5d1SDavid du Colombier if(strcmp(a, "/") == 0) 8123e12c5d1SDavid du Colombier a = ""; 8133e12c5d1SDavid du Colombier path = erealloc(0, strlen(a)+1+strlen(elem)+1); 8143e12c5d1SDavid du Colombier sprintf(path, "%s/%s", a, elem); 815*7dd7cddfSDavid du Colombier if(strlen(elem) >= NAMELEN) 816*7dd7cddfSDavid du Colombier error("bldpath: name too long"); 8173e12c5d1SDavid du Colombier strcpy(name, elem); 8183e12c5d1SDavid du Colombier } 8193e12c5d1SDavid du Colombier return path; 8203e12c5d1SDavid du Colombier } 8213e12c5d1SDavid du Colombier 822*7dd7cddfSDavid du Colombier const char* 8233e12c5d1SDavid du Colombier dostat(File *f, char *elem) 8243e12c5d1SDavid du Colombier { 8253e12c5d1SDavid du Colombier char *path; 8263e12c5d1SDavid du Colombier struct stat stbuf; 8273e12c5d1SDavid du Colombier char name[NAMELEN]; 8283e12c5d1SDavid du Colombier 8293e12c5d1SDavid du Colombier if(elem) 8303e12c5d1SDavid du Colombier path = bldpath(f->path, elem, name); 8313e12c5d1SDavid du Colombier else 8323e12c5d1SDavid du Colombier path = f->path; 8333e12c5d1SDavid du Colombier errno = 0; 8343e12c5d1SDavid du Colombier if(stat(path, &stbuf) < 0) 8353e12c5d1SDavid du Colombier return sys_errlist[errno]; 8363e12c5d1SDavid du Colombier if(elem){ 8373e12c5d1SDavid du Colombier free(f->path); 8383e12c5d1SDavid du Colombier f->path = path; 8393e12c5d1SDavid du Colombier f->name = estrdup(name); 8403e12c5d1SDavid du Colombier } 8413e12c5d1SDavid du Colombier f->qid.path = qid(&stbuf); 842219b2ee8SDavid du Colombier f->qid.vers = vers(&stbuf); 8433e12c5d1SDavid du Colombier f->stbuf = stbuf; 8443e12c5d1SDavid du Colombier return 0; 8453e12c5d1SDavid du Colombier } 8463e12c5d1SDavid du Colombier 8473e12c5d1SDavid du Colombier int 8483e12c5d1SDavid du Colombier omode(int m) 8493e12c5d1SDavid du Colombier { 8503e12c5d1SDavid du Colombier switch(m){ 8513e12c5d1SDavid du Colombier case 0: /* OREAD */ 8523e12c5d1SDavid du Colombier case 3: /* OEXEC */ 8533e12c5d1SDavid du Colombier return 0; 8543e12c5d1SDavid du Colombier case 1: /* OWRITE */ 8553e12c5d1SDavid du Colombier return 1; 8563e12c5d1SDavid du Colombier case 2: /* ORDWR */ 8573e12c5d1SDavid du Colombier return 2; 8583e12c5d1SDavid du Colombier } 8593e12c5d1SDavid du Colombier errjmp(Emode); 8603e12c5d1SDavid du Colombier return 0; 8613e12c5d1SDavid du Colombier } 8623e12c5d1SDavid du Colombier 8633e12c5d1SDavid du Colombier void 864*7dd7cddfSDavid du Colombier sendmsg(const char *err) 8653e12c5d1SDavid du Colombier { 8663e12c5d1SDavid du Colombier int n; 8673e12c5d1SDavid du Colombier 8683e12c5d1SDavid du Colombier if(err){ 8693e12c5d1SDavid du Colombier thdr.type = Rerror; 8703e12c5d1SDavid du Colombier strncpy(thdr.ename, err, ERRLEN); 8713e12c5d1SDavid du Colombier } 8723e12c5d1SDavid du Colombier DBG(fprintf(stderr, "<< %s\n", mfmt(&thdr))); 8733e12c5d1SDavid du Colombier n = convS2M(&thdr, tdata); 8743e12c5d1SDavid du Colombier if(n == 0) 8753e12c5d1SDavid du Colombier error("bad sendmsg format"); 8763e12c5d1SDavid du Colombier if(write(1, tdata, n) != n) 8773e12c5d1SDavid du Colombier error("write error"); 8783e12c5d1SDavid du Colombier } 8793e12c5d1SDavid du Colombier 8803e12c5d1SDavid du Colombier int 8813e12c5d1SDavid du Colombier okfid(int fid) 8823e12c5d1SDavid du Colombier { 8833e12c5d1SDavid du Colombier enum{ Delta=10 }; 8843e12c5d1SDavid du Colombier 8853e12c5d1SDavid du Colombier if(fid < 0){ 8863e12c5d1SDavid du Colombier fprintf(stderr, "u9fs: negative fid %d\n", fid); 8873e12c5d1SDavid du Colombier return 0; 8883e12c5d1SDavid du Colombier } 8893e12c5d1SDavid du Colombier if(fid >= nrfilealloc){ 8903e12c5d1SDavid du Colombier fid += Delta; 8913e12c5d1SDavid du Colombier rfile = erealloc(rfile, fid*sizeof(Rfile)); 8923e12c5d1SDavid du Colombier memset(rfile+nrfilealloc, 0, (fid-nrfilealloc)*sizeof(Rfile)); 8933e12c5d1SDavid du Colombier nrfilealloc = fid; 8943e12c5d1SDavid du Colombier } 8953e12c5d1SDavid du Colombier return 1; 8963e12c5d1SDavid du Colombier } 8973e12c5d1SDavid du Colombier 8983e12c5d1SDavid du Colombier Rfile* 8993e12c5d1SDavid du Colombier rfilefid(void) 9003e12c5d1SDavid du Colombier { 9013e12c5d1SDavid du Colombier Rfile *rf; 9023e12c5d1SDavid du Colombier 9033e12c5d1SDavid du Colombier if(!okfid(rhdr.fid)) 9043e12c5d1SDavid du Colombier errjmp(Ebadfid); 9053e12c5d1SDavid du Colombier rf = &rfile[rhdr.fid]; 9063e12c5d1SDavid du Colombier if(rf->busy == 0) 9073e12c5d1SDavid du Colombier errjmp(Ebadfid); 9083e12c5d1SDavid du Colombier if(rf->file->ref <= 0) 9093e12c5d1SDavid du Colombier error("ref count"); 910*7dd7cddfSDavid du Colombier setupuser(rf->uid); 9113e12c5d1SDavid du Colombier return rf; 9123e12c5d1SDavid du Colombier } 9133e12c5d1SDavid du Colombier 9143e12c5d1SDavid du Colombier File* 9153e12c5d1SDavid du Colombier newfile(void) 9163e12c5d1SDavid du Colombier { 9173e12c5d1SDavid du Colombier File *f; 9183e12c5d1SDavid du Colombier 9193e12c5d1SDavid du Colombier f = erealloc(0, sizeof(File)); 9203e12c5d1SDavid du Colombier memset(f, 0, sizeof(File)); 9213e12c5d1SDavid du Colombier f->ref = 1; 9223e12c5d1SDavid du Colombier return f; 9233e12c5d1SDavid du Colombier } 9243e12c5d1SDavid du Colombier 9253e12c5d1SDavid du Colombier /* 9263e12c5d1SDavid du Colombier * qids: directory bit, seven bits of device, 24 bits of inode 9273e12c5d1SDavid du Colombier */ 9283e12c5d1SDavid du Colombier Ulong 929219b2ee8SDavid du Colombier vers(struct stat *st) 930219b2ee8SDavid du Colombier { 931*7dd7cddfSDavid du Colombier return st->st_mtime ^ (st->st_size<<8); 932219b2ee8SDavid du Colombier } 933219b2ee8SDavid du Colombier 934219b2ee8SDavid du Colombier Ulong 9353e12c5d1SDavid du Colombier qid(struct stat *st) 9363e12c5d1SDavid du Colombier { 9373e12c5d1SDavid du Colombier static int nqdev; 9383e12c5d1SDavid du Colombier static Uchar *qdev; 9393e12c5d1SDavid du Colombier Ulong q; 9403e12c5d1SDavid du Colombier int dev; 9413e12c5d1SDavid du Colombier 942219b2ee8SDavid du Colombier if(qdev == 0){ 9433e12c5d1SDavid du Colombier qdev = erealloc(0, 65536U); 944219b2ee8SDavid du Colombier memset(qdev, 0, 65536U); 945219b2ee8SDavid du Colombier } 9463e12c5d1SDavid du Colombier q = 0; 947219b2ee8SDavid du Colombier if((st->st_mode&S_IFMT) == S_IFDIR) 9483e12c5d1SDavid du Colombier q = CHDIR; 9493e12c5d1SDavid du Colombier dev = st->st_dev & 0xFFFFUL; 9503e12c5d1SDavid du Colombier if(qdev[dev] == 0){ 9513e12c5d1SDavid du Colombier if(++nqdev >= 128) 9523e12c5d1SDavid du Colombier error("too many devices"); 9533e12c5d1SDavid du Colombier qdev[dev] = nqdev; 9543e12c5d1SDavid du Colombier } 9553e12c5d1SDavid du Colombier q |= qdev[dev]<<24; 9563e12c5d1SDavid du Colombier q |= st->st_ino & 0x00FFFFFFUL; 9573e12c5d1SDavid du Colombier return q; 9583e12c5d1SDavid du Colombier } 9593e12c5d1SDavid du Colombier 9603e12c5d1SDavid du Colombier Pass* 9613e12c5d1SDavid du Colombier name2pass(Pass **pw, char *name) 9623e12c5d1SDavid du Colombier { 9633e12c5d1SDavid du Colombier Pass *p; 9643e12c5d1SDavid du Colombier 965*7dd7cddfSDavid du Colombier for(p = pw[hash(name)]; p; p = p->nnext) 9663e12c5d1SDavid du Colombier if(strcmp(name, p->name) == 0) 9673e12c5d1SDavid du Colombier return p; 9683e12c5d1SDavid du Colombier return 0; 9693e12c5d1SDavid du Colombier } 9703e12c5d1SDavid du Colombier 971*7dd7cddfSDavid du Colombier Pass* 972*7dd7cddfSDavid du Colombier id2pass(Pass **pw, int id) 973*7dd7cddfSDavid du Colombier { 974*7dd7cddfSDavid du Colombier int i; 975*7dd7cddfSDavid du Colombier Pass *p, *pp; 976*7dd7cddfSDavid du Colombier 977*7dd7cddfSDavid du Colombier pp = 0; 978*7dd7cddfSDavid du Colombier /* use last on list == first in file */ 979*7dd7cddfSDavid du Colombier i = (id&0xFF) ^ ((id>>8)&0xFF); 980*7dd7cddfSDavid du Colombier for(p = pw[i]; p; p = p->next) 981*7dd7cddfSDavid du Colombier if(p->id == id) 982*7dd7cddfSDavid du Colombier pp = p; 983*7dd7cddfSDavid du Colombier return pp; 984*7dd7cddfSDavid du Colombier } 985*7dd7cddfSDavid du Colombier 9863e12c5d1SDavid du Colombier char* 9873e12c5d1SDavid du Colombier id2name(Pass **pw, int id) 9883e12c5d1SDavid du Colombier { 9893e12c5d1SDavid du Colombier int i; 9903e12c5d1SDavid du Colombier Pass *p; 9913e12c5d1SDavid du Colombier char *s; 992*7dd7cddfSDavid du Colombier static char buf[40]; 9933e12c5d1SDavid du Colombier 9943e12c5d1SDavid du Colombier s = 0; 9953e12c5d1SDavid du Colombier /* use last on list == first in file */ 9963e12c5d1SDavid du Colombier i = (id&0xFF) ^ ((id>>8)&0xFF); 9973e12c5d1SDavid du Colombier for(p = pw[i]; p; p = p->next) 9983e12c5d1SDavid du Colombier if(p->id == id) 9993e12c5d1SDavid du Colombier s = p->name; 10003e12c5d1SDavid du Colombier if(s) 10013e12c5d1SDavid du Colombier return s; 10023e12c5d1SDavid du Colombier sprintf(buf, "%d", id); 10033e12c5d1SDavid du Colombier return buf; 10043e12c5d1SDavid du Colombier } 10053e12c5d1SDavid du Colombier 10063e12c5d1SDavid du Colombier void 10073e12c5d1SDavid du Colombier freepass(Pass **pass) 10083e12c5d1SDavid du Colombier { 10093e12c5d1SDavid du Colombier int i; 10103e12c5d1SDavid du Colombier Pass *p, *np; 10113e12c5d1SDavid du Colombier 10123e12c5d1SDavid du Colombier for(i=0; i<256; i++){ 10133e12c5d1SDavid du Colombier for(p = pass[i]; p; p = np){ 10143e12c5d1SDavid du Colombier np = p->next; 1015*7dd7cddfSDavid du Colombier free(p->mem); 10163e12c5d1SDavid du Colombier free(p); 10173e12c5d1SDavid du Colombier } 10183e12c5d1SDavid du Colombier pass[i] = 0; 10193e12c5d1SDavid du Colombier } 10203e12c5d1SDavid du Colombier } 10213e12c5d1SDavid du Colombier 10223e12c5d1SDavid du Colombier void 1023*7dd7cddfSDavid du Colombier setupuser(int u) 1024*7dd7cddfSDavid du Colombier { 1025*7dd7cddfSDavid du Colombier Pass *p; 1026*7dd7cddfSDavid du Colombier 1027*7dd7cddfSDavid du Colombier if(curuid == u || myuid != 0) 1028*7dd7cddfSDavid du Colombier return; 1029*7dd7cddfSDavid du Colombier 1030*7dd7cddfSDavid du Colombier p = id2pass(uid, u); 1031*7dd7cddfSDavid du Colombier if(p == 0 || p->id == 0 || (uid_t)p->id == (uid_t)-1) 1032*7dd7cddfSDavid du Colombier errjmp(Eunknown); 1033*7dd7cddfSDavid du Colombier 1034*7dd7cddfSDavid du Colombier if(setreuid(0, 0) < 0) 1035*7dd7cddfSDavid du Colombier error("can't revert to root"); 1036*7dd7cddfSDavid du Colombier 1037*7dd7cddfSDavid du Colombier /* 1038*7dd7cddfSDavid du Colombier * this error message is just a likely guess 1039*7dd7cddfSDavid du Colombier */ 1040*7dd7cddfSDavid du Colombier if(setgroups(p->nmem, p->mem) < 0) 1041*7dd7cddfSDavid du Colombier errjmp("member of too many groups"); 1042*7dd7cddfSDavid du Colombier 1043*7dd7cddfSDavid du Colombier if(setgid(p->gid) < 0 1044*7dd7cddfSDavid du Colombier || setreuid(0, p->id) < 0) 1045*7dd7cddfSDavid du Colombier errjmp(Eunknown); 1046*7dd7cddfSDavid du Colombier } 1047*7dd7cddfSDavid du Colombier 1048*7dd7cddfSDavid du Colombier void 10493e12c5d1SDavid du Colombier getpwdf(void) 10503e12c5d1SDavid du Colombier { 1051*7dd7cddfSDavid du Colombier static int mtime; 10523e12c5d1SDavid du Colombier struct stat stbuf; 10533e12c5d1SDavid du Colombier struct passwd *pw; 10543e12c5d1SDavid du Colombier int i; 10553e12c5d1SDavid du Colombier Pass *p; 10563e12c5d1SDavid du Colombier 1057*7dd7cddfSDavid du Colombier if(onlyuser){ 1058*7dd7cddfSDavid du Colombier i = (myuid&0xFF) ^ ((myuid>>8)&0xFF); 1059*7dd7cddfSDavid du Colombier if(uid[i]) 1060*7dd7cddfSDavid du Colombier return; 1061*7dd7cddfSDavid du Colombier p = erealloc(0, sizeof(Pass)); 1062*7dd7cddfSDavid du Colombier uid[i] = p; 1063*7dd7cddfSDavid du Colombier p->name = strdup(onlyuser); 1064*7dd7cddfSDavid du Colombier uidname[hash(p->name)] = p; 1065*7dd7cddfSDavid du Colombier p->id = myuid; 1066*7dd7cddfSDavid du Colombier p->gid = 60001; 1067*7dd7cddfSDavid du Colombier p->next = 0; 1068*7dd7cddfSDavid du Colombier p->nnext = 0; 1069*7dd7cddfSDavid du Colombier p->nmem = 0; 1070*7dd7cddfSDavid du Colombier p->mem = 0; 1071*7dd7cddfSDavid du Colombier curuid = p->id; 1072*7dd7cddfSDavid du Colombier return; 1073*7dd7cddfSDavid du Colombier } 1074*7dd7cddfSDavid du Colombier 1075*7dd7cddfSDavid du Colombier curuid = -1; 1076*7dd7cddfSDavid du Colombier if(myuid == 0 && setreuid(0, 0) < 0) 1077*7dd7cddfSDavid du Colombier error("can't revert to root"); 1078*7dd7cddfSDavid du Colombier 10793e12c5d1SDavid du Colombier if(stat("/etc/passwd", &stbuf) < 0) 10803e12c5d1SDavid du Colombier error("can't read /etc/passwd"); 10813e12c5d1SDavid du Colombier if(stbuf.st_mtime <= mtime) 10823e12c5d1SDavid du Colombier return; 10833e12c5d1SDavid du Colombier freepass(uid); 1084*7dd7cddfSDavid du Colombier for(i=0; i<256; i++) 1085*7dd7cddfSDavid du Colombier uidname[i] = 0; 1086*7dd7cddfSDavid du Colombier for(;;) { 1087*7dd7cddfSDavid du Colombier pw = getpwent(); 1088*7dd7cddfSDavid du Colombier if(!pw) 1089*7dd7cddfSDavid du Colombier break; 10903e12c5d1SDavid du Colombier i = pw->pw_uid; 10913e12c5d1SDavid du Colombier i = (i&0xFF) ^ ((i>>8)&0xFF); 10923e12c5d1SDavid du Colombier p = erealloc(0, sizeof(Pass)); 10933e12c5d1SDavid du Colombier p->next = uid[i]; 10943e12c5d1SDavid du Colombier uid[i] = p; 10953e12c5d1SDavid du Colombier p->id = pw->pw_uid; 10963e12c5d1SDavid du Colombier p->gid = pw->pw_gid; 10973e12c5d1SDavid du Colombier p->name = estrdup(pw->pw_name); 1098*7dd7cddfSDavid du Colombier p->nmem = 1; 1099*7dd7cddfSDavid du Colombier p->mem = erealloc(0, sizeof(p->mem[0])); 1100*7dd7cddfSDavid du Colombier p->mem[0] = p->gid; 1101*7dd7cddfSDavid du Colombier i = hash(p->name); 1102*7dd7cddfSDavid du Colombier p->nnext = uidname[i]; 1103*7dd7cddfSDavid du Colombier uidname[i] = p; 11043e12c5d1SDavid du Colombier } 11053e12c5d1SDavid du Colombier setpwent(); 11063e12c5d1SDavid du Colombier endpwent(); 11073e12c5d1SDavid du Colombier } 11083e12c5d1SDavid du Colombier 1109*7dd7cddfSDavid du Colombier int 1110*7dd7cddfSDavid du Colombier ismem(Pass *u, int gid) 1111*7dd7cddfSDavid du Colombier { 1112*7dd7cddfSDavid du Colombier int i; 1113*7dd7cddfSDavid du Colombier 1114*7dd7cddfSDavid du Colombier if(u->gid == gid) 1115*7dd7cddfSDavid du Colombier return 1; 1116*7dd7cddfSDavid du Colombier for(i = 0; i < u->nmem; i++) 1117*7dd7cddfSDavid du Colombier if(u->mem[i] == gid) 1118*7dd7cddfSDavid du Colombier return 1; 1119*7dd7cddfSDavid du Colombier return 0; 1120*7dd7cddfSDavid du Colombier } 1121*7dd7cddfSDavid du Colombier 11223e12c5d1SDavid du Colombier void 11233e12c5d1SDavid du Colombier getgrpf(void) 11243e12c5d1SDavid du Colombier { 1125*7dd7cddfSDavid du Colombier static int mtime; 11263e12c5d1SDavid du Colombier struct stat stbuf; 11273e12c5d1SDavid du Colombier struct group *pw; 1128*7dd7cddfSDavid du Colombier int i, m; 1129*7dd7cddfSDavid du Colombier Pass *p, *u; 11303e12c5d1SDavid du Colombier 1131*7dd7cddfSDavid du Colombier if(onlyuser) 1132*7dd7cddfSDavid du Colombier return; 1133*7dd7cddfSDavid du Colombier 1134*7dd7cddfSDavid du Colombier if(stat("/etc/group", &stbuf) < 0 1135*7dd7cddfSDavid du Colombier || stbuf.st_mtime <= mtime) 11363e12c5d1SDavid du Colombier return; 11373e12c5d1SDavid du Colombier freepass(gid); 1138*7dd7cddfSDavid du Colombier for(i=0; i<256; i++) 1139*7dd7cddfSDavid du Colombier gidname[i] = 0; 1140*7dd7cddfSDavid du Colombier for(;;) { 1141*7dd7cddfSDavid du Colombier pw = getgrent(); 1142*7dd7cddfSDavid du Colombier if(!pw) 1143*7dd7cddfSDavid du Colombier break; 11443e12c5d1SDavid du Colombier i = pw->gr_gid; 11453e12c5d1SDavid du Colombier i = (i&0xFF) ^ ((i>>8)&0xFF); 11463e12c5d1SDavid du Colombier p = erealloc(0, sizeof(Pass)); 11473e12c5d1SDavid du Colombier p->next = gid[i]; 11483e12c5d1SDavid du Colombier gid[i] = p; 11493e12c5d1SDavid du Colombier p->id = pw->gr_gid; 11503e12c5d1SDavid du Colombier p->gid = 0; 11513e12c5d1SDavid du Colombier p->name = estrdup(pw->gr_name); 1152*7dd7cddfSDavid du Colombier i = hash(p->name); 1153*7dd7cddfSDavid du Colombier p->nnext = gidname[i]; 1154*7dd7cddfSDavid du Colombier gidname[i] = p; 1155*7dd7cddfSDavid du Colombier 1156*7dd7cddfSDavid du Colombier for(m=0; pw->gr_mem[m]; m++) 1157*7dd7cddfSDavid du Colombier ; 1158*7dd7cddfSDavid du Colombier p->nmem = m; 1159*7dd7cddfSDavid du Colombier p->mem = 0; 1160*7dd7cddfSDavid du Colombier if(m != 0) 1161*7dd7cddfSDavid du Colombier p->mem = erealloc(0, m*sizeof(p->mem[0])); 1162*7dd7cddfSDavid du Colombier for(m = 0; m<p->nmem; m++){ 1163*7dd7cddfSDavid du Colombier u = name2pass(uidname, pw->gr_mem[m]); 1164*7dd7cddfSDavid du Colombier p->mem[m] = -1; 1165*7dd7cddfSDavid du Colombier if(u){ 1166*7dd7cddfSDavid du Colombier p->mem[m] = u->id; 1167*7dd7cddfSDavid du Colombier if(!ismem(u, p->id)){ 1168*7dd7cddfSDavid du Colombier u->mem = erealloc(u->mem, (u->nmem+1)*sizeof(u->mem[0])); 1169*7dd7cddfSDavid du Colombier u->mem[u->nmem++] = p->id; 1170*7dd7cddfSDavid du Colombier } 1171*7dd7cddfSDavid du Colombier } 1172*7dd7cddfSDavid du Colombier } 11733e12c5d1SDavid du Colombier } 11743e12c5d1SDavid du Colombier setgrent(); 11753e12c5d1SDavid du Colombier endgrent(); 11763e12c5d1SDavid du Colombier } 11773e12c5d1SDavid du Colombier 1178*7dd7cddfSDavid du Colombier int 1179*7dd7cddfSDavid du Colombier hash(char *s) 1180*7dd7cddfSDavid du Colombier { 1181*7dd7cddfSDavid du Colombier int h; 1182*7dd7cddfSDavid du Colombier 1183*7dd7cddfSDavid du Colombier h = 0; 1184*7dd7cddfSDavid du Colombier for(; *s; s++) 1185*7dd7cddfSDavid du Colombier h = (h << 1) ^ *s; 1186*7dd7cddfSDavid du Colombier return h & 255; 1187*7dd7cddfSDavid du Colombier } 1188*7dd7cddfSDavid du Colombier 11893e12c5d1SDavid du Colombier void 11903e12c5d1SDavid du Colombier error(char *s) 11913e12c5d1SDavid du Colombier { 11923e12c5d1SDavid du Colombier fprintf(stderr, "u9fs: %s\n", s); 11933e12c5d1SDavid du Colombier perror("unix error"); 11943e12c5d1SDavid du Colombier exit(1); 11953e12c5d1SDavid du Colombier } 11963e12c5d1SDavid du Colombier 11973e12c5d1SDavid du Colombier void 1198*7dd7cddfSDavid du Colombier errjmp(const char *s) 11993e12c5d1SDavid du Colombier { 12003e12c5d1SDavid du Colombier if(s == 0) 12013e12c5d1SDavid du Colombier return; 12023e12c5d1SDavid du Colombier sendmsg(s); 12033e12c5d1SDavid du Colombier longjmp(loopjmp, 1); 12043e12c5d1SDavid du Colombier } 12053e12c5d1SDavid du Colombier 12063e12c5d1SDavid du Colombier void* 12073e12c5d1SDavid du Colombier erealloc(void *p, unsigned n) 12083e12c5d1SDavid du Colombier { 12093e12c5d1SDavid du Colombier if(p == 0) 12103e12c5d1SDavid du Colombier p = malloc(n); 12113e12c5d1SDavid du Colombier else 12123e12c5d1SDavid du Colombier p = realloc(p, n); 12133e12c5d1SDavid du Colombier if(p == 0) 12143e12c5d1SDavid du Colombier error("realloc fail"); 12153e12c5d1SDavid du Colombier return p; 12163e12c5d1SDavid du Colombier } 12173e12c5d1SDavid du Colombier 12183e12c5d1SDavid du Colombier char* 12193e12c5d1SDavid du Colombier estrdup(char *p) 12203e12c5d1SDavid du Colombier { 12213e12c5d1SDavid du Colombier p = strdup(p); 12223e12c5d1SDavid du Colombier if(p == 0) 12233e12c5d1SDavid du Colombier error("strdup fail"); 12243e12c5d1SDavid du Colombier return p; 12253e12c5d1SDavid du Colombier } 1226219b2ee8SDavid du Colombier 1227219b2ee8SDavid du Colombier #ifdef SOCKETS 1228219b2ee8SDavid du Colombier void 1229219b2ee8SDavid du Colombier remotehostname(void) 1230219b2ee8SDavid du Colombier { 1231219b2ee8SDavid du Colombier struct sockaddr_in sock; 1232219b2ee8SDavid du Colombier struct hostent *hp; 1233219b2ee8SDavid du Colombier int len; 1234219b2ee8SDavid du Colombier int on = 1; 1235219b2ee8SDavid du Colombier 1236219b2ee8SDavid du Colombier len = sizeof sock; 1237*7dd7cddfSDavid du Colombier if(getpeername(0, (struct sockaddr*)&sock, &len) < 0) 1238219b2ee8SDavid du Colombier error("getpeername"); 1239219b2ee8SDavid du Colombier hp = gethostbyaddr((char *)&sock.sin_addr, sizeof (struct in_addr), 1240219b2ee8SDavid du Colombier sock.sin_family); 1241219b2ee8SDavid du Colombier if(hp == 0) 1242219b2ee8SDavid du Colombier error("gethostbyaddr"); 1243*7dd7cddfSDavid du Colombier strncpy(bsdhost, hp->h_name, sizeof(bsdhost)-1); 1244*7dd7cddfSDavid du Colombier bsdhost[sizeof(bsdhost)-1] = '\0'; 1245219b2ee8SDavid du Colombier fprintf(stderr, "bsdhost %s on %d\n", bsdhost, getpid()); 1246*7dd7cddfSDavid du Colombier strcpy(ipaddr, inet_ntoa(sock.sin_addr)); 1247219b2ee8SDavid du Colombier 1248*7dd7cddfSDavid du Colombier setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on)); 1249219b2ee8SDavid du Colombier } 1250219b2ee8SDavid du Colombier #endif 1251