1 #include <u.h> 2 #include <libc.h> 3 #include <auth.h> 4 #include <fcall.h> 5 #include "iotrack.h" 6 #include "dat.h" 7 #include "fns.h" 8 9 extern Fcall thdr; 10 extern Fcall rhdr; 11 extern char data[sizeof(Fcall)+MAXFDATA]; 12 extern char fdata[MAXFDATA]; 13 extern int errno; 14 15 void 16 rnop(void) 17 { 18 chat("nop..."); 19 } 20 void 21 rsession(void) 22 { 23 memset(thdr.authid, 0, sizeof(thdr.authid)); 24 memset(thdr.authdom, 0, sizeof(thdr.authdom)); 25 memset(thdr.chal, 0, sizeof(thdr.chal)); 26 chat("session..."); 27 } 28 void 29 rflush(void) 30 { 31 chat("flush..."); 32 } 33 void 34 rattach(void) 35 { 36 Xfs *xf; 37 Xfile *root; 38 Dosptr *dp; 39 40 chat("attach(fid=%d,uname=\"%s\",aname=\"%s\",auth=\"%s\")...", 41 thdr.fid, thdr.uname, thdr.aname, thdr.auth); 42 43 root = xfile(thdr.fid, Clean); 44 if(!root){ 45 errno = Enomem; 46 goto error; 47 } 48 root->xf = xf = getxfs(thdr.aname); 49 if(!xf) 50 goto error; 51 if(xf->fmt==0 && dosfs(xf)<0){ 52 errno = Eformat; 53 goto error; 54 } 55 root->qid.path = CHDIR; 56 root->qid.vers = 0; 57 root->xf->rootqid = root->qid; 58 dp = malloc(sizeof(Dosptr)); 59 memset(dp, 0, sizeof(Dosptr)); 60 root->ptr = dp; 61 rhdr.qid = root->qid; 62 return; 63 error: 64 if(root) 65 xfile(thdr.fid, Clunk); 66 return; 67 } 68 void 69 rclone(void) 70 { 71 Xfile *of = xfile(thdr.fid, Asis); 72 Xfile *nf = xfile(thdr.newfid, Clean); 73 74 chat("clone(fid=%d,newfid=%d)...", thdr.fid, thdr.newfid); 75 if(!of) 76 errno = Eio; 77 else if(!nf) 78 errno = Enomem; 79 else{ 80 Xfile *next = nf->next; 81 Dosptr *dp = malloc(sizeof(Dosptr)); 82 *nf = *of; 83 nf->next = next; 84 nf->fid = thdr.newfid; 85 nf->ptr = dp; 86 refxfs(nf->xf, 1); 87 memmove(dp, of->ptr, sizeof(Dosptr)); 88 dp->p = 0; 89 dp->d = 0; 90 } 91 } 92 void 93 rwalk(void) 94 { 95 Xfile *f=xfile(thdr.fid, Asis); 96 Dosptr dp[1]; 97 int r; 98 99 chat("walk(fid=%d,name=\"%s\")...", thdr.fid, thdr.name); 100 if(!f){ 101 chat("no xfile..."); 102 goto error; 103 } 104 if(!(f->qid.path & CHDIR)){ 105 chat("qid.path=0x%x...", f->qid.path); 106 goto error; 107 } 108 if(strcmp(thdr.name, ".")==0){ 109 rhdr.qid = f->qid; 110 return; 111 }else if(strcmp(thdr.name, "..")==0){ 112 if(f->qid.path==f->xf->rootqid.path){ 113 chat("walkup from root..."); 114 rhdr.qid = f->qid; 115 return; 116 } 117 r = walkup(f, dp); 118 if(r < 0) 119 goto error; 120 memmove(f->ptr, dp, sizeof(Dosptr)); 121 if(dp->addr == 0) 122 f->qid.path = f->xf->rootqid.path; 123 else{ 124 Iosect *p; Dosdir *xd; 125 p = getsect(f->xf, dp->addr); 126 if(p == 0) 127 goto error; 128 xd = (Dosdir *)&p->iobuf[dp->offset]; 129 f->qid.path = CHDIR | GSHORT(xd->start); 130 putsect(p); 131 } 132 }else{ 133 if(getfile(f) < 0) 134 goto error; 135 r = searchdir(f, thdr.name, dp, 0); 136 putfile(f); 137 if(r < 0) 138 goto error; 139 memmove(f->ptr, dp, sizeof(Dosptr)); 140 f->qid.path = GSHORT(dp->d->start); 141 if(f->qid.path == 0) 142 f->qid.path = f->xf->rootqid.path; 143 else if(dp->d->attr & DDIR) 144 f->qid.path |= CHDIR; 145 putfile(f); 146 } 147 rhdr.qid = f->qid; 148 return; 149 error: 150 errno = Enonexist; 151 return; 152 } 153 void 154 ropen(void) 155 { 156 Xfile *f; 157 Dosptr *dp; 158 int attr, omode=0; 159 160 chat("open(fid=%d,mode=%d)...", thdr.fid, thdr.mode); 161 f = xfile(thdr.fid, Asis); 162 if(!f || (f->flags&Omodes)){ 163 errno = Eio; 164 return; 165 } 166 dp = f->ptr; 167 if(dp->paddr && (thdr.mode & ORCLOSE)){ 168 /* 169 * check on parent directory of file to be deleted 170 */ 171 Iosect *p = getsect(f->xf, dp->paddr); 172 if(p == 0){ 173 errno = Eio; 174 return; 175 } 176 attr = ((Dosdir *)&p->iobuf[dp->poffset])->attr; 177 putsect(p); 178 if(attr & DRONLY){ 179 errno = Eperm; 180 return; 181 } 182 omode |= Orclose; 183 }else if(thdr.mode & ORCLOSE) 184 omode |= Orclose; 185 if(getfile(f) < 0){ 186 errno = Enonexist; 187 return; 188 } 189 if(dp->addr) 190 attr = dp->d->attr; 191 else 192 attr = DDIR; 193 switch(thdr.mode & 7){ 194 case OREAD: 195 case OEXEC: 196 omode |= Oread; 197 break; 198 case ORDWR: 199 omode |= Oread; 200 /* fall through */ 201 case OWRITE: 202 omode |= Owrite; 203 if(attr & DRONLY){ 204 errno = Eperm; 205 goto out; 206 } 207 break; 208 default: 209 errno = Eio; 210 goto out; 211 } 212 if(thdr.mode & OTRUNC){ 213 if(attr & DDIR || attr & DRONLY){ 214 errno = Eperm; 215 goto out; 216 } 217 if(truncfile(f, 0) < 0){ 218 errno = Eio; 219 goto out; 220 } 221 } 222 f->flags |= omode; 223 chat("f->qid=0x%8.8lux...", f->qid.path); 224 rhdr.qid = f->qid; 225 out: 226 putfile(f); 227 } 228 void 229 rcreate(void) 230 { 231 Dosbpb *bp; 232 Xfile *f; 233 Dosptr *pdp, *ndp; 234 Iosect *xp; 235 Dosdir *pd, *nd, *xd; 236 int attr, omode=0, start; 237 238 chat("create(fid=%d,name=\"%s\",perm=%uo,mode=%d)...", 239 thdr.fid, thdr.name, thdr.perm, thdr.mode); 240 f = xfile(thdr.fid, Asis); 241 if(!f || (f->flags&Omodes) || getfile(f)<0){ 242 errno = Eio; 243 return; 244 } 245 ndp = malloc(sizeof(Dosptr)); 246 pdp = f->ptr; 247 pd = pdp->addr ? pdp->d : 0; 248 attr = pd ? pd->attr : DDIR; 249 if(!(attr & DDIR) || (attr & DRONLY)){ 250 badperm: 251 if(ndp) 252 free(ndp); 253 putfile(f); 254 errno = Eperm; 255 return; 256 } 257 if(thdr.mode & ORCLOSE) 258 omode |= Orclose; 259 switch(thdr.mode & 7){ 260 case OREAD: 261 case OEXEC: 262 omode |= Oread; 263 break; 264 case ORDWR: 265 omode |= Oread; 266 /* fall through */ 267 case OWRITE: 268 omode |= Owrite; 269 if(thdr.perm & CHDIR) 270 goto badperm; 271 break; 272 default: 273 goto badperm; 274 } 275 if(strcmp(thdr.name, ".") == 0 || strcmp(thdr.name, "..") == 0) 276 goto badperm; 277 if(searchdir(f, thdr.name, ndp, 1) < 0) 278 goto badperm; 279 bp = f->xf->ptr; 280 lock(bp); 281 start = falloc(f->xf); 282 unlock(bp); 283 if(start <= 0){ 284 if(ndp) 285 free(ndp); 286 putfile(f); 287 errno = Eio; 288 return; 289 } 290 /* 291 * now we're committed 292 */ 293 if(pd){ 294 puttime(pd, 0); 295 pdp->p->flags |= BMOD; 296 } 297 f->ptr = ndp; 298 f->qid.path = start; 299 ndp->p = getsect(f->xf, ndp->addr); 300 if(ndp->p == 0) 301 goto badio; 302 ndp->d = (Dosdir *)&ndp->p->iobuf[ndp->offset]; 303 nd = ndp->d; 304 memset(nd, 0, sizeof(Dosdir)); 305 putname(thdr.name, nd); 306 if((thdr.perm & 0222) == 0) 307 nd->attr |= DRONLY; 308 puttime(nd, 0); 309 nd->start[0] = start; 310 nd->start[1] = start>>8; 311 if(thdr.perm & CHDIR){ 312 nd->attr |= DDIR; 313 f->qid.path |= CHDIR; 314 xp = getsect(f->xf, bp->dataaddr+(start-2)*bp->clustsize); 315 if(xp == 0) 316 goto badio; 317 xd = (Dosdir *)&xp->iobuf[0]; 318 memmove(xd, nd, sizeof(Dosdir)); 319 memset(xd->name, ' ', sizeof xd->name+sizeof xd->ext); 320 xd->name[0] = '.'; 321 xd = (Dosdir *)&xp->iobuf[sizeof(Dosdir)]; 322 if(pd) 323 memmove(xd, pd, sizeof(Dosdir)); 324 else{ 325 memset(xd, 0, sizeof(Dosdir)); 326 puttime(xd, 0); 327 xd->attr = DDIR; 328 } 329 memset(xd->name, ' ', sizeof xd->name+sizeof xd->ext); 330 xd->name[0] = '.'; 331 xd->name[1] = '.'; 332 xp->flags |= BMOD; 333 putsect(xp); 334 } 335 ndp->p->flags |= BMOD; 336 putfile(f); 337 putsect(pdp->p); 338 free(pdp); 339 f->flags |= omode; 340 chat("f->qid=0x%8.8lux...", f->qid.path); 341 rhdr.qid = f->qid; 342 return; 343 badio: 344 if(ndp->p) 345 putfile(f); 346 putsect(pdp->p); 347 free(pdp); 348 errno = Eio; 349 } 350 void 351 rread(void) 352 { 353 Xfile *f; int r; 354 355 chat("read(fid=%d,offset=%d,count=%d)...", 356 thdr.fid, thdr.offset, thdr.count); 357 if (!(f=xfile(thdr.fid, Asis)) || !(f->flags&Oread)) 358 goto error; 359 if(f->qid.path & CHDIR){ 360 thdr.count = (thdr.count/DIRLEN)*DIRLEN; 361 if(thdr.count<DIRLEN || thdr.offset%DIRLEN){ 362 chat("count=%d,offset=%d,DIRLEN=%d...", 363 thdr.count, thdr.offset, DIRLEN); 364 goto error; 365 } 366 if(getfile(f) < 0) 367 goto error; 368 r = readdir(f, fdata, thdr.offset, thdr.count); 369 }else{ 370 if(getfile(f) < 0) 371 goto error; 372 r = readfile(f, fdata, thdr.offset, thdr.count); 373 } 374 putfile(f); 375 if(r < 0){ 376 error: 377 errno = Eio; 378 }else{ 379 rhdr.count = r; 380 rhdr.data = fdata; 381 chat("rcnt=%d...", r); 382 } 383 } 384 void 385 rwrite(void) 386 { 387 Xfile *f; int r; 388 389 chat("write(fid=%d,offset=%d,count=%d)...", 390 thdr.fid, thdr.offset, thdr.count); 391 if (!(f=xfile(thdr.fid, Asis)) || !(f->flags&Owrite)) 392 goto error; 393 if(getfile(f) < 0) 394 goto error; 395 r = writefile(f, thdr.data, thdr.offset, thdr.count); 396 putfile(f); 397 if(r < 0){ 398 error: 399 errno = Eio; 400 }else{ 401 rhdr.count = r; 402 chat("rcnt=%d...", r); 403 } 404 } 405 void 406 rclunk(void) 407 { 408 chat("clunk(fid=%d)...", thdr.fid); 409 xfile(thdr.fid, Clunk); 410 sync(); 411 } 412 void 413 rremove(void) 414 { 415 Xfile *f=xfile(thdr.fid, Asis); 416 Dosptr *dp; 417 Iosect *parp; Dosdir *pard; 418 419 chat("remove(fid=%d,name=\"%s\")...", thdr.fid, thdr.name); 420 if(!f){ 421 errno = Eio; 422 goto out; 423 } 424 dp = f->ptr; 425 if(!dp->addr){ 426 chat("root..."); 427 errno = Eperm; 428 goto out; 429 } 430 /* 431 * check on parent directory of file to be deleted 432 */ 433 parp = getsect(f->xf, dp->paddr); 434 if(parp == 0){ 435 errno = Eio; 436 goto out; 437 } 438 pard = (Dosdir *)&parp->iobuf[dp->poffset]; 439 if(dp->paddr && (pard->attr & DRONLY)){ 440 chat("parent read-only..."); 441 putsect(parp); 442 errno = Eperm; 443 goto out; 444 } 445 if(getfile(f) < 0){ 446 chat("getfile failed..."); 447 putsect(parp); 448 errno = Eio; 449 goto out; 450 } 451 if((dp->d->attr & DDIR) && emptydir(f) < 0){ 452 chat("non-empty dir..."); 453 putfile(f); 454 putsect(parp); 455 errno = Eperm; 456 goto out; 457 } 458 if(dp->paddr == 0 && (dp->d->attr&DRONLY)){ 459 chat("read-only file in root directory..."); 460 putfile(f); 461 putsect(parp); 462 errno = Eperm; 463 goto out; 464 } 465 if(dp->paddr){ 466 puttime(pard, 0); 467 parp->flags |= BMOD; 468 } 469 putsect(parp); 470 if(truncfile(f, 1) < 0) 471 errno = Eio; 472 dp->d->name[0] = 0xe5; 473 dp->p->flags |= BMOD; 474 putfile(f); 475 out: 476 xfile(thdr.fid, Clunk); 477 sync(); 478 } 479 void 480 rstat(void) 481 { 482 Dir dir; 483 Xfile *f=xfile(thdr.fid, Asis); 484 Dosptr *dp = f->ptr; 485 486 chat("stat(fid=%d)...", thdr.fid); 487 if(!f || getfile(f)< 0) 488 errno = Eio; 489 else{ 490 getdir(&dir, dp->addr ? dp->d : 0); 491 convD2M(&dir, rhdr.stat); 492 putfile(f); 493 } 494 } 495 496 static char isfrog[256]={ 497 /*NUL*/ 1, 1, 1, 1, 1, 1, 1, 1, 498 /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1, 499 /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1, 500 /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1, 501 [' '] 1, 502 ['/'] 1, 503 [0x7f] 1, 504 }; 505 506 static int 507 nameok(char *elem) 508 { 509 char *eelem; 510 511 eelem = elem+NAMELEN; 512 while(*elem){ 513 if(isfrog[*(uchar*)elem]) 514 return -1; 515 elem++; 516 if(elem >= eelem) 517 return -1; 518 } 519 return 0; 520 } 521 522 void 523 rwstat(void) 524 { 525 errno = Eperm; 526 } 527