sysfile.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. /*
  16. * The sys*() routines needn't poperror() as they return directly to syscall().
  17. */
  18. static void
  19. unlockfgrp(Fgrp *f)
  20. {
  21. int ex;
  22. ex = f->exceed;
  23. f->exceed = 0;
  24. unlock(&f->r.l);
  25. if(ex)
  26. pprint("warning: process exceeds %d file descriptors\n", ex);
  27. }
  28. static int
  29. growfd(Fgrp *f, int fd) /* fd is always >= 0 */
  30. {
  31. Chan **newfd, **oldfd;
  32. if(fd < f->nfd)
  33. return 0;
  34. if(fd >= f->nfd+DELTAFD)
  35. return -1; /* out of range */
  36. /*
  37. * Unbounded allocation is unwise; besides, there are only 16 bits
  38. * of fid in 9P
  39. */
  40. if(f->nfd >= 5000){
  41. Exhausted:
  42. print("no free file descriptors\n");
  43. return -1;
  44. }
  45. newfd = malloc((f->nfd+DELTAFD)*sizeof(Chan*));
  46. if(newfd == 0)
  47. goto Exhausted;
  48. oldfd = f->fd;
  49. memmove(newfd, oldfd, f->nfd*sizeof(Chan*));
  50. f->fd = newfd;
  51. free(oldfd);
  52. f->nfd += DELTAFD;
  53. if(fd > f->maxfd){
  54. if(fd/100 > f->maxfd/100)
  55. f->exceed = (fd/100)*100;
  56. f->maxfd = fd;
  57. }
  58. return 1;
  59. }
  60. /*
  61. * this assumes that the fgrp is locked
  62. */
  63. static int
  64. findfreefd(Fgrp *f, int start)
  65. {
  66. int fd;
  67. for(fd=start; fd<f->nfd; fd++)
  68. if(f->fd[fd] == 0)
  69. break;
  70. if(fd >= f->nfd && growfd(f, fd) < 0)
  71. return -1;
  72. return fd;
  73. }
  74. int
  75. newfd(Chan *c)
  76. {
  77. Proc *up = externup();
  78. int fd;
  79. Fgrp *f;
  80. f = up->fgrp;
  81. lock(&f->r.l);
  82. fd = findfreefd(f, 0);
  83. if(fd < 0){
  84. unlockfgrp(f);
  85. return -1;
  86. }
  87. if(fd > f->maxfd)
  88. f->maxfd = fd;
  89. f->fd[fd] = c;
  90. unlockfgrp(f);
  91. return fd;
  92. }
  93. static int
  94. newfd2(int fd[2], Chan *c[2])
  95. {
  96. Proc *up = externup();
  97. Fgrp *f;
  98. f = up->fgrp;
  99. lock(&f->r.l);
  100. fd[0] = findfreefd(f, 0);
  101. if(fd[0] < 0){
  102. unlockfgrp(f);
  103. return -1;
  104. }
  105. fd[1] = findfreefd(f, fd[0]+1);
  106. if(fd[1] < 0){
  107. unlockfgrp(f);
  108. return -1;
  109. }
  110. if(fd[1] > f->maxfd)
  111. f->maxfd = fd[1];
  112. f->fd[fd[0]] = c[0];
  113. f->fd[fd[1]] = c[1];
  114. unlockfgrp(f);
  115. return 0;
  116. }
  117. Chan*
  118. fdtochan(int fd, int mode, int chkmnt, int iref)
  119. {
  120. Proc *up = externup();
  121. Chan *c;
  122. Fgrp *f;
  123. c = nil;
  124. f = up->fgrp;
  125. lock(&f->r.l);
  126. if(fd<0 || f->nfd<=fd || (c = f->fd[fd])==0) {
  127. unlock(&f->r.l);
  128. error(Ebadfd);
  129. }
  130. if(iref)
  131. incref(&c->r);
  132. unlock(&f->r.l);
  133. if(chkmnt && (c->flag&CMSG)) {
  134. if(iref)
  135. cclose(c);
  136. error(Ebadusefd);
  137. }
  138. if(mode<0 || c->mode==ORDWR)
  139. return c;
  140. if((mode&OTRUNC) && c->mode==OREAD) {
  141. if(iref)
  142. cclose(c);
  143. error(Ebadusefd);
  144. }
  145. if((mode&~OTRUNC) != c->mode) {
  146. if(iref)
  147. cclose(c);
  148. error(Ebadusefd);
  149. }
  150. return c;
  151. }
  152. int
  153. openmode(int omode)
  154. {
  155. omode &= ~(OTRUNC|OCEXEC|ORCLOSE);
  156. if(omode > OEXEC)
  157. error(Ebadarg);
  158. if(omode == OEXEC)
  159. return OREAD;
  160. return omode;
  161. }
  162. void
  163. sysfd2path(Ar0* ar0, ...)
  164. {
  165. Chan *c;
  166. char *buf;
  167. int fd;
  168. usize nbuf;
  169. va_list list;
  170. va_start(list, ar0);
  171. /*
  172. * int fd2path(int fd, char* buf, int nbuf);
  173. * should be
  174. * int fd2path(int fd, char* buf, usize nbuf);
  175. */
  176. fd = va_arg(list, int);
  177. buf = va_arg(list, char*);
  178. nbuf = va_arg(list, usize);
  179. va_end(list);
  180. buf = validaddr(buf, nbuf, 1);
  181. c = fdtochan(fd, -1, 0, 1);
  182. snprint(buf, nbuf, "%s", chanpath(c));
  183. cclose(c);
  184. ar0->i = 0;
  185. }
  186. void
  187. syspipe(Ar0* ar0, ...)
  188. {
  189. Proc *up = externup();
  190. int *a, fd[2];
  191. Chan *c[2];
  192. static char *datastr[] = {"data", "data1"};
  193. va_list list;
  194. va_start(list, ar0);
  195. /*
  196. * int pipe(int fd[2]);
  197. */
  198. a = va_arg(list, int*);
  199. va_end(list);
  200. a = validaddr(a, sizeof(fd), 1);
  201. evenaddr(PTR2UINT(a));
  202. c[0] = namec("#|", Atodir, 0, 0);
  203. c[1] = nil;
  204. fd[0] = -1;
  205. fd[1] = -1;
  206. if(waserror()){
  207. cclose(c[0]);
  208. if(c[1])
  209. cclose(c[1]);
  210. nexterror();
  211. }
  212. c[1] = cclone(c[0]);
  213. if(walk(&c[0], datastr+0, 1, 1, nil) < 0)
  214. error(Egreg);
  215. if(walk(&c[1], datastr+1, 1, 1, nil) < 0)
  216. error(Egreg);
  217. c[0] = c[0]->dev->open(c[0], ORDWR);
  218. c[1] = c[1]->dev->open(c[1], ORDWR);
  219. if(newfd2(fd, c) < 0)
  220. error(Enofd);
  221. poperror();
  222. a[0] = fd[0];
  223. a[1] = fd[1];
  224. ar0->i = 0;
  225. }
  226. void
  227. sysdup(Ar0* ar0, ...)
  228. {
  229. Proc *up = externup();
  230. int nfd, ofd;
  231. Chan *nc, *oc;
  232. Fgrp *f;
  233. va_list list;
  234. va_start(list, ar0);
  235. /*
  236. * int dup(int oldfd, int newfd);
  237. *
  238. * Close after dup'ing, so date > #d/1 works
  239. */
  240. ofd = va_arg(list, int);
  241. oc = fdtochan(ofd, -1, 0, 1);
  242. nfd = va_arg(list, int);
  243. va_end(list);
  244. if(nfd != -1){
  245. f = up->fgrp;
  246. lock(&f->r.l);
  247. if(nfd < 0 || growfd(f, nfd) < 0) {
  248. unlockfgrp(f);
  249. cclose(oc);
  250. error(Ebadfd);
  251. }
  252. if(nfd > f->maxfd)
  253. f->maxfd = nfd;
  254. nc = f->fd[nfd];
  255. f->fd[nfd] = oc;
  256. unlockfgrp(f);
  257. if(nc != nil)
  258. cclose(nc);
  259. }else{
  260. if(waserror()) {
  261. cclose(oc);
  262. nexterror();
  263. }
  264. nfd = newfd(oc);
  265. if(nfd < 0)
  266. error(Enofd);
  267. poperror();
  268. }
  269. ar0->i = nfd;
  270. }
  271. void
  272. sysopen(Ar0* ar0, ...)
  273. {
  274. Proc *up = externup();
  275. va_list list;
  276. char *aname;
  277. int fd, omode;
  278. Chan *c;
  279. /*
  280. * int open(char* file, int omode);
  281. */
  282. va_start(list, ar0);
  283. aname = va_arg(list, char*);
  284. omode = va_arg(list, int);
  285. va_end(list);
  286. openmode(omode); /* error check only */
  287. c = nil;
  288. if(waserror()){
  289. if(c != nil)
  290. cclose(c);
  291. nexterror();
  292. }
  293. aname = validaddr(aname, 1, 0);
  294. c = namec(aname, Aopen, omode, 0);
  295. fd = newfd(c);
  296. if(fd < 0)
  297. error(Enofd);
  298. poperror();
  299. ar0->i = fd;
  300. }
  301. void
  302. sysnsec(Ar0* ar0, ...)
  303. {
  304. va_list list;
  305. va_start(list, ar0);
  306. va_end(list);
  307. /*
  308. * int64_t nsec(void);
  309. */
  310. ar0->vl = todget(nil);
  311. }
  312. void
  313. fdclose(int fd, int flag)
  314. {
  315. Proc *up = externup();
  316. int i;
  317. Chan *c;
  318. Fgrp *f;
  319. f = up->fgrp;
  320. lock(&f->r.l);
  321. c = f->fd[fd];
  322. if(c == nil){
  323. /* can happen for users with shared fd tables */
  324. unlock(&f->r.l);
  325. return;
  326. }
  327. if(flag){
  328. if(c == nil || !(c->flag&flag)){
  329. unlock(&f->r.l);
  330. return;
  331. }
  332. }
  333. f->fd[fd] = nil;
  334. if(fd == f->maxfd)
  335. for(i = fd; --i >= 0 && f->fd[i] == 0; )
  336. f->maxfd = i;
  337. unlock(&f->r.l);
  338. cclose(c);
  339. }
  340. void
  341. sysclose(Ar0* ar0, ...)
  342. {
  343. int fd;
  344. va_list list;
  345. va_start(list, ar0);
  346. /*
  347. * int close(int fd);
  348. */
  349. fd = va_arg(list, int);
  350. va_end(list);
  351. fdtochan(fd, -1, 0, 0);
  352. fdclose(fd, 0);
  353. ar0->i = 0;
  354. }
  355. static int32_t
  356. unionread(Chan *c, void *va, int32_t n)
  357. {
  358. Proc *up = externup();
  359. int i;
  360. int32_t nr;
  361. Mhead *mh;
  362. Mount *mount;
  363. qlock(&c->umqlock);
  364. mh = c->umh;
  365. rlock(&mh->lock);
  366. mount = mh->mount;
  367. /* bring mount in sync with c->uri and c->umc */
  368. for(i = 0; mount != nil && i < c->uri; i++)
  369. mount = mount->next;
  370. nr = 0;
  371. while(mount != nil){
  372. /* Error causes component of union to be skipped */
  373. if(mount->to && !waserror()){
  374. if(c->umc == nil){
  375. c->umc = cclone(mount->to);
  376. c->umc = c->umc->dev->open(c->umc, OREAD);
  377. }
  378. nr = c->umc->dev->read(c->umc, va, n, c->umc->offset);
  379. c->umc->offset += nr;
  380. poperror();
  381. }
  382. if(nr > 0)
  383. break;
  384. /* Advance to next element */
  385. c->uri++;
  386. if(c->umc){
  387. cclose(c->umc);
  388. c->umc = nil;
  389. }
  390. mount = mount->next;
  391. }
  392. runlock(&mh->lock);
  393. qunlock(&c->umqlock);
  394. return nr;
  395. }
  396. static void
  397. unionrewind(Chan *c)
  398. {
  399. qlock(&c->umqlock);
  400. c->uri = 0;
  401. if(c->umc){
  402. cclose(c->umc);
  403. c->umc = nil;
  404. }
  405. qunlock(&c->umqlock);
  406. }
  407. static usize
  408. dirfixed(uint8_t *p, uint8_t *e, Dir *d)
  409. {
  410. int len;
  411. Dev *dev;
  412. len = GBIT16(p)+BIT16SZ;
  413. if(p + len > e)
  414. return 0;
  415. p += BIT16SZ; /* ignore size */
  416. dev = devtabget(GBIT16(p), 1); //XDYNX
  417. if(dev != nil){
  418. d->type = dev->dc;
  419. //devtabdecr(dev);
  420. }
  421. else
  422. d->type = -1;
  423. p += BIT16SZ;
  424. d->dev = GBIT32(p);
  425. p += BIT32SZ;
  426. d->qid.type = GBIT8(p);
  427. p += BIT8SZ;
  428. d->qid.vers = GBIT32(p);
  429. p += BIT32SZ;
  430. d->qid.path = GBIT64(p);
  431. p += BIT64SZ;
  432. d->mode = GBIT32(p);
  433. p += BIT32SZ;
  434. d->atime = GBIT32(p);
  435. p += BIT32SZ;
  436. d->mtime = GBIT32(p);
  437. p += BIT32SZ;
  438. d->length = GBIT64(p);
  439. return len;
  440. }
  441. static char*
  442. dirname(uint8_t *p, usize *n)
  443. {
  444. p += BIT16SZ+BIT16SZ+BIT32SZ+BIT8SZ+BIT32SZ+BIT64SZ
  445. + BIT32SZ+BIT32SZ+BIT32SZ+BIT64SZ;
  446. *n = GBIT16(p);
  447. return (char*)p+BIT16SZ;
  448. }
  449. static usize
  450. dirsetname(char *name, usize len, uint8_t *p, usize n, usize maxn)
  451. {
  452. char *oname;
  453. usize nn, olen;
  454. if(n == BIT16SZ)
  455. return BIT16SZ;
  456. oname = dirname(p, &olen);
  457. nn = n+len-olen;
  458. PBIT16(p, nn-BIT16SZ);
  459. if(nn > maxn)
  460. return BIT16SZ;
  461. if(len != olen)
  462. memmove(oname+len, oname+olen, p+n-(uint8_t*)(oname+olen));
  463. PBIT16((uint8_t*)(oname-2), len);
  464. memmove(oname, name, len);
  465. return nn;
  466. }
  467. /*
  468. * Mountfix might have caused the fixed results of the directory read
  469. * to overflow the buffer. Catch the overflow in c->dirrock.
  470. */
  471. static void
  472. mountrock(Chan *c, uint8_t *p, uint8_t **pe)
  473. {
  474. uint8_t *e, *r;
  475. int len, n;
  476. e = *pe;
  477. /* find last directory entry */
  478. for(;;){
  479. len = BIT16SZ+GBIT16(p);
  480. if(p+len >= e)
  481. break;
  482. p += len;
  483. }
  484. /* save it away */
  485. qlock(&c->rockqlock);
  486. if(c->nrock+len > c->mrock){
  487. n = ROUNDUP(c->nrock+len, 1024);
  488. r = smalloc(n);
  489. memmove(r, c->dirrock, c->nrock);
  490. free(c->dirrock);
  491. c->dirrock = r;
  492. c->mrock = n;
  493. }
  494. memmove(c->dirrock+c->nrock, p, len);
  495. c->nrock += len;
  496. qunlock(&c->rockqlock);
  497. /* drop it */
  498. *pe = p;
  499. }
  500. /*
  501. * Satisfy a directory read with the results saved in c->dirrock.
  502. */
  503. static int
  504. mountrockread(Chan *c, uint8_t *op, int32_t n, int32_t *nn)
  505. {
  506. int32_t dirlen;
  507. uint8_t *rp, *erp, *ep, *p;
  508. /* common case */
  509. if(c->nrock == 0)
  510. return 0;
  511. /* copy out what we can */
  512. qlock(&c->rockqlock);
  513. rp = c->dirrock;
  514. erp = rp+c->nrock;
  515. p = op;
  516. ep = p+n;
  517. while(rp+BIT16SZ <= erp){
  518. dirlen = BIT16SZ+GBIT16(rp);
  519. if(p+dirlen > ep)
  520. break;
  521. memmove(p, rp, dirlen);
  522. p += dirlen;
  523. rp += dirlen;
  524. }
  525. if(p == op){
  526. qunlock(&c->rockqlock);
  527. return 0;
  528. }
  529. /* shift the rest */
  530. if(rp != erp)
  531. memmove(c->dirrock, rp, erp-rp);
  532. c->nrock = erp - rp;
  533. *nn = p - op;
  534. qunlock(&c->rockqlock);
  535. return 1;
  536. }
  537. static void
  538. mountrewind(Chan *c)
  539. {
  540. c->nrock = 0;
  541. }
  542. /*
  543. * Rewrite the results of a directory read to reflect current
  544. * name space bindings and mounts. Specifically, replace
  545. * directory entries for bind and mount points with the results
  546. * of statting what is mounted there. Except leave the old names.
  547. */
  548. static int32_t
  549. mountfix(Chan *c, uint8_t *op, int32_t n, int32_t maxn)
  550. {
  551. Proc *up = externup();
  552. char *name;
  553. int nbuf;
  554. Chan *nc;
  555. Mhead *mh;
  556. Mount *mount;
  557. usize dirlen, nname, r, rest;
  558. int32_t l;
  559. uint8_t *buf, *e, *p;
  560. Dir d;
  561. p = op;
  562. buf = nil;
  563. nbuf = 0;
  564. for(e=&p[n]; p+BIT16SZ<e; p+=dirlen){
  565. dirlen = dirfixed(p, e, &d);
  566. if(dirlen == 0)
  567. break;
  568. nc = nil;
  569. mh = nil;
  570. if(findmount(&nc, &mh, d.type, d.dev, d.qid)){
  571. /*
  572. * If it's a union directory and the original is
  573. * in the union, don't rewrite anything.
  574. */
  575. for(mount=mh->mount; mount; mount=mount->next)
  576. if(eqchanddq(mount->to, d.type, d.dev, d.qid, 1))
  577. goto Norewrite;
  578. name = dirname(p, &nname);
  579. /*
  580. * Do the stat but fix the name. If it fails,
  581. * leave old entry.
  582. * BUG: If it fails because there isn't room for
  583. * the entry, what can we do? Nothing, really.
  584. * Might as well skip it.
  585. */
  586. if(buf == nil){
  587. buf = smalloc(4096);
  588. nbuf = 4096;
  589. }
  590. if(waserror())
  591. goto Norewrite;
  592. l = nc->dev->stat(nc, buf, nbuf);
  593. r = dirsetname(name, nname, buf, l, nbuf);
  594. if(r == BIT16SZ)
  595. error("dirsetname");
  596. poperror();
  597. /*
  598. * Shift data in buffer to accomodate new entry,
  599. * possibly overflowing into rock.
  600. */
  601. rest = e - (p+dirlen);
  602. if(r > dirlen){
  603. while(p+r+rest > op+maxn){
  604. mountrock(c, p, &e);
  605. if(e == p){
  606. dirlen = 0;
  607. goto Norewrite;
  608. }
  609. rest = e - (p+dirlen);
  610. }
  611. }
  612. if(r != dirlen){
  613. memmove(p+r, p+dirlen, rest);
  614. dirlen = r;
  615. e = p+dirlen+rest;
  616. }
  617. /*
  618. * Rewrite directory entry.
  619. */
  620. memmove(p, buf, r);
  621. Norewrite:
  622. cclose(nc);
  623. putmhead(mh);
  624. }
  625. }
  626. if(buf)
  627. free(buf);
  628. if(p != e)
  629. error("oops in mountfix");
  630. return e-op;
  631. }
  632. static int32_t
  633. read(int ispread, int fd, void *p, int32_t n, int64_t off)
  634. {
  635. Proc *up = externup();
  636. int32_t nn, nnn;
  637. Chan *c;
  638. p = validaddr(p, n, 1);
  639. c = fdtochan(fd, OREAD, 1, 1);
  640. if(waserror()){
  641. cclose(c);
  642. nexterror();
  643. }
  644. /*
  645. * The offset is passed through on directories, normally.
  646. * Sysseek complains, but pread is used by servers like exportfs,
  647. * that shouldn't need to worry about this issue.
  648. *
  649. * Notice that c->devoffset is the offset that c's dev is seeing.
  650. * The number of bytes read on this fd (c->offset) may be different
  651. * due to rewritings in mountfix.
  652. */
  653. if(ispread){
  654. if(off == ~0LL){ /* use and maintain channel's offset */
  655. off = c->offset;
  656. ispread = 0;
  657. }
  658. }
  659. else
  660. off = c->offset;
  661. if(c->qid.type & QTDIR){
  662. /*
  663. * Directory read:
  664. * rewind to the beginning of the file if necessary;
  665. * try to fill the buffer via mountrockread;
  666. * clear ispread to always maintain the Chan offset.
  667. */
  668. if(off == 0LL){
  669. if(!ispread){
  670. c->offset = 0;
  671. c->devoffset = 0;
  672. }
  673. mountrewind(c);
  674. unionrewind(c);
  675. }
  676. if(!mountrockread(c, p, n, &nn)){
  677. if(c->umh)
  678. nn = unionread(c, p, n);
  679. else{
  680. if(off != c->offset)
  681. error(Edirseek);
  682. nn = c->dev->read(c, p, n, c->devoffset);
  683. }
  684. }
  685. nnn = mountfix(c, p, nn, n);
  686. ispread = 0;
  687. }
  688. else
  689. nnn = nn = c->dev->read(c, p, n, off);
  690. if(!ispread){
  691. lock(&c->r.l);
  692. c->devoffset += nn;
  693. c->offset += nnn;
  694. unlock(&c->r.l);
  695. }
  696. poperror();
  697. cclose(c);
  698. return nnn;
  699. }
  700. void
  701. sysread(Ar0* ar0, ...)
  702. {
  703. int fd;
  704. void *p;
  705. int32_t n;
  706. int64_t off = ~0ULL;
  707. va_list list;
  708. va_start(list, ar0);
  709. fd = va_arg(list, int);
  710. p = va_arg(list, void*);
  711. n = va_arg(list, int32_t);
  712. va_end(list);
  713. /*
  714. * long read(int fd, void* buf, long nbytes);
  715. */
  716. ar0->l = read(0, fd, p, n, off);
  717. }
  718. void
  719. syspread(Ar0* ar0, ...)
  720. {
  721. int fd;
  722. void *p;
  723. int32_t n;
  724. int64_t off;
  725. va_list list;
  726. va_start(list, ar0);
  727. fd = va_arg(list, int);
  728. p = va_arg(list, void*);
  729. n = va_arg(list, int32_t);
  730. off = va_arg(list, int64_t);
  731. va_end(list);
  732. /*
  733. * long pread(int fd, void* buf, long nbytes, int64_t offset);
  734. */
  735. ar0->l = read(1, fd, p, n, off);
  736. }
  737. static int32_t
  738. write(int fd, void *p, int32_t n, int64_t off, int ispwrite)
  739. {
  740. Proc *up = externup();
  741. int32_t r;
  742. Chan *c;
  743. r = n;
  744. p = validaddr(p, n, 0);
  745. n = 0;
  746. c = fdtochan(fd, OWRITE, 1, 1);
  747. if(waserror()) {
  748. if(!ispwrite){
  749. lock(&c->r.l);
  750. c->offset -= n;
  751. unlock(&c->r.l);
  752. }
  753. cclose(c);
  754. nexterror();
  755. }
  756. if(c->qid.type & QTDIR)
  757. error(Eisdir);
  758. n = r;
  759. if(off == ~0LL){ /* use and maintain channel's offset */
  760. lock(&c->r.l);
  761. off = c->offset;
  762. c->offset += n;
  763. unlock(&c->r.l);
  764. }
  765. r = c->dev->write(c, p, n, off);
  766. if(!ispwrite && r < n){
  767. lock(&c->r.l);
  768. c->offset -= n - r;
  769. unlock(&c->r.l);
  770. }
  771. poperror();
  772. cclose(c);
  773. return r;
  774. }
  775. void
  776. syswrite(Ar0* ar0, ...)
  777. {
  778. va_list list;
  779. va_start(list, ar0);
  780. int fd = va_arg(list, int);
  781. void *buf = va_arg(list, void *);
  782. long nbytes = va_arg(list, long);
  783. int64_t offset = -1ULL;
  784. va_end(list);
  785. /*
  786. * long write(int fd, void* buf, long nbytes);
  787. */
  788. ar0->l = write(fd, buf, nbytes, offset, 0);
  789. }
  790. void
  791. syspwrite(Ar0* ar0, ...)
  792. {
  793. va_list list;
  794. va_start(list, ar0);
  795. int fd = va_arg(list, int);
  796. void *buf = va_arg(list, void *);
  797. long nbytes = va_arg(list, long);
  798. int64_t offset = va_arg(list, int64_t);
  799. va_end(list);
  800. /*
  801. * long pwrite(int fd, void *buf, long nbytes, int64_t offset);
  802. */
  803. ar0->l = write(fd, buf, nbytes, offset, 1);
  804. }
  805. static int64_t
  806. sseek(int fd, int64_t offset, int whence)
  807. {
  808. Proc *up = externup();
  809. Chan *c;
  810. uint8_t buf[sizeof(Dir)+100];
  811. Dir dir;
  812. int n;
  813. c = fdtochan(fd, -1, 1, 1);
  814. if(waserror()){
  815. cclose(c);
  816. nexterror();
  817. }
  818. if(c->dev->dc == '|')
  819. error(Eisstream);
  820. switch(whence){
  821. case 0:
  822. if((c->qid.type & QTDIR) && offset != 0LL)
  823. error(Eisdir);
  824. c->offset = offset;
  825. break;
  826. case 1:
  827. if(c->qid.type & QTDIR)
  828. error(Eisdir);
  829. lock(&c->r.l); /* lock for read/write update */
  830. offset += c->offset;
  831. c->offset = offset;
  832. unlock(&c->r.l);
  833. break;
  834. case 2:
  835. if(c->qid.type & QTDIR)
  836. error(Eisdir);
  837. n = c->dev->stat(c, buf, sizeof buf);
  838. if(convM2D(buf, n, &dir, nil) == 0)
  839. error("internal error: stat error in seek");
  840. offset += dir.length;
  841. c->offset = offset;
  842. break;
  843. default:
  844. error(Ebadarg);
  845. }
  846. c->uri = 0;
  847. c->dri = 0;
  848. cclose(c);
  849. poperror();
  850. return offset;
  851. }
  852. void
  853. sysseek(Ar0* ar0, ...)
  854. {
  855. int fd, whence;
  856. int64_t offset, *rv;
  857. va_list list;
  858. va_start(list, ar0);
  859. /*
  860. * int64_t seek(int fd, int64_t n, int type);
  861. *
  862. * The system call actually has 4 arguments,
  863. * int _seek(int64_t*, int, int64_t, int);
  864. * and the first argument is where the offset
  865. * is returned. The C library arranges the
  866. * argument/return munging if necessary.
  867. */
  868. rv = va_arg(list, int64_t*);
  869. rv = validaddr(rv, sizeof(int64_t), 1);
  870. fd = va_arg(list, int);
  871. offset = va_arg(list, int64_t);
  872. whence = va_arg(list, int);
  873. va_end(list);
  874. *rv = sseek(fd, offset, whence);
  875. ar0->i = 0;
  876. }
  877. void
  878. sysoseek(Ar0* ar0, ...)
  879. {
  880. int32_t offset;
  881. int fd, whence;
  882. va_list list;
  883. va_start(list, ar0);
  884. /*
  885. * long oseek(int fd, long n, int type);
  886. *
  887. * Deprecated; backwards compatibility only.
  888. */
  889. fd = va_arg(list, int);
  890. offset = va_arg(list, int32_t);
  891. whence = va_arg(list, int);
  892. va_end(list);
  893. ar0->l = sseek(fd, offset, whence);
  894. }
  895. void
  896. validstat(uint8_t *s, usize n)
  897. {
  898. usize m;
  899. char buf[64];
  900. if(statcheck(s, n) < 0)
  901. error(Ebadstat);
  902. /* verify that name entry is acceptable */
  903. s += STATFIXLEN - 4*BIT16SZ; /* location of first string */
  904. /*
  905. * s now points at count for first string.
  906. * if it's too long, let the server decide; this is
  907. * only for his protection anyway. otherwise
  908. * we'd have to allocate and waserror.
  909. */
  910. m = GBIT16(s);
  911. s += BIT16SZ;
  912. if(m+1 > sizeof buf)
  913. return;
  914. memmove(buf, s, m);
  915. buf[m] = '\0';
  916. /* name could be '/' */
  917. if(strcmp(buf, "/") != 0)
  918. validname(buf, 0);
  919. }
  920. static char*
  921. pathlast(Path *p)
  922. {
  923. char *s;
  924. if(p == nil)
  925. return nil;
  926. if(p->len == 0)
  927. return nil;
  928. s = strrchr(p->s, '/');
  929. if(s)
  930. return s+1;
  931. return p->s;
  932. }
  933. void
  934. sysfstat(Ar0* ar0, ...)
  935. {
  936. Proc *up = externup();
  937. int fd;
  938. Chan *c;
  939. usize n;
  940. int r;
  941. uint8_t *p;
  942. va_list list;
  943. va_start(list, ar0);
  944. /*
  945. * int fstat(int fd, uchar* edir, int nedir);
  946. * should really be
  947. * usize fstat(int fd, uchar* edir, usize nedir);
  948. * but returning an unsigned is probably too
  949. * radical.
  950. */
  951. fd = va_arg(list, int);
  952. p = va_arg(list, uint8_t*);
  953. n = va_arg(list, usize);
  954. va_end(list);
  955. p = validaddr(p, n, 1);
  956. c = fdtochan(fd, -1, 0, 1);
  957. if(waserror()) {
  958. cclose(c);
  959. nexterror();
  960. }
  961. r = c->dev->stat(c, p, n);
  962. poperror();
  963. cclose(c);
  964. ar0->i = r;
  965. }
  966. void
  967. sysstat(Ar0* ar0, ...)
  968. {
  969. Proc *up = externup();
  970. char *aname;
  971. Chan *c;
  972. usize n;
  973. int r;
  974. uint8_t *p;
  975. va_list list;
  976. va_start(list, ar0);
  977. /*
  978. * int stat(char* name, uchar* edir, int nedir);
  979. * should really be
  980. * usize stat(char* name, uchar* edir, usize nedir);
  981. * but returning an unsigned is probably too
  982. * radical.
  983. */
  984. aname = va_arg(list, char*);
  985. aname = validaddr(aname, 1, 0);
  986. p = va_arg(list, uint8_t*);
  987. n = va_arg(list, usize);
  988. va_end(list);
  989. p = validaddr(p, n, 1);
  990. c = namec(aname, Aaccess, 0, 0);
  991. if(waserror()){
  992. cclose(c);
  993. nexterror();
  994. }
  995. r = c->dev->stat(c, p, n);
  996. aname = pathlast(c->path);
  997. if(aname)
  998. r = dirsetname(aname, strlen(aname), p, r, n);
  999. poperror();
  1000. cclose(c);
  1001. ar0->i = r;
  1002. }
  1003. void
  1004. syschdir(Ar0* ar0, ...)
  1005. {
  1006. Proc *up = externup();
  1007. Chan *c;
  1008. char *aname;
  1009. va_list list;
  1010. va_start(list, ar0);
  1011. /*
  1012. * int chdir(char* dirname);
  1013. */
  1014. aname = va_arg(list, char*);
  1015. aname = validaddr(aname, 1, 0);
  1016. va_end(list);
  1017. c = namec(aname, Atodir, 0, 0);
  1018. cclose(up->dot);
  1019. up->dot = c;
  1020. ar0->i = 0;
  1021. }
  1022. /* white list of devices we allow mounting on.
  1023. * At some point we can have build generate this if we ever
  1024. * really start using it.
  1025. */
  1026. static int dcok[] = {
  1027. 'M',
  1028. 'N',
  1029. '9'
  1030. };
  1031. /* to be used in chan.c to disallow attach to these devices
  1032. */
  1033. int
  1034. checkdc(int dc)
  1035. {
  1036. int i;
  1037. /* we check for non-zero in case somebody ever puts a ,
  1038. * after the last element and we end up with 0 as the last thing ...
  1039. */
  1040. for(i = 0; (i < nelem(dcok)) && dcok[i]; i++)
  1041. if (dcok[i] == dc)
  1042. return 1;
  1043. return 0;
  1044. }
  1045. /* if dc is non-zero, it means we're doing a mount and dc is the mount device to use. */
  1046. static int
  1047. bindmount(int dc, int fd, int afd, char* arg0, char* arg1, int flag, char* spec)
  1048. {
  1049. Proc *up = externup();
  1050. int i;
  1051. Dev *dev;
  1052. Chan *c0, *c1, *ac, *bc;
  1053. struct{
  1054. Chan *chan;
  1055. Chan *authchan;
  1056. char *spec;
  1057. int flags;
  1058. }bogus;
  1059. if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER))
  1060. error(Ebadarg);
  1061. bogus.flags = flag & MCACHE;
  1062. if(dc){
  1063. if (! checkdc(dc))
  1064. error(Ebadarg);
  1065. if(up->pgrp->noattach)
  1066. error(Enoattach);
  1067. ac = nil;
  1068. bc = fdtochan(fd, ORDWR, 0, 1);
  1069. if(waserror()) {
  1070. if(ac)
  1071. cclose(ac);
  1072. cclose(bc);
  1073. nexterror();
  1074. }
  1075. if(afd >= 0)
  1076. ac = fdtochan(afd, ORDWR, 0, 1);
  1077. bogus.chan = bc;
  1078. bogus.authchan = ac;
  1079. bogus.spec = validaddr(spec, 1, 0);
  1080. if(waserror())
  1081. error(Ebadspec);
  1082. spec = validnamedup(spec, 1);
  1083. poperror();
  1084. if(waserror()){
  1085. free(spec);
  1086. nexterror();
  1087. }
  1088. dev = devtabget(dc, 0); //XDYNX
  1089. if(waserror()){
  1090. //devtabdecr(dev);
  1091. nexterror();
  1092. }
  1093. c0 = dev->attach((char*)&bogus);
  1094. poperror();
  1095. //devtabdecr(dev);
  1096. poperror(); /* spec */
  1097. free(spec);
  1098. poperror(); /* ac bc */
  1099. if(ac)
  1100. cclose(ac);
  1101. cclose(bc);
  1102. }else{
  1103. bogus.spec = nil;
  1104. c0 = namec(validaddr(arg0, 1, 0), Abind, 0, 0);
  1105. }
  1106. if(waserror()){
  1107. cclose(c0);
  1108. nexterror();
  1109. }
  1110. c1 = namec(validaddr(arg1, 1, 0), Amount, 0, 0);
  1111. if(waserror()){
  1112. cclose(c1);
  1113. nexterror();
  1114. }
  1115. i = cmount(&c0, c1, flag, bogus.spec);
  1116. poperror();
  1117. cclose(c1);
  1118. poperror();
  1119. cclose(c0);
  1120. if(dc)
  1121. fdclose(fd, 0);
  1122. return i;
  1123. }
  1124. void
  1125. sysbind(Ar0* ar0, ...)
  1126. {
  1127. int flag;
  1128. char *name, *old;
  1129. va_list list;
  1130. va_start(list, ar0);
  1131. /*
  1132. * int bind(char* name, char* old, int flag);
  1133. * should be
  1134. * long bind(char* name, char* old, int flag);
  1135. */
  1136. name = va_arg(list, char*);
  1137. old = va_arg(list, char*);
  1138. flag = va_arg(list, int);
  1139. va_end(list);
  1140. ar0->i = bindmount(0, -1, -1, name, old, flag, nil);
  1141. }
  1142. void
  1143. sysmount(Ar0* ar0, ...)
  1144. {
  1145. int afd, fd, flag;
  1146. char *aname, *old;
  1147. int dc;
  1148. va_list list;
  1149. va_start(list, ar0);
  1150. /*
  1151. * int mount(int fd, int afd, char* old, int flag, char* aname);
  1152. * should be
  1153. * long mount(int fd, int afd, char* old, int flag, char* aname);
  1154. */
  1155. fd = va_arg(list, int);
  1156. afd = va_arg(list, int);
  1157. old = va_arg(list, char*);
  1158. flag = va_arg(list, int);
  1159. aname = va_arg(list, char*);
  1160. dc = va_arg(list, int);
  1161. va_end(list);
  1162. ar0->i = bindmount(dc, fd, afd, nil, old, flag, aname);
  1163. }
  1164. void
  1165. sys_mount(Ar0* ar0, ...)
  1166. {
  1167. int fd, flag;
  1168. char *aname, *old;
  1169. va_list list;
  1170. va_start(list, ar0);
  1171. /*
  1172. * int mount(int fd, char *old, int flag, char *aname);
  1173. * should be
  1174. * long mount(int fd, char *old, int flag, char *aname);
  1175. *
  1176. * Deprecated; backwards compatibility only.
  1177. */
  1178. fd = va_arg(list, int);
  1179. old = va_arg(list, char*);
  1180. flag = va_arg(list, int);
  1181. aname = va_arg(list, char*);
  1182. va_end(list);
  1183. ar0->i = bindmount(1, fd, -1, nil, old, flag, aname);
  1184. }
  1185. void
  1186. sysunmount(Ar0* ar0, ...)
  1187. {
  1188. Proc *up = externup();
  1189. char *name, *old;
  1190. Chan *cmount, *cmounted;
  1191. va_list list;
  1192. va_start(list, ar0);
  1193. /*
  1194. * int unmount(char* name, char* old);
  1195. */
  1196. name = va_arg(list, char*);
  1197. old = va_arg(list, char*);
  1198. cmount = namec(validaddr(old, 1, 0), Amount, 0, 0);
  1199. va_end(list);
  1200. cmounted = nil;
  1201. if(name != nil) {
  1202. if(waserror()) {
  1203. cclose(cmount);
  1204. nexterror();
  1205. }
  1206. /*
  1207. * This has to be namec(..., Aopen, ...) because
  1208. * if arg[0] is something like /srv/cs or /fd/0,
  1209. * opening it is the only way to get at the real
  1210. * Chan underneath.
  1211. */
  1212. cmounted = namec(validaddr(name, 1, 0), Aopen, OREAD, 0);
  1213. poperror();
  1214. }
  1215. if(waserror()) {
  1216. cclose(cmount);
  1217. if(cmounted != nil)
  1218. cclose(cmounted);
  1219. nexterror();
  1220. }
  1221. cunmount(cmount, cmounted);
  1222. cclose(cmount);
  1223. if(cmounted != nil)
  1224. cclose(cmounted);
  1225. poperror();
  1226. ar0->i = 0;
  1227. }
  1228. void
  1229. syscreate(Ar0* ar0, ...)
  1230. {
  1231. Proc *up = externup();
  1232. char *aname;
  1233. int fd, omode, perm;
  1234. Chan *c;
  1235. va_list list;
  1236. va_start(list, ar0);
  1237. /*
  1238. * int create(char* file, int omode, uint32_t perm);
  1239. * should be
  1240. * int create(char* file, int omode, int perm);
  1241. */
  1242. aname = va_arg(list, char*);
  1243. omode = va_arg(list, int);
  1244. perm = va_arg(list, int);
  1245. va_end(list);
  1246. openmode(omode & ~OEXCL); /* error check only; OEXCL okay here */
  1247. c = nil;
  1248. if(waserror()) {
  1249. if(c != nil)
  1250. cclose(c);
  1251. nexterror();
  1252. }
  1253. c = namec(validaddr(aname, 1, 0), Acreate, omode, perm);
  1254. fd = newfd(c);
  1255. if(fd < 0)
  1256. error(Enofd);
  1257. poperror();
  1258. ar0->i = fd;
  1259. }
  1260. void
  1261. sysremove(Ar0* ar0, ...)
  1262. {
  1263. Proc *up = externup();
  1264. Chan *c;
  1265. char *aname;
  1266. va_list list;
  1267. va_start(list, ar0);
  1268. /*
  1269. * int remove(char* file);
  1270. */
  1271. aname = va_arg(list, char*);
  1272. c = namec(validaddr(aname, 1, 0), Aremove, 0, 0);
  1273. va_end(list);
  1274. /*
  1275. * Removing mount points is disallowed to avoid surprises
  1276. * (which should be removed: the mount point or the mounted Chan?).
  1277. */
  1278. if(c->ismtpt){
  1279. cclose(c);
  1280. error(Eismtpt);
  1281. }
  1282. if(waserror()){
  1283. c->dev = nil; /* see below */
  1284. cclose(c);
  1285. nexterror();
  1286. }
  1287. c->dev->remove(c);
  1288. /*
  1289. * Remove clunks the fid, but we need to recover the Chan
  1290. * so fake it up. rootclose() is known to be a nop.
  1291. Not sure this dicking around is right for Dev ref counts.
  1292. */
  1293. c->dev = nil;
  1294. poperror();
  1295. cclose(c);
  1296. ar0->i = 0;
  1297. }
  1298. static int32_t
  1299. wstat(Chan* c, uint8_t* p, usize n)
  1300. {
  1301. Proc *up = externup();
  1302. int32_t l;
  1303. usize namelen;
  1304. if(waserror()){
  1305. cclose(c);
  1306. nexterror();
  1307. }
  1308. /*
  1309. * Renaming mount points is disallowed to avoid surprises
  1310. * (which should be renamed? the mount point or the mounted Chan?).
  1311. */
  1312. if(c->ismtpt){
  1313. dirname(p, &namelen);
  1314. if(namelen)
  1315. nameerror(chanpath(c), Eismtpt);
  1316. }
  1317. l = c->dev->wstat(c, p, n);
  1318. poperror();
  1319. cclose(c);
  1320. return l;
  1321. }
  1322. void
  1323. syswstat(Ar0* ar0, ...)
  1324. {
  1325. Chan *c;
  1326. char *aname;
  1327. uint8_t *p;
  1328. usize n;
  1329. va_list list;
  1330. va_start(list, ar0);
  1331. /*
  1332. * int wstat(char* name, uchar* edir, int nedir);
  1333. * should really be
  1334. * usize wstat(char* name, uchar* edir, usize nedir);
  1335. * but returning an unsigned is probably too
  1336. * radical.
  1337. */
  1338. aname = va_arg(list, char*);
  1339. p = va_arg(list, uint8_t*);
  1340. n = va_arg(list, usize);
  1341. p = validaddr(p, n, 0);
  1342. validstat(p, n);
  1343. c = namec(validaddr(aname, 1, 0), Aaccess, 0, 0);
  1344. va_end(list);
  1345. ar0->l = wstat(c, p, n);
  1346. }
  1347. void
  1348. sysfwstat(Ar0* ar0, ...)
  1349. {
  1350. Chan *c;
  1351. int fd;
  1352. uint8_t *p;
  1353. usize n;
  1354. va_list list;
  1355. va_start(list, ar0);
  1356. /*
  1357. * int fwstat(int fd, uchar* edir, int nedir);
  1358. * should really be
  1359. * usize wstat(int fd, uchar* edir, usize nedir);
  1360. * but returning an unsigned is probably too
  1361. * radical.
  1362. */
  1363. fd = va_arg(list, int);
  1364. p = va_arg(list, uint8_t*);
  1365. n = va_arg(list, usize);
  1366. p = validaddr(p, n, 0);
  1367. validstat(p, n);
  1368. c = fdtochan(fd, -1, 1, 1);
  1369. va_end(list);
  1370. ar0->l = wstat(c, p, n);
  1371. }
  1372. static void
  1373. packoldstat(uint8_t *buf, Dir *d)
  1374. {
  1375. uint8_t *p;
  1376. uint32_t q;
  1377. /* lay down old stat buffer - grotty code but it's temporary */
  1378. p = buf;
  1379. strncpy((char*)p, d->name, 28);
  1380. p += 28;
  1381. strncpy((char*)p, d->uid, 28);
  1382. p += 28;
  1383. strncpy((char*)p, d->gid, 28);
  1384. p += 28;
  1385. q = d->qid.path & ~DMDIR; /* make sure doesn't accidentally look like directory */
  1386. if(d->qid.type & QTDIR) /* this is the real test of a new directory */
  1387. q |= DMDIR;
  1388. PBIT32(p, q);
  1389. p += BIT32SZ;
  1390. PBIT32(p, d->qid.vers);
  1391. p += BIT32SZ;
  1392. PBIT32(p, d->mode);
  1393. p += BIT32SZ;
  1394. PBIT32(p, d->atime);
  1395. p += BIT32SZ;
  1396. PBIT32(p, d->mtime);
  1397. p += BIT32SZ;
  1398. PBIT64(p, d->length);
  1399. p += BIT64SZ;
  1400. PBIT16(p, d->type);
  1401. p += BIT16SZ;
  1402. PBIT16(p, d->dev);
  1403. }
  1404. void
  1405. sys_stat(Ar0* ar0, ...)
  1406. {
  1407. Proc *up = externup();
  1408. Chan *c;
  1409. int32_t l;
  1410. uint8_t buf[128], *p;
  1411. char *aname, *name, strs[128];
  1412. Dir d;
  1413. char old[] = "old stat system call - recompile";
  1414. va_list list;
  1415. va_start(list, ar0);
  1416. /*
  1417. * int stat(char* name, char* edir);
  1418. * should have been
  1419. * usize stat(char* name, uchar* edir));
  1420. *
  1421. * Deprecated; backwards compatibility only.
  1422. */
  1423. aname = va_arg(list, char*);
  1424. p = va_arg(list, uint8_t*);
  1425. va_end(list);
  1426. /*
  1427. * Old DIRLEN (116) plus a little should be plenty
  1428. * for the buffer sizes.
  1429. */
  1430. p = validaddr(p, 116, 1);
  1431. c = namec(validaddr(aname, 1, 0), Aaccess, 0, 0);
  1432. if(waserror()){
  1433. cclose(c);
  1434. nexterror();
  1435. }
  1436. l = c->dev->stat(c, buf, sizeof buf);
  1437. /*
  1438. * Buf contains a new stat buf; convert to old.
  1439. * Yuck.
  1440. * If buffer too small, time to face reality.
  1441. */
  1442. if(l <= BIT16SZ)
  1443. error(old);
  1444. name = pathlast(c->path);
  1445. if(name)
  1446. l = dirsetname(name, strlen(name), buf, l, sizeof buf);
  1447. l = convM2D(buf, l, &d, strs);
  1448. if(l == 0)
  1449. error(old);
  1450. packoldstat(p, &d);
  1451. poperror();
  1452. cclose(c);
  1453. ar0->i = 0;
  1454. }
  1455. void
  1456. sys_fstat(Ar0* ar0, ...)
  1457. {
  1458. Proc *up = externup();
  1459. Chan *c;
  1460. char *name;
  1461. int32_t l;
  1462. uint8_t buf[128], *p;
  1463. char strs[128];
  1464. Dir d;
  1465. int fd;
  1466. char old[] = "old fstat system call - recompile";
  1467. va_list list;
  1468. va_start(list, ar0);
  1469. /*
  1470. * int fstat(int fd, char* edir);
  1471. * should have been
  1472. * usize fstat(int fd, uchar* edir));
  1473. *
  1474. * Deprecated; backwards compatibility only.
  1475. */
  1476. fd = va_arg(list, int);
  1477. p = va_arg(list, uint8_t*);
  1478. va_end(list);
  1479. /*
  1480. * Old DIRLEN (116) plus a little should be plenty
  1481. * for the buffer sizes.
  1482. */
  1483. p = validaddr(p, 116, 1);
  1484. c = fdtochan(fd, -1, 0, 1);
  1485. if(waserror()){
  1486. cclose(c);
  1487. nexterror();
  1488. }
  1489. l = c->dev->stat(c, buf, sizeof buf);
  1490. /*
  1491. * Buf contains a new stat buf; convert to old.
  1492. * Yuck.
  1493. * If buffer too small, time to face reality.
  1494. */
  1495. if(l <= BIT16SZ)
  1496. error(old);
  1497. name = pathlast(c->path);
  1498. if(name)
  1499. l = dirsetname(name, strlen(name), buf, l, sizeof buf);
  1500. l = convM2D(buf, l, &d, strs);
  1501. if(l == 0)
  1502. error(old);
  1503. packoldstat(p, &d);
  1504. poperror();
  1505. cclose(c);
  1506. ar0->i = 0;
  1507. }
  1508. void
  1509. sys_wstat(Ar0* ar0, ...)
  1510. {
  1511. va_list list;
  1512. va_start(list, ar0);
  1513. va_end(list);
  1514. error("old wstat system call - recompile");
  1515. }
  1516. void
  1517. sys_fwstat(Ar0* ar0, ...)
  1518. {
  1519. va_list list;
  1520. va_start(list, ar0);
  1521. va_end(list);
  1522. error("old fwstat system call - recompile");
  1523. }