sysfile.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732
  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);
  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);
  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);
  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);
  126. if(fd<0 || f->nfd<=fd || (c = f->fd[fd])==0) {
  127. unlock(f);
  128. error(Ebadfd);
  129. }
  130. if(iref)
  131. incref(c);
  132. unlock(f);
  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);
  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);
  321. c = f->fd[fd];
  322. if(c == nil){
  323. /* can happen for users with shared fd tables */
  324. unlock(f);
  325. return;
  326. }
  327. if(flag){
  328. if(c == nil || !(c->flag&flag)){
  329. unlock(f);
  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);
  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);
  692. c->devoffset += nn;
  693. c->offset += nnn;
  694. unlock(c);
  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);
  750. c->offset -= n;
  751. unlock(c);
  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);
  761. off = c->offset;
  762. c->offset += n;
  763. unlock(c);
  764. }
  765. r = c->dev->write(c, p, n, off);
  766. if(!ispwrite && r < n){
  767. lock(c);
  768. c->offset -= n - r;
  769. unlock(c);
  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); /* lock for read/write update */
  830. offset += c->offset;
  831. c->offset = offset;
  832. unlock(c);
  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. };
  1029. static int checkdc(int dc)
  1030. {
  1031. int i;
  1032. /* we check for non-zero in case somebody ever puts a ,
  1033. * after the last element and we end up with 0 as the last thing ...
  1034. */
  1035. for(i = 0; (i < nelem(dcok)) && dcok[i]; i++)
  1036. if (dcok[i] == dc)
  1037. return 1;
  1038. return 0;
  1039. }
  1040. /* if dc is non-zero, it means we're doing a mount and dc is the mount device to use. */
  1041. static int
  1042. bindmount(int dc, int fd, int afd, char* arg0, char* arg1, int flag, char* spec)
  1043. {
  1044. Proc *up = externup();
  1045. int i;
  1046. Dev *dev;
  1047. Chan *c0, *c1, *ac, *bc;
  1048. struct{
  1049. Chan *chan;
  1050. Chan *authchan;
  1051. char *spec;
  1052. int flags;
  1053. }bogus;
  1054. if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER))
  1055. error(Ebadarg);
  1056. bogus.flags = flag & MCACHE;
  1057. if(dc){
  1058. if (! checkdc(dc))
  1059. error(Ebadarg);
  1060. if(up->pgrp->noattach)
  1061. error(Enoattach);
  1062. ac = nil;
  1063. bc = fdtochan(fd, ORDWR, 0, 1);
  1064. if(waserror()) {
  1065. if(ac)
  1066. cclose(ac);
  1067. cclose(bc);
  1068. nexterror();
  1069. }
  1070. if(afd >= 0)
  1071. ac = fdtochan(afd, ORDWR, 0, 1);
  1072. bogus.chan = bc;
  1073. bogus.authchan = ac;
  1074. bogus.spec = validaddr(spec, 1, 0);
  1075. if(waserror())
  1076. error(Ebadspec);
  1077. spec = validnamedup(spec, 1);
  1078. poperror();
  1079. if(waserror()){
  1080. free(spec);
  1081. nexterror();
  1082. }
  1083. dev = devtabget(dc, 0); //XDYNX
  1084. if(waserror()){
  1085. //devtabdecr(dev);
  1086. nexterror();
  1087. }
  1088. c0 = dev->attach((char*)&bogus);
  1089. poperror();
  1090. //devtabdecr(dev);
  1091. poperror(); /* spec */
  1092. free(spec);
  1093. poperror(); /* ac bc */
  1094. if(ac)
  1095. cclose(ac);
  1096. cclose(bc);
  1097. }else{
  1098. bogus.spec = nil;
  1099. c0 = namec(validaddr(arg0, 1, 0), Abind, 0, 0);
  1100. }
  1101. if(waserror()){
  1102. cclose(c0);
  1103. nexterror();
  1104. }
  1105. c1 = namec(validaddr(arg1, 1, 0), Amount, 0, 0);
  1106. if(waserror()){
  1107. cclose(c1);
  1108. nexterror();
  1109. }
  1110. i = cmount(&c0, c1, flag, bogus.spec);
  1111. poperror();
  1112. cclose(c1);
  1113. poperror();
  1114. cclose(c0);
  1115. if(dc)
  1116. fdclose(fd, 0);
  1117. return i;
  1118. }
  1119. void
  1120. sysbind(Ar0* ar0, ...)
  1121. {
  1122. int flag;
  1123. char *name, *old;
  1124. va_list list;
  1125. va_start(list, ar0);
  1126. /*
  1127. * int bind(char* name, char* old, int flag);
  1128. * should be
  1129. * long bind(char* name, char* old, int flag);
  1130. */
  1131. name = va_arg(list, char*);
  1132. old = va_arg(list, char*);
  1133. flag = va_arg(list, int);
  1134. va_end(list);
  1135. ar0->i = bindmount(0, -1, -1, name, old, flag, nil);
  1136. }
  1137. void
  1138. sysmount(Ar0* ar0, ...)
  1139. {
  1140. int afd, fd, flag;
  1141. char *aname, *old;
  1142. int dc;
  1143. va_list list;
  1144. va_start(list, ar0);
  1145. /*
  1146. * int mount(int fd, int afd, char* old, int flag, char* aname);
  1147. * should be
  1148. * long mount(int fd, int afd, char* old, int flag, char* aname);
  1149. */
  1150. fd = va_arg(list, int);
  1151. afd = va_arg(list, int);
  1152. old = va_arg(list, char*);
  1153. flag = va_arg(list, int);
  1154. aname = va_arg(list, char*);
  1155. dc = va_arg(list, int);
  1156. va_end(list);
  1157. ar0->i = bindmount(dc, fd, afd, nil, old, flag, aname);
  1158. }
  1159. void
  1160. sys_mount(Ar0* ar0, ...)
  1161. {
  1162. int fd, flag;
  1163. char *aname, *old;
  1164. va_list list;
  1165. va_start(list, ar0);
  1166. /*
  1167. * int mount(int fd, char *old, int flag, char *aname);
  1168. * should be
  1169. * long mount(int fd, char *old, int flag, char *aname);
  1170. *
  1171. * Deprecated; backwards compatibility only.
  1172. */
  1173. fd = va_arg(list, int);
  1174. old = va_arg(list, char*);
  1175. flag = va_arg(list, int);
  1176. aname = va_arg(list, char*);
  1177. va_end(list);
  1178. ar0->i = bindmount(1, fd, -1, nil, old, flag, aname);
  1179. }
  1180. void
  1181. sysunmount(Ar0* ar0, ...)
  1182. {
  1183. Proc *up = externup();
  1184. char *name, *old;
  1185. Chan *cmount, *cmounted;
  1186. va_list list;
  1187. va_start(list, ar0);
  1188. /*
  1189. * int unmount(char* name, char* old);
  1190. */
  1191. name = va_arg(list, char*);
  1192. old = va_arg(list, char*);
  1193. cmount = namec(validaddr(old, 1, 0), Amount, 0, 0);
  1194. va_end(list);
  1195. cmounted = nil;
  1196. if(name != nil) {
  1197. if(waserror()) {
  1198. cclose(cmount);
  1199. nexterror();
  1200. }
  1201. /*
  1202. * This has to be namec(..., Aopen, ...) because
  1203. * if arg[0] is something like /srv/cs or /fd/0,
  1204. * opening it is the only way to get at the real
  1205. * Chan underneath.
  1206. */
  1207. cmounted = namec(validaddr(name, 1, 0), Aopen, OREAD, 0);
  1208. poperror();
  1209. }
  1210. if(waserror()) {
  1211. cclose(cmount);
  1212. if(cmounted != nil)
  1213. cclose(cmounted);
  1214. nexterror();
  1215. }
  1216. cunmount(cmount, cmounted);
  1217. cclose(cmount);
  1218. if(cmounted != nil)
  1219. cclose(cmounted);
  1220. poperror();
  1221. ar0->i = 0;
  1222. }
  1223. void
  1224. syscreate(Ar0* ar0, ...)
  1225. {
  1226. Proc *up = externup();
  1227. char *aname;
  1228. int fd, omode, perm;
  1229. Chan *c;
  1230. va_list list;
  1231. va_start(list, ar0);
  1232. /*
  1233. * int create(char* file, int omode, uint32_t perm);
  1234. * should be
  1235. * int create(char* file, int omode, int perm);
  1236. */
  1237. aname = va_arg(list, char*);
  1238. omode = va_arg(list, int);
  1239. perm = va_arg(list, int);
  1240. va_end(list);
  1241. openmode(omode & ~OEXCL); /* error check only; OEXCL okay here */
  1242. c = nil;
  1243. if(waserror()) {
  1244. if(c != nil)
  1245. cclose(c);
  1246. nexterror();
  1247. }
  1248. c = namec(validaddr(aname, 1, 0), Acreate, omode, perm);
  1249. fd = newfd(c);
  1250. if(fd < 0)
  1251. error(Enofd);
  1252. poperror();
  1253. ar0->i = fd;
  1254. }
  1255. void
  1256. sysremove(Ar0* ar0, ...)
  1257. {
  1258. Proc *up = externup();
  1259. Chan *c;
  1260. char *aname;
  1261. va_list list;
  1262. va_start(list, ar0);
  1263. /*
  1264. * int remove(char* file);
  1265. */
  1266. aname = va_arg(list, char*);
  1267. c = namec(validaddr(aname, 1, 0), Aremove, 0, 0);
  1268. va_end(list);
  1269. /*
  1270. * Removing mount points is disallowed to avoid surprises
  1271. * (which should be removed: the mount point or the mounted Chan?).
  1272. */
  1273. if(c->ismtpt){
  1274. cclose(c);
  1275. error(Eismtpt);
  1276. }
  1277. if(waserror()){
  1278. c->dev = nil; /* see below */
  1279. cclose(c);
  1280. nexterror();
  1281. }
  1282. c->dev->remove(c);
  1283. /*
  1284. * Remove clunks the fid, but we need to recover the Chan
  1285. * so fake it up. rootclose() is known to be a nop.
  1286. Not sure this dicking around is right for Dev ref counts.
  1287. */
  1288. c->dev = nil;
  1289. poperror();
  1290. cclose(c);
  1291. ar0->i = 0;
  1292. }
  1293. static int32_t
  1294. wstat(Chan* c, uint8_t* p, usize n)
  1295. {
  1296. Proc *up = externup();
  1297. int32_t l;
  1298. usize namelen;
  1299. if(waserror()){
  1300. cclose(c);
  1301. nexterror();
  1302. }
  1303. /*
  1304. * Renaming mount points is disallowed to avoid surprises
  1305. * (which should be renamed? the mount point or the mounted Chan?).
  1306. */
  1307. if(c->ismtpt){
  1308. dirname(p, &namelen);
  1309. if(namelen)
  1310. nameerror(chanpath(c), Eismtpt);
  1311. }
  1312. l = c->dev->wstat(c, p, n);
  1313. poperror();
  1314. cclose(c);
  1315. return l;
  1316. }
  1317. void
  1318. syswstat(Ar0* ar0, ...)
  1319. {
  1320. Chan *c;
  1321. char *aname;
  1322. uint8_t *p;
  1323. usize n;
  1324. va_list list;
  1325. va_start(list, ar0);
  1326. /*
  1327. * int wstat(char* name, uchar* edir, int nedir);
  1328. * should really be
  1329. * usize wstat(char* name, uchar* edir, usize nedir);
  1330. * but returning an unsigned is probably too
  1331. * radical.
  1332. */
  1333. aname = va_arg(list, char*);
  1334. p = va_arg(list, uint8_t*);
  1335. n = va_arg(list, usize);
  1336. p = validaddr(p, n, 0);
  1337. validstat(p, n);
  1338. c = namec(validaddr(aname, 1, 0), Aaccess, 0, 0);
  1339. va_end(list);
  1340. ar0->l = wstat(c, p, n);
  1341. }
  1342. void
  1343. sysfwstat(Ar0* ar0, ...)
  1344. {
  1345. Chan *c;
  1346. int fd;
  1347. uint8_t *p;
  1348. usize n;
  1349. va_list list;
  1350. va_start(list, ar0);
  1351. /*
  1352. * int fwstat(int fd, uchar* edir, int nedir);
  1353. * should really be
  1354. * usize wstat(int fd, uchar* edir, usize nedir);
  1355. * but returning an unsigned is probably too
  1356. * radical.
  1357. */
  1358. fd = va_arg(list, int);
  1359. p = va_arg(list, uint8_t*);
  1360. n = va_arg(list, usize);
  1361. p = validaddr(p, n, 0);
  1362. validstat(p, n);
  1363. c = fdtochan(fd, -1, 1, 1);
  1364. va_end(list);
  1365. ar0->l = wstat(c, p, n);
  1366. }
  1367. static void
  1368. packoldstat(uint8_t *buf, Dir *d)
  1369. {
  1370. uint8_t *p;
  1371. uint32_t q;
  1372. /* lay down old stat buffer - grotty code but it's temporary */
  1373. p = buf;
  1374. strncpy((char*)p, d->name, 28);
  1375. p += 28;
  1376. strncpy((char*)p, d->uid, 28);
  1377. p += 28;
  1378. strncpy((char*)p, d->gid, 28);
  1379. p += 28;
  1380. q = d->qid.path & ~DMDIR; /* make sure doesn't accidentally look like directory */
  1381. if(d->qid.type & QTDIR) /* this is the real test of a new directory */
  1382. q |= DMDIR;
  1383. PBIT32(p, q);
  1384. p += BIT32SZ;
  1385. PBIT32(p, d->qid.vers);
  1386. p += BIT32SZ;
  1387. PBIT32(p, d->mode);
  1388. p += BIT32SZ;
  1389. PBIT32(p, d->atime);
  1390. p += BIT32SZ;
  1391. PBIT32(p, d->mtime);
  1392. p += BIT32SZ;
  1393. PBIT64(p, d->length);
  1394. p += BIT64SZ;
  1395. PBIT16(p, d->type);
  1396. p += BIT16SZ;
  1397. PBIT16(p, d->dev);
  1398. }
  1399. void
  1400. sys_stat(Ar0* ar0, ...)
  1401. {
  1402. Proc *up = externup();
  1403. Chan *c;
  1404. int32_t l;
  1405. uint8_t buf[128], *p;
  1406. char *aname, *name, strs[128];
  1407. Dir d;
  1408. char old[] = "old stat system call - recompile";
  1409. va_list list;
  1410. va_start(list, ar0);
  1411. /*
  1412. * int stat(char* name, char* edir);
  1413. * should have been
  1414. * usize stat(char* name, uchar* edir));
  1415. *
  1416. * Deprecated; backwards compatibility only.
  1417. */
  1418. aname = va_arg(list, char*);
  1419. p = va_arg(list, uint8_t*);
  1420. va_end(list);
  1421. /*
  1422. * Old DIRLEN (116) plus a little should be plenty
  1423. * for the buffer sizes.
  1424. */
  1425. p = validaddr(p, 116, 1);
  1426. c = namec(validaddr(aname, 1, 0), Aaccess, 0, 0);
  1427. if(waserror()){
  1428. cclose(c);
  1429. nexterror();
  1430. }
  1431. l = c->dev->stat(c, buf, sizeof buf);
  1432. /*
  1433. * Buf contains a new stat buf; convert to old.
  1434. * Yuck.
  1435. * If buffer too small, time to face reality.
  1436. */
  1437. if(l <= BIT16SZ)
  1438. error(old);
  1439. name = pathlast(c->path);
  1440. if(name)
  1441. l = dirsetname(name, strlen(name), buf, l, sizeof buf);
  1442. l = convM2D(buf, l, &d, strs);
  1443. if(l == 0)
  1444. error(old);
  1445. packoldstat(p, &d);
  1446. poperror();
  1447. cclose(c);
  1448. ar0->i = 0;
  1449. }
  1450. void
  1451. sys_fstat(Ar0* ar0, ...)
  1452. {
  1453. Proc *up = externup();
  1454. Chan *c;
  1455. char *name;
  1456. int32_t l;
  1457. uint8_t buf[128], *p;
  1458. char strs[128];
  1459. Dir d;
  1460. int fd;
  1461. char old[] = "old fstat system call - recompile";
  1462. va_list list;
  1463. va_start(list, ar0);
  1464. /*
  1465. * int fstat(int fd, char* edir);
  1466. * should have been
  1467. * usize fstat(int fd, uchar* edir));
  1468. *
  1469. * Deprecated; backwards compatibility only.
  1470. */
  1471. fd = va_arg(list, int);
  1472. p = va_arg(list, uint8_t*);
  1473. va_end(list);
  1474. /*
  1475. * Old DIRLEN (116) plus a little should be plenty
  1476. * for the buffer sizes.
  1477. */
  1478. p = validaddr(p, 116, 1);
  1479. c = fdtochan(fd, -1, 0, 1);
  1480. if(waserror()){
  1481. cclose(c);
  1482. nexterror();
  1483. }
  1484. l = c->dev->stat(c, buf, sizeof buf);
  1485. /*
  1486. * Buf contains a new stat buf; convert to old.
  1487. * Yuck.
  1488. * If buffer too small, time to face reality.
  1489. */
  1490. if(l <= BIT16SZ)
  1491. error(old);
  1492. name = pathlast(c->path);
  1493. if(name)
  1494. l = dirsetname(name, strlen(name), buf, l, sizeof buf);
  1495. l = convM2D(buf, l, &d, strs);
  1496. if(l == 0)
  1497. error(old);
  1498. packoldstat(p, &d);
  1499. poperror();
  1500. cclose(c);
  1501. ar0->i = 0;
  1502. }
  1503. void
  1504. sys_wstat(Ar0* ar0, ...)
  1505. {
  1506. va_list list;
  1507. va_start(list, ar0);
  1508. va_end(list);
  1509. error("old wstat system call - recompile");
  1510. }
  1511. void
  1512. sys_fwstat(Ar0* ar0, ...)
  1513. {
  1514. va_list list;
  1515. va_start(list, ar0);
  1516. va_end(list);
  1517. error("old fwstat system call - recompile");
  1518. }