1bd389b36SDavid du Colombier #include <u.h> 2bd389b36SDavid du Colombier #include <libc.h> 3*219b2ee8SDavid du Colombier #include <auth.h> 4bd389b36SDavid du Colombier #include <fcall.h> 5bd389b36SDavid du Colombier #include <tapefs.h> 6bd389b36SDavid du Colombier 7bd389b36SDavid du Colombier Fid *fids; 8bd389b36SDavid du Colombier Ram *ram; 9bd389b36SDavid du Colombier int mfd[2]; 10bd389b36SDavid du Colombier char user[NAMELEN]; 11bd389b36SDavid du Colombier char mdata[MAXMSG+MAXFDATA]; 12bd389b36SDavid du Colombier Fcall rhdr; 13bd389b36SDavid du Colombier Fcall thdr; 14bd389b36SDavid du Colombier ulong path; 15bd389b36SDavid du Colombier Idmap *uidmap; 16bd389b36SDavid du Colombier Idmap *gidmap; 17bd389b36SDavid du Colombier int replete; 18bd389b36SDavid du Colombier 19bd389b36SDavid du Colombier Fid * newfid(int); 20bd389b36SDavid du Colombier void ramstat(Ram*, char*); 21bd389b36SDavid du Colombier void io(void); 22bd389b36SDavid du Colombier void usage(void); 23bd389b36SDavid du Colombier int perm(Fid*, Ram*, int); 24bd389b36SDavid du Colombier 25bd389b36SDavid du Colombier char *rflush(Fid*), *rnop(Fid*), *rsession(Fid*), 26bd389b36SDavid du Colombier *rattach(Fid*), *rclone(Fid*), *rwalk(Fid*), 27bd389b36SDavid du Colombier *rclwalk(Fid*), *ropen(Fid*), *rcreate(Fid*), 28bd389b36SDavid du Colombier *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*), 29bd389b36SDavid du Colombier *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*), 30bd389b36SDavid du Colombier *rauth(Fid*); 31bd389b36SDavid du Colombier 32bd389b36SDavid du Colombier char *(*fcalls[])(Fid*) = { 33bd389b36SDavid du Colombier [Tflush] rflush, 34bd389b36SDavid du Colombier [Tsession] rsession, 35bd389b36SDavid du Colombier [Tnop] rnop, 36bd389b36SDavid du Colombier [Tattach] rattach, 37bd389b36SDavid du Colombier [Tclone] rclone, 38bd389b36SDavid du Colombier [Twalk] rwalk, 39bd389b36SDavid du Colombier [Tclwalk] rclwalk, 40bd389b36SDavid du Colombier [Topen] ropen, 41bd389b36SDavid du Colombier [Tcreate] rcreate, 42bd389b36SDavid du Colombier [Tread] rread, 43bd389b36SDavid du Colombier [Twrite] rwrite, 44bd389b36SDavid du Colombier [Tclunk] rclunk, 45bd389b36SDavid du Colombier [Tremove] rremove, 46bd389b36SDavid du Colombier [Tstat] rstat, 47bd389b36SDavid du Colombier [Twstat] rwstat, 48bd389b36SDavid du Colombier }; 49bd389b36SDavid du Colombier 50bd389b36SDavid du Colombier char Eperm[] = "permission denied"; 51bd389b36SDavid du Colombier char Enotdir[] = "not a directory"; 52bd389b36SDavid du Colombier char Enoauth[] = "no authentication in ramfs"; 53bd389b36SDavid du Colombier char Enotexist[] = "file does not exist"; 54bd389b36SDavid du Colombier char Einuse[] = "file in use"; 55bd389b36SDavid du Colombier char Eexist[] = "file exists"; 56bd389b36SDavid du Colombier char Enotowner[] = "not owner"; 57bd389b36SDavid du Colombier char Eisopen[] = "file already open for I/O"; 58bd389b36SDavid du Colombier char Excl[] = "exclusive use file already open"; 59bd389b36SDavid du Colombier char Ename[] = "illegal name"; 60bd389b36SDavid du Colombier 61bd389b36SDavid du Colombier void 62bd389b36SDavid du Colombier notifyf(void *a, char *s) 63bd389b36SDavid du Colombier { 64bd389b36SDavid du Colombier USED(a); 65bd389b36SDavid du Colombier if(strncmp(s, "interrupt", 9) == 0) 66bd389b36SDavid du Colombier noted(NCONT); 67bd389b36SDavid du Colombier noted(NDFLT); 68bd389b36SDavid du Colombier } 69bd389b36SDavid du Colombier 70bd389b36SDavid du Colombier void 71bd389b36SDavid du Colombier main(int argc, char *argv[]) 72bd389b36SDavid du Colombier { 73bd389b36SDavid du Colombier Ram *r; 74bd389b36SDavid du Colombier char *defmnt; 75bd389b36SDavid du Colombier int p[2]; 76bd389b36SDavid du Colombier 77*219b2ee8SDavid du Colombier defmnt = "/n/tapefs"; 78bd389b36SDavid du Colombier ARGBEGIN{ 79bd389b36SDavid du Colombier case 'm': 80bd389b36SDavid du Colombier defmnt = ARGF(); 81bd389b36SDavid du Colombier break; 82bd389b36SDavid du Colombier case 'p': /* password file */ 83bd389b36SDavid du Colombier uidmap = getpass(ARGF()); 84bd389b36SDavid du Colombier break; 85bd389b36SDavid du Colombier case 'g': /* group file */ 86bd389b36SDavid du Colombier gidmap = getpass(ARGF()); 87bd389b36SDavid du Colombier break; 88bd389b36SDavid du Colombier default: 89bd389b36SDavid du Colombier usage(); 90bd389b36SDavid du Colombier }ARGEND 91bd389b36SDavid du Colombier 92bd389b36SDavid du Colombier if (argc==0) 93bd389b36SDavid du Colombier error("no file to mount"); 94bd389b36SDavid du Colombier ram = r = (Ram *)emalloc(sizeof(Ram)); 95bd389b36SDavid du Colombier r->busy = 1; 96bd389b36SDavid du Colombier r->data = 0; 97bd389b36SDavid du Colombier r->ndata = 0; 98bd389b36SDavid du Colombier r->perm = CHDIR | 0775; 99bd389b36SDavid du Colombier r->qid.path = CHDIR; 100bd389b36SDavid du Colombier r->qid.vers = 0; 101bd389b36SDavid du Colombier r->parent = 0; 102bd389b36SDavid du Colombier r->child = 0; 103bd389b36SDavid du Colombier r->next = 0; 104bd389b36SDavid du Colombier r->user = user; 105bd389b36SDavid du Colombier r->group = user; 106bd389b36SDavid du Colombier r->atime = time(0); 107bd389b36SDavid du Colombier r->mtime = r->atime; 108bd389b36SDavid du Colombier r->replete = 0; 109bd389b36SDavid du Colombier strcpy(r->name, "."); 110bd389b36SDavid du Colombier strcpy(user, getuser()); 111bd389b36SDavid du Colombier populate(argv[0]); 112bd389b36SDavid du Colombier r->replete |= replete; 113bd389b36SDavid du Colombier if(pipe(p) < 0) 114bd389b36SDavid du Colombier error("pipe failed"); 115bd389b36SDavid du Colombier mfd[0] = mfd[1] = p[0]; 116bd389b36SDavid du Colombier notify(notifyf); 117bd389b36SDavid du Colombier 118bd389b36SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){ 119bd389b36SDavid du Colombier case -1: 120bd389b36SDavid du Colombier error("fork"); 121bd389b36SDavid du Colombier case 0: 122bd389b36SDavid du Colombier close(p[1]); 123bd389b36SDavid du Colombier notify(notifyf); 124bd389b36SDavid du Colombier io(); 125bd389b36SDavid du Colombier break; 126bd389b36SDavid du Colombier default: 127bd389b36SDavid du Colombier close(p[0]); /* don't deadlock if child fails */ 128*219b2ee8SDavid du Colombier if(mount(p[1], defmnt, MREPL|MCREATE, "") < 0) { 129*219b2ee8SDavid du Colombier char buf[256]; 130*219b2ee8SDavid du Colombier sprint(buf, "mount on `%s' failed", defmnt); 131*219b2ee8SDavid du Colombier error(buf); 132*219b2ee8SDavid du Colombier } 133bd389b36SDavid du Colombier } 134bd389b36SDavid du Colombier exits(0); 135bd389b36SDavid du Colombier } 136bd389b36SDavid du Colombier 137bd389b36SDavid du Colombier char* 138bd389b36SDavid du Colombier rnop(Fid *f) 139bd389b36SDavid du Colombier { 140bd389b36SDavid du Colombier USED(f); 141bd389b36SDavid du Colombier return 0; 142bd389b36SDavid du Colombier } 143bd389b36SDavid du Colombier 144bd389b36SDavid du Colombier char* 145bd389b36SDavid du Colombier rsession(Fid *unused) 146bd389b36SDavid du Colombier { 147bd389b36SDavid du Colombier Fid *f; 148bd389b36SDavid du Colombier 149bd389b36SDavid du Colombier USED(unused); 150bd389b36SDavid du Colombier 151*219b2ee8SDavid du Colombier memset(thdr.authid, 0, sizeof(thdr.authid)); 152*219b2ee8SDavid du Colombier memset(thdr.authdom, 0, sizeof(thdr.authdom)); 153*219b2ee8SDavid du Colombier memset(thdr.chal, 0, sizeof(thdr.chal)); 154bd389b36SDavid du Colombier for(f = fids; f; f = f->next) 155bd389b36SDavid du Colombier if(f->busy) 156bd389b36SDavid du Colombier rclunk(f); 157bd389b36SDavid du Colombier return 0; 158bd389b36SDavid du Colombier } 159bd389b36SDavid du Colombier 160bd389b36SDavid du Colombier char* 161bd389b36SDavid du Colombier rflush(Fid *f) 162bd389b36SDavid du Colombier { 163bd389b36SDavid du Colombier USED(f); 164bd389b36SDavid du Colombier return 0; 165bd389b36SDavid du Colombier } 166bd389b36SDavid du Colombier 167bd389b36SDavid du Colombier char* 168bd389b36SDavid du Colombier rattach(Fid *f) 169bd389b36SDavid du Colombier { 170bd389b36SDavid du Colombier /* no authentication! */ 171bd389b36SDavid du Colombier f->busy = 1; 172bd389b36SDavid du Colombier f->rclose = 0; 173bd389b36SDavid du Colombier f->ram = ram; 174bd389b36SDavid du Colombier thdr.qid = f->ram->qid; 175bd389b36SDavid du Colombier if(rhdr.uname[0]) 176bd389b36SDavid du Colombier f->user = strdup(rhdr.uname); 177bd389b36SDavid du Colombier else 178bd389b36SDavid du Colombier f->user = "none"; 179bd389b36SDavid du Colombier return 0; 180bd389b36SDavid du Colombier } 181bd389b36SDavid du Colombier 182bd389b36SDavid du Colombier char* 183bd389b36SDavid du Colombier rclone(Fid *f) 184bd389b36SDavid du Colombier { 185bd389b36SDavid du Colombier Fid *nf; 186bd389b36SDavid du Colombier 187bd389b36SDavid du Colombier if(f->open) 188bd389b36SDavid du Colombier return Eisopen; 189bd389b36SDavid du Colombier if(f->ram->busy == 0) 190bd389b36SDavid du Colombier return Enotexist; 191bd389b36SDavid du Colombier nf = newfid(rhdr.newfid); 192bd389b36SDavid du Colombier nf->busy = 1; 193bd389b36SDavid du Colombier nf->open = 0; 194bd389b36SDavid du Colombier nf->rclose = 0; 195bd389b36SDavid du Colombier nf->ram = f->ram; 196bd389b36SDavid du Colombier nf->user = f->user; /* no ref count; the leakage is minor */ 197bd389b36SDavid du Colombier return 0; 198bd389b36SDavid du Colombier } 199bd389b36SDavid du Colombier 200bd389b36SDavid du Colombier char* 201bd389b36SDavid du Colombier rwalk(Fid *f) 202bd389b36SDavid du Colombier { 203bd389b36SDavid du Colombier Ram *r; 204bd389b36SDavid du Colombier char *name; 205bd389b36SDavid du Colombier Ram *dir; 206bd389b36SDavid du Colombier 207bd389b36SDavid du Colombier if((f->ram->qid.path & CHDIR) == 0) 208bd389b36SDavid du Colombier return Enotdir; 209bd389b36SDavid du Colombier if(f->ram->busy == 0) 210bd389b36SDavid du Colombier return Enotexist; 211bd389b36SDavid du Colombier f->ram->atime = time(0); 212bd389b36SDavid du Colombier name = rhdr.name; 213bd389b36SDavid du Colombier if(strcmp(name, ".") == 0){ 214bd389b36SDavid du Colombier thdr.qid = f->ram->qid; 215bd389b36SDavid du Colombier return 0; 216bd389b36SDavid du Colombier } 217bd389b36SDavid du Colombier dir = f->ram; 218bd389b36SDavid du Colombier if(!dir || !perm(f, dir, Pexec)) 219bd389b36SDavid du Colombier return Eperm; 220bd389b36SDavid du Colombier if(strcmp(name, "..") == 0){ 221bd389b36SDavid du Colombier f->ram = dir->parent; 222bd389b36SDavid du Colombier thdr.qid = f->ram->qid; 223bd389b36SDavid du Colombier return 0; 224bd389b36SDavid du Colombier } 225bd389b36SDavid du Colombier if (!dir->replete) 226bd389b36SDavid du Colombier popdir(dir); 227bd389b36SDavid du Colombier for(r=dir->child; r; r=r->next) 228bd389b36SDavid du Colombier if(r->busy && strcmp(name, r->name)==0){ 229bd389b36SDavid du Colombier thdr.qid = r->qid; 230bd389b36SDavid du Colombier f->ram = r; 231bd389b36SDavid du Colombier return 0; 232bd389b36SDavid du Colombier } 233bd389b36SDavid du Colombier return Enotexist; 234bd389b36SDavid du Colombier } 235bd389b36SDavid du Colombier 236bd389b36SDavid du Colombier char * 237bd389b36SDavid du Colombier rclwalk(Fid *f) 238bd389b36SDavid du Colombier { 239bd389b36SDavid du Colombier Fid *nf; 240bd389b36SDavid du Colombier char *err; 241bd389b36SDavid du Colombier 242bd389b36SDavid du Colombier nf = newfid(rhdr.newfid); 243bd389b36SDavid du Colombier nf->busy = 1; 244bd389b36SDavid du Colombier nf->rclose = 0; 245bd389b36SDavid du Colombier nf->ram = f->ram; 246bd389b36SDavid du Colombier nf->user = f->user; 247bd389b36SDavid du Colombier if(err = rwalk(nf)) 248bd389b36SDavid du Colombier rclunk(nf); 249bd389b36SDavid du Colombier return err; 250bd389b36SDavid du Colombier } 251bd389b36SDavid du Colombier 252bd389b36SDavid du Colombier char * 253bd389b36SDavid du Colombier ropen(Fid *f) 254bd389b36SDavid du Colombier { 255bd389b36SDavid du Colombier Ram *r; 256bd389b36SDavid du Colombier int mode, trunc; 257bd389b36SDavid du Colombier 258bd389b36SDavid du Colombier if(f->open) 259bd389b36SDavid du Colombier return Eisopen; 260bd389b36SDavid du Colombier r = f->ram; 261bd389b36SDavid du Colombier if(r->busy == 0) 262bd389b36SDavid du Colombier return Enotexist; 263bd389b36SDavid du Colombier if(r->perm & CHEXCL) 264bd389b36SDavid du Colombier if(r->open) 265bd389b36SDavid du Colombier return Excl; 266bd389b36SDavid du Colombier mode = rhdr.mode; 267bd389b36SDavid du Colombier if(r->qid.path & CHDIR){ 268bd389b36SDavid du Colombier if(mode != OREAD) 269bd389b36SDavid du Colombier return Eperm; 270bd389b36SDavid du Colombier thdr.qid = r->qid; 271bd389b36SDavid du Colombier return 0; 272bd389b36SDavid du Colombier } 273bd389b36SDavid du Colombier if(mode & ORCLOSE) 274bd389b36SDavid du Colombier return Eperm; 275bd389b36SDavid du Colombier trunc = mode & OTRUNC; 276bd389b36SDavid du Colombier mode &= OPERM; 277bd389b36SDavid du Colombier if(mode==OWRITE || mode==ORDWR || trunc) 278bd389b36SDavid du Colombier if(!perm(f, r, Pwrite)) 279bd389b36SDavid du Colombier return Eperm; 280bd389b36SDavid du Colombier if(mode==OREAD || mode==ORDWR) 281bd389b36SDavid du Colombier if(!perm(f, r, Pread)) 282bd389b36SDavid du Colombier return Eperm; 283bd389b36SDavid du Colombier if(mode==OEXEC) 284bd389b36SDavid du Colombier if(!perm(f, r, Pexec)) 285bd389b36SDavid du Colombier return Eperm; 286bd389b36SDavid du Colombier if(trunc && (r->perm&CHAPPEND)==0){ 287bd389b36SDavid du Colombier r->ndata = 0; 288bd389b36SDavid du Colombier dotrunc(r); 289bd389b36SDavid du Colombier r->qid.vers++; 290bd389b36SDavid du Colombier } 291bd389b36SDavid du Colombier thdr.qid = r->qid; 292bd389b36SDavid du Colombier f->open = 1; 293bd389b36SDavid du Colombier r->open++; 294bd389b36SDavid du Colombier return 0; 295bd389b36SDavid du Colombier } 296bd389b36SDavid du Colombier 297bd389b36SDavid du Colombier char * 298bd389b36SDavid du Colombier rcreate(Fid *f) 299bd389b36SDavid du Colombier { 300bd389b36SDavid du Colombier USED(f); 301bd389b36SDavid du Colombier 302bd389b36SDavid du Colombier return Eperm; 303bd389b36SDavid du Colombier } 304bd389b36SDavid du Colombier 305bd389b36SDavid du Colombier char* 306bd389b36SDavid du Colombier rread(Fid *f) 307bd389b36SDavid du Colombier { 308bd389b36SDavid du Colombier Ram *r; 309bd389b36SDavid du Colombier char *buf; 310bd389b36SDavid du Colombier long off; 311bd389b36SDavid du Colombier int n, cnt; 312bd389b36SDavid du Colombier 313bd389b36SDavid du Colombier if(f->ram->busy == 0) 314bd389b36SDavid du Colombier return Enotexist; 315bd389b36SDavid du Colombier n = 0; 316bd389b36SDavid du Colombier thdr.count = 0; 317bd389b36SDavid du Colombier off = rhdr.offset; 318bd389b36SDavid du Colombier cnt = rhdr.count; 319bd389b36SDavid du Colombier buf = thdr.data; 320bd389b36SDavid du Colombier if(f->ram->qid.path & CHDIR){ 321bd389b36SDavid du Colombier if (!f->ram->replete) 322bd389b36SDavid du Colombier popdir(f->ram); 323bd389b36SDavid du Colombier if(off%DIRLEN || cnt%DIRLEN) 324bd389b36SDavid du Colombier return "i/o error"; 325bd389b36SDavid du Colombier for(r=f->ram->child; off; r=r->next){ 326bd389b36SDavid du Colombier if (r==0) 327bd389b36SDavid du Colombier return 0; 328bd389b36SDavid du Colombier if(r->busy) 329bd389b36SDavid du Colombier off -= DIRLEN; 330bd389b36SDavid du Colombier } 331bd389b36SDavid du Colombier for(; r && n < cnt; r=r->next){ 332bd389b36SDavid du Colombier if(!r->busy) 333bd389b36SDavid du Colombier continue; 334bd389b36SDavid du Colombier ramstat(r, buf+n); 335bd389b36SDavid du Colombier n += DIRLEN; 336bd389b36SDavid du Colombier } 337bd389b36SDavid du Colombier thdr.count = n; 338bd389b36SDavid du Colombier return 0; 339bd389b36SDavid du Colombier } 340bd389b36SDavid du Colombier r = f->ram; 341bd389b36SDavid du Colombier if(off >= r->ndata) 342bd389b36SDavid du Colombier return 0; 343bd389b36SDavid du Colombier r->atime = time(0); 344bd389b36SDavid du Colombier n = cnt; 345bd389b36SDavid du Colombier if(off+n > r->ndata) 346bd389b36SDavid du Colombier n = r->ndata - off; 347bd389b36SDavid du Colombier thdr.data = doread(r, off, n); 348bd389b36SDavid du Colombier thdr.count = n; 349bd389b36SDavid du Colombier return 0; 350bd389b36SDavid du Colombier } 351bd389b36SDavid du Colombier 352bd389b36SDavid du Colombier char* 353bd389b36SDavid du Colombier rwrite(Fid *f) 354bd389b36SDavid du Colombier { 355bd389b36SDavid du Colombier Ram *r; 356bd389b36SDavid du Colombier ulong off; 357bd389b36SDavid du Colombier int cnt; 358bd389b36SDavid du Colombier 359bd389b36SDavid du Colombier r = f->ram; 360bd389b36SDavid du Colombier if (dopermw(f->ram)==0) 361bd389b36SDavid du Colombier return Eperm; 362bd389b36SDavid du Colombier if(r->busy == 0) 363bd389b36SDavid du Colombier return Enotexist; 364bd389b36SDavid du Colombier off = rhdr.offset; 365bd389b36SDavid du Colombier if(r->perm & CHAPPEND) 366bd389b36SDavid du Colombier off = r->ndata; 367bd389b36SDavid du Colombier cnt = rhdr.count; 368bd389b36SDavid du Colombier if(r->qid.path & CHDIR) 369bd389b36SDavid du Colombier return "file is a directory"; 370bd389b36SDavid du Colombier if(off > 100*1024*1024) /* sanity check */ 371bd389b36SDavid du Colombier return "write too big"; 372bd389b36SDavid du Colombier dowrite(r, rhdr.data, off, cnt); 373bd389b36SDavid du Colombier r->qid.vers++; 374bd389b36SDavid du Colombier r->mtime = time(0); 375bd389b36SDavid du Colombier thdr.count = cnt; 376bd389b36SDavid du Colombier return 0; 377bd389b36SDavid du Colombier } 378bd389b36SDavid du Colombier 379bd389b36SDavid du Colombier char * 380bd389b36SDavid du Colombier rclunk(Fid *f) 381bd389b36SDavid du Colombier { 382bd389b36SDavid du Colombier if(f->open) 383bd389b36SDavid du Colombier f->ram->open--; 384bd389b36SDavid du Colombier f->busy = 0; 385bd389b36SDavid du Colombier f->open = 0; 386bd389b36SDavid du Colombier f->ram = 0; 387bd389b36SDavid du Colombier return 0; 388bd389b36SDavid du Colombier } 389bd389b36SDavid du Colombier 390bd389b36SDavid du Colombier char * 391bd389b36SDavid du Colombier rremove(Fid *f) 392bd389b36SDavid du Colombier { 393bd389b36SDavid du Colombier USED(f); 394bd389b36SDavid du Colombier return Eperm; 395bd389b36SDavid du Colombier } 396bd389b36SDavid du Colombier 397bd389b36SDavid du Colombier char * 398bd389b36SDavid du Colombier rstat(Fid *f) 399bd389b36SDavid du Colombier { 400bd389b36SDavid du Colombier if(f->ram->busy == 0) 401bd389b36SDavid du Colombier return Enotexist; 402bd389b36SDavid du Colombier ramstat(f->ram, thdr.stat); 403bd389b36SDavid du Colombier return 0; 404bd389b36SDavid du Colombier } 405bd389b36SDavid du Colombier 406bd389b36SDavid du Colombier char * 407bd389b36SDavid du Colombier rwstat(Fid *f) 408bd389b36SDavid du Colombier { 409bd389b36SDavid du Colombier if(f->ram->busy == 0) 410bd389b36SDavid du Colombier return Enotexist; 411bd389b36SDavid du Colombier return Eperm; 412bd389b36SDavid du Colombier } 413bd389b36SDavid du Colombier 414bd389b36SDavid du Colombier void 415bd389b36SDavid du Colombier ramstat(Ram *r, char *buf) 416bd389b36SDavid du Colombier { 417bd389b36SDavid du Colombier Dir dir; 418bd389b36SDavid du Colombier 419bd389b36SDavid du Colombier memmove(dir.name, r->name, NAMELEN); 420bd389b36SDavid du Colombier dir.qid = r->qid; 421bd389b36SDavid du Colombier dir.mode = r->perm; 422bd389b36SDavid du Colombier dir.length = r->ndata; 423bd389b36SDavid du Colombier dir.hlength = 0; 424bd389b36SDavid du Colombier strcpy(dir.uid, r->user); 425bd389b36SDavid du Colombier strcpy(dir.gid, r->group); 426bd389b36SDavid du Colombier dir.atime = r->atime; 427bd389b36SDavid du Colombier dir.mtime = r->mtime; 428bd389b36SDavid du Colombier convD2M(&dir, buf); 429bd389b36SDavid du Colombier } 430bd389b36SDavid du Colombier 431bd389b36SDavid du Colombier Fid * 432bd389b36SDavid du Colombier newfid(int fid) 433bd389b36SDavid du Colombier { 434bd389b36SDavid du Colombier Fid *f, *ff; 435bd389b36SDavid du Colombier 436bd389b36SDavid du Colombier ff = 0; 437bd389b36SDavid du Colombier for(f = fids; f; f = f->next) 438bd389b36SDavid du Colombier if(f->fid == fid) 439bd389b36SDavid du Colombier return f; 440bd389b36SDavid du Colombier else if(!ff && !f->busy) 441bd389b36SDavid du Colombier ff = f; 442bd389b36SDavid du Colombier if(ff){ 443bd389b36SDavid du Colombier ff->fid = fid; 444bd389b36SDavid du Colombier ff->open = 0; 445bd389b36SDavid du Colombier ff->busy = 1; 446bd389b36SDavid du Colombier } 447bd389b36SDavid du Colombier f = emalloc(sizeof *f); 448bd389b36SDavid du Colombier f->ram = 0; 449bd389b36SDavid du Colombier f->fid = fid; 450bd389b36SDavid du Colombier f->busy = 1; 451bd389b36SDavid du Colombier f->open = 0; 452bd389b36SDavid du Colombier f->next = fids; 453bd389b36SDavid du Colombier fids = f; 454bd389b36SDavid du Colombier return f; 455bd389b36SDavid du Colombier } 456bd389b36SDavid du Colombier 457bd389b36SDavid du Colombier void 458bd389b36SDavid du Colombier io(void) 459bd389b36SDavid du Colombier { 460bd389b36SDavid du Colombier char *err; 461bd389b36SDavid du Colombier int n, nerr; 462bd389b36SDavid du Colombier char buf[ERRLEN]; 463bd389b36SDavid du Colombier 464bd389b36SDavid du Colombier errstr(buf); 465bd389b36SDavid du Colombier for(nerr=0, buf[0]='\0'; nerr<100; nerr++){ 466bd389b36SDavid du Colombier /* 467bd389b36SDavid du Colombier * reading from a pipe or a network device 468bd389b36SDavid du Colombier * will give an error after a few eof reads 469bd389b36SDavid du Colombier * however, we cannot tell the difference 470bd389b36SDavid du Colombier * between a zero-length read and an interrupt 471bd389b36SDavid du Colombier * on the processes writing to us, 472bd389b36SDavid du Colombier * so we wait for the error 473bd389b36SDavid du Colombier */ 474bd389b36SDavid du Colombier n = read(mfd[0], mdata, sizeof mdata); 475bd389b36SDavid du Colombier if (n==0) 476bd389b36SDavid du Colombier continue; 477bd389b36SDavid du Colombier if(n < 0){ 478bd389b36SDavid du Colombier if (buf[0]=='\0') 479bd389b36SDavid du Colombier errstr(buf); 480bd389b36SDavid du Colombier continue; 481bd389b36SDavid du Colombier } 482bd389b36SDavid du Colombier nerr = 0; 483bd389b36SDavid du Colombier buf[0] = '\0'; 484bd389b36SDavid du Colombier if(convM2S(mdata, &rhdr, n) == 0) 485bd389b36SDavid du Colombier continue; 486bd389b36SDavid du Colombier 487bd389b36SDavid du Colombier /* fprint(2, "ramfs:%F\n", &rhdr);/**/ 488bd389b36SDavid du Colombier 489bd389b36SDavid du Colombier thdr.data = mdata + MAXMSG; 490bd389b36SDavid du Colombier if(!fcalls[rhdr.type]) 491bd389b36SDavid du Colombier err = "bad fcall type"; 492bd389b36SDavid du Colombier else 493bd389b36SDavid du Colombier err = (*fcalls[rhdr.type])(newfid(rhdr.fid)); 494bd389b36SDavid du Colombier if(err){ 495bd389b36SDavid du Colombier thdr.type = Rerror; 496bd389b36SDavid du Colombier strncpy(thdr.ename, err, ERRLEN); 497bd389b36SDavid du Colombier }else{ 498bd389b36SDavid du Colombier thdr.type = rhdr.type + 1; 499bd389b36SDavid du Colombier thdr.fid = rhdr.fid; 500bd389b36SDavid du Colombier } 501bd389b36SDavid du Colombier thdr.tag = rhdr.tag; 502bd389b36SDavid du Colombier n = convS2M(&thdr, mdata); 503bd389b36SDavid du Colombier if(write(mfd[1], mdata, n) != n) 504bd389b36SDavid du Colombier error("mount write"); 505bd389b36SDavid du Colombier } 506bd389b36SDavid du Colombier if (buf[0]=='\0' || strncmp(buf, "write to hung", 13)==0) 507bd389b36SDavid du Colombier exits(""); 508bd389b36SDavid du Colombier fprint(2, "%s: mount read: %s\n", argv0, buf); 509bd389b36SDavid du Colombier exits(buf); 510bd389b36SDavid du Colombier } 511bd389b36SDavid du Colombier 512bd389b36SDavid du Colombier int 513bd389b36SDavid du Colombier perm(Fid *f, Ram *r, int p) 514bd389b36SDavid du Colombier { 515bd389b36SDavid du Colombier if (p==Pwrite && dopermw(r)==0) 516bd389b36SDavid du Colombier return 0; 517bd389b36SDavid du Colombier if((p*Pother) & r->perm) 518bd389b36SDavid du Colombier return 1; 519bd389b36SDavid du Colombier if(strcmp(f->user, r->group)==0 && ((p*Pgroup) & r->perm)) 520bd389b36SDavid du Colombier return 1; 521bd389b36SDavid du Colombier if(strcmp(f->user, r->user)==0 && ((p*Powner) & r->perm)) 522bd389b36SDavid du Colombier return 1; 523bd389b36SDavid du Colombier return 0; 524bd389b36SDavid du Colombier } 525bd389b36SDavid du Colombier 526bd389b36SDavid du Colombier void 527bd389b36SDavid du Colombier error(char *s) 528bd389b36SDavid du Colombier { 529bd389b36SDavid du Colombier fprint(2, "%s: %s: ", argv0, s); 530bd389b36SDavid du Colombier perror(""); 531bd389b36SDavid du Colombier exits(s); 532bd389b36SDavid du Colombier } 533bd389b36SDavid du Colombier 534bd389b36SDavid du Colombier void * 535bd389b36SDavid du Colombier emalloc(ulong n) 536bd389b36SDavid du Colombier { 537bd389b36SDavid du Colombier void *p; 538bd389b36SDavid du Colombier p = malloc(n); 539bd389b36SDavid du Colombier if(!p) 540bd389b36SDavid du Colombier error("out of memory"); 541bd389b36SDavid du Colombier return p; 542bd389b36SDavid du Colombier } 543bd389b36SDavid du Colombier 544bd389b36SDavid du Colombier void * 545bd389b36SDavid du Colombier erealloc(void *p, ulong n) 546bd389b36SDavid du Colombier { 547bd389b36SDavid du Colombier p = realloc(p, n); 548bd389b36SDavid du Colombier if(!p) 549bd389b36SDavid du Colombier error("out of memory"); 550bd389b36SDavid du Colombier return p; 551bd389b36SDavid du Colombier } 552bd389b36SDavid du Colombier 553bd389b36SDavid du Colombier void 554bd389b36SDavid du Colombier usage(void) 555bd389b36SDavid du Colombier { 556bd389b36SDavid du Colombier fprint(2, "usage: %s [-s] [-m mountpoint]\n", argv0); 557bd389b36SDavid du Colombier exits("usage"); 558bd389b36SDavid du Colombier } 559