sysfile.c 29 KB

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