sysfile.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. /*
  8. * The sys*() routines needn't poperror() as they return directly to syscall().
  9. */
  10. int
  11. growfd(Fgrp *f, int fd) /* fd is always >= 0 */
  12. {
  13. Chan **newfd, **oldfd;
  14. if(fd < f->nfd)
  15. return 0;
  16. if(fd >= f->nfd+DELTAFD)
  17. return -1; /* out of range */
  18. if(fd % 100 == 0)
  19. pprint("warning: process exceeds %d file descriptors\n", fd);
  20. /*
  21. * Unbounded allocation is unwise; besides, there are only 16 bits
  22. * of fid in 9P
  23. */
  24. if(f->nfd >= 5000){
  25. Exhausted:
  26. print("no free file descriptors\n");
  27. return -1;
  28. }
  29. newfd = malloc((f->nfd+DELTAFD)*sizeof(Chan*));
  30. if(newfd == 0)
  31. goto Exhausted;
  32. oldfd = f->fd;
  33. memmove(newfd, oldfd, f->nfd*sizeof(Chan*));
  34. f->fd = newfd;
  35. free(oldfd);
  36. f->nfd += DELTAFD;
  37. if(fd > f->maxfd)
  38. f->maxfd = fd;
  39. return 1;
  40. }
  41. /*
  42. * this assumes that the fgrp is locked
  43. */
  44. int
  45. findfreefd(Fgrp *f, int start)
  46. {
  47. int fd;
  48. for(fd=start; fd<f->nfd; fd++)
  49. if(f->fd[fd] == 0)
  50. break;
  51. if(fd >= f->nfd && growfd(f, fd) < 0)
  52. return -1;
  53. return fd;
  54. }
  55. int
  56. newfd(Chan *c)
  57. {
  58. int fd;
  59. Fgrp *f;
  60. f = up->fgrp;
  61. lock(f);
  62. fd = findfreefd(f, 0);
  63. if(fd < 0){
  64. unlock(f);
  65. return -1;
  66. }
  67. if(fd > f->maxfd)
  68. f->maxfd = fd;
  69. f->fd[fd] = c;
  70. unlock(f);
  71. return fd;
  72. }
  73. int
  74. newfd2(int fd[2], Chan *c[2])
  75. {
  76. Fgrp *f;
  77. f = up->fgrp;
  78. lock(f);
  79. fd[0] = findfreefd(f, 0);
  80. if(fd[0] < 0){
  81. unlock(f);
  82. return -1;
  83. }
  84. fd[1] = findfreefd(f, fd[0]+1);
  85. if(fd[1] < 0){
  86. unlock(f);
  87. return -1;
  88. }
  89. if(fd[1] > f->maxfd)
  90. f->maxfd = fd[1];
  91. f->fd[fd[0]] = c[0];
  92. f->fd[fd[1]] = c[1];
  93. unlock(f);
  94. return 0;
  95. }
  96. Chan*
  97. fdtochan(int fd, int mode, int chkmnt, int iref)
  98. {
  99. Chan *c;
  100. Fgrp *f;
  101. c = 0;
  102. f = up->fgrp;
  103. lock(f);
  104. if(fd<0 || f->nfd<=fd || (c = f->fd[fd])==0) {
  105. unlock(f);
  106. error(Ebadfd);
  107. }
  108. if(iref)
  109. incref(c);
  110. unlock(f);
  111. if(chkmnt && (c->flag&CMSG)) {
  112. if(iref)
  113. cclose(c);
  114. error(Ebadusefd);
  115. }
  116. if(mode<0 || c->mode==ORDWR)
  117. return c;
  118. if((mode&OTRUNC) && c->mode==OREAD) {
  119. if(iref)
  120. cclose(c);
  121. error(Ebadusefd);
  122. }
  123. if((mode&~OTRUNC) != c->mode) {
  124. if(iref)
  125. cclose(c);
  126. error(Ebadusefd);
  127. }
  128. return c;
  129. }
  130. int
  131. openmode(ulong o)
  132. {
  133. o &= ~(OTRUNC|OCEXEC|ORCLOSE);
  134. if(o > OEXEC)
  135. error(Ebadarg);
  136. if(o == OEXEC)
  137. return OREAD;
  138. return o;
  139. }
  140. long
  141. sysfd2path(ulong *arg)
  142. {
  143. Chan *c;
  144. validaddr(arg[1], arg[2], 1);
  145. c = fdtochan(arg[0], -1, 0, 1);
  146. if(c->name == nil)
  147. snprint((char*)arg[1], arg[2], "<null>");
  148. else
  149. snprint((char*)arg[1], arg[2], "%s", c->name->s);
  150. cclose(c);
  151. return 0;
  152. }
  153. long
  154. syspipe(ulong *arg)
  155. {
  156. int fd[2];
  157. Chan *c[2];
  158. Dev *d;
  159. static char *datastr[] = {"data", "data1"};
  160. validaddr(arg[0], 2*BY2WD, 1);
  161. evenaddr(arg[0]);
  162. d = devtab[devno('|', 0)];
  163. c[0] = namec("#|", Atodir, 0, 0);
  164. c[1] = 0;
  165. fd[0] = -1;
  166. fd[1] = -1;
  167. if(waserror()){
  168. cclose(c[0]);
  169. if(c[1])
  170. cclose(c[1]);
  171. nexterror();
  172. }
  173. c[1] = cclone(c[0]);
  174. if(walk(&c[0], datastr+0, 1, 1, nil) < 0)
  175. error(Egreg);
  176. if(walk(&c[1], datastr+1, 1, 1, nil) < 0)
  177. error(Egreg);
  178. c[0] = d->open(c[0], ORDWR);
  179. c[1] = d->open(c[1], ORDWR);
  180. if(newfd2(fd, c) < 0)
  181. error(Enofd);
  182. poperror();
  183. ((long*)arg[0])[0] = fd[0];
  184. ((long*)arg[0])[1] = fd[1];
  185. return 0;
  186. }
  187. long
  188. sysdup(ulong *arg)
  189. {
  190. int fd;
  191. Chan *c, *oc;
  192. Fgrp *f = up->fgrp;
  193. /*
  194. * Close after dup'ing, so date > #d/1 works
  195. */
  196. c = fdtochan(arg[0], -1, 0, 1);
  197. fd = arg[1];
  198. if(fd != -1){
  199. lock(f);
  200. if(fd<0 || growfd(f, fd)<0) {
  201. unlock(f);
  202. cclose(c);
  203. error(Ebadfd);
  204. }
  205. if(fd > f->maxfd)
  206. f->maxfd = fd;
  207. oc = f->fd[fd];
  208. f->fd[fd] = c;
  209. unlock(f);
  210. if(oc)
  211. cclose(oc);
  212. }else{
  213. if(waserror()) {
  214. cclose(c);
  215. nexterror();
  216. }
  217. fd = newfd(c);
  218. if(fd < 0)
  219. error(Enofd);
  220. poperror();
  221. }
  222. return fd;
  223. }
  224. long
  225. sysopen(ulong *arg)
  226. {
  227. int fd;
  228. Chan *c = 0;
  229. openmode(arg[1]); /* error check only */
  230. if(waserror()){
  231. if(c)
  232. cclose(c);
  233. nexterror();
  234. }
  235. validaddr(arg[0], 1, 0);
  236. c = namec((char*)arg[0], Aopen, arg[1], 0);
  237. fd = newfd(c);
  238. if(fd < 0)
  239. error(Enofd);
  240. poperror();
  241. return fd;
  242. }
  243. void
  244. fdclose(int fd, int flag)
  245. {
  246. int i;
  247. Chan *c;
  248. Fgrp *f = up->fgrp;
  249. lock(f);
  250. c = f->fd[fd];
  251. if(c == 0){
  252. /* can happen for users with shared fd tables */
  253. unlock(f);
  254. return;
  255. }
  256. if(flag){
  257. if(c==0 || !(c->flag&flag)){
  258. unlock(f);
  259. return;
  260. }
  261. }
  262. f->fd[fd] = 0;
  263. if(fd == f->maxfd)
  264. for(i=fd; --i>=0 && f->fd[i]==0; )
  265. f->maxfd = i;
  266. unlock(f);
  267. cclose(c);
  268. }
  269. long
  270. sysclose(ulong *arg)
  271. {
  272. fdtochan(arg[0], -1, 0, 0);
  273. fdclose(arg[0], 0);
  274. return 0;
  275. }
  276. long
  277. unionread(Chan *c, void *va, long n)
  278. {
  279. int i;
  280. long nr;
  281. Mhead *m;
  282. Mount *mount;
  283. qlock(&c->umqlock);
  284. m = c->umh;
  285. rlock(&m->lock);
  286. mount = m->mount;
  287. /* bring mount in sync with c->uri and c->umc */
  288. for(i = 0; mount != nil && i < c->uri; i++)
  289. mount = mount->next;
  290. nr = 0;
  291. while(mount != nil) {
  292. /* Error causes component of union to be skipped */
  293. if(mount->to && !waserror()) {
  294. if(c->umc == nil){
  295. c->umc = cclone(mount->to);
  296. c->umc = devtab[c->umc->type]->open(c->umc, OREAD);
  297. }
  298. nr = devtab[c->umc->type]->read(c->umc, va, n, c->umc->offset);
  299. c->umc->offset += nr;
  300. poperror();
  301. }
  302. if(nr > 0)
  303. break;
  304. /* Advance to next element */
  305. c->uri++;
  306. if(c->umc) {
  307. cclose(c->umc);
  308. c->umc = nil;
  309. }
  310. mount = mount->next;
  311. }
  312. runlock(&m->lock);
  313. qunlock(&c->umqlock);
  314. return nr;
  315. }
  316. static long
  317. read(ulong *arg, vlong *offp)
  318. {
  319. int dir;
  320. long n;
  321. Chan *c;
  322. vlong off;
  323. n = arg[2];
  324. validaddr(arg[1], n, 1);
  325. c = fdtochan(arg[0], OREAD, 1, 1);
  326. if(waserror()) {
  327. cclose(c);
  328. nexterror();
  329. }
  330. dir = c->qid.type&QTDIR;
  331. /*
  332. * The offset is passed through on directories, normally. sysseek complains but
  333. * pread is used by servers and e.g. exportfs that shouldn't need to worry about this issue.
  334. */
  335. if(offp == nil) /* use and maintain channel's offset */
  336. off = c->offset;
  337. else
  338. off = *offp;
  339. if(off < 0)
  340. error(Enegoff);
  341. if(dir && c->umh)
  342. n = unionread(c, (void*)arg[1], n);
  343. else
  344. n = devtab[c->type]->read(c, (void*)arg[1], n, off);
  345. if(offp == nil){
  346. lock(c);
  347. c->offset += n;
  348. unlock(c);
  349. }
  350. poperror();
  351. cclose(c);
  352. return n;
  353. }
  354. long
  355. sys_read(ulong *arg)
  356. {
  357. return read(arg, nil);
  358. }
  359. long
  360. syspread(ulong *arg)
  361. {
  362. vlong v;
  363. va_list list;
  364. /* use varargs to guarantee alignment of vlong */
  365. va_start(list, arg[2]);
  366. v = va_arg(list, vlong);
  367. va_end(list);
  368. if(v == ~0ULL)
  369. return read(arg, nil);
  370. return read(arg, &v);
  371. }
  372. static long
  373. write(ulong *arg, vlong *offp)
  374. {
  375. Chan *c;
  376. long m, n;
  377. vlong off;
  378. validaddr(arg[1], arg[2], 0);
  379. n = 0;
  380. c = fdtochan(arg[0], OWRITE, 1, 1);
  381. if(waserror()) {
  382. if(offp == nil){
  383. lock(c);
  384. c->offset -= n;
  385. unlock(c);
  386. }
  387. cclose(c);
  388. nexterror();
  389. }
  390. if(c->qid.type & QTDIR)
  391. error(Eisdir);
  392. n = arg[2];
  393. if(offp == nil){ /* use and maintain channel's offset */
  394. lock(c);
  395. off = c->offset;
  396. c->offset += n;
  397. unlock(c);
  398. }else
  399. off = *offp;
  400. if(off < 0)
  401. error(Enegoff);
  402. m = devtab[c->type]->write(c, (void*)arg[1], n, off);
  403. if(offp == nil && m < n){
  404. lock(c);
  405. c->offset -= n - m;
  406. unlock(c);
  407. }
  408. poperror();
  409. cclose(c);
  410. return m;
  411. }
  412. long
  413. sys_write(ulong *arg)
  414. {
  415. return write(arg, nil);
  416. }
  417. long
  418. syspwrite(ulong *arg)
  419. {
  420. vlong v;
  421. va_list list;
  422. /* use varargs to guarantee alignment of vlong */
  423. va_start(list, arg[2]);
  424. v = va_arg(list, vlong);
  425. va_end(list);
  426. if(v == ~0ULL)
  427. return write(arg, nil);
  428. return write(arg, &v);
  429. }
  430. static void
  431. sseek(ulong *arg)
  432. {
  433. Chan *c;
  434. uchar buf[sizeof(Dir)+100];
  435. Dir dir;
  436. int n;
  437. vlong off;
  438. union {
  439. vlong v;
  440. ulong u[2];
  441. } o;
  442. c = fdtochan(arg[1], -1, 1, 1);
  443. if(waserror()){
  444. cclose(c);
  445. nexterror();
  446. }
  447. if(devtab[c->type]->dc == '|')
  448. error(Eisstream);
  449. off = 0;
  450. o.u[0] = arg[2];
  451. o.u[1] = arg[3];
  452. switch(arg[4]){
  453. case 0:
  454. off = o.v;
  455. if((c->qid.type & QTDIR) && off != 0)
  456. error(Eisdir);
  457. if(off < 0)
  458. error(Enegoff);
  459. c->offset = off;
  460. break;
  461. case 1:
  462. if(c->qid.type & QTDIR)
  463. error(Eisdir);
  464. lock(c); /* lock for read/write update */
  465. off = o.v + c->offset;
  466. if(off < 0)
  467. error(Enegoff);
  468. c->offset = off;
  469. unlock(c);
  470. break;
  471. case 2:
  472. if(c->qid.type & QTDIR)
  473. error(Eisdir);
  474. n = devtab[c->type]->stat(c, buf, sizeof buf);
  475. if(convM2D(buf, n, &dir, nil) == 0)
  476. error("internal error: stat error in seek");
  477. off = dir.length + o.v;
  478. if(off < 0)
  479. error(Enegoff);
  480. c->offset = off;
  481. break;
  482. default:
  483. error(Ebadarg);
  484. }
  485. *(vlong*)arg[0] = off;
  486. c->uri = 0;
  487. c->dri = 0;
  488. cclose(c);
  489. poperror();
  490. }
  491. long
  492. sysseek(ulong *arg)
  493. {
  494. validaddr(arg[0], BY2V, 1);
  495. sseek(arg);
  496. return 0;
  497. }
  498. long
  499. sysoseek(ulong *arg)
  500. {
  501. union {
  502. vlong v;
  503. ulong u[2];
  504. } o;
  505. ulong a[5];
  506. o.v = (long)arg[1];
  507. a[0] = (ulong)&o.v;
  508. a[1] = arg[0];
  509. a[2] = o.u[0];
  510. a[3] = o.u[1];
  511. a[4] = arg[2];
  512. sseek(a);
  513. return o.v;
  514. }
  515. void
  516. validstat(uchar *s, int n)
  517. {
  518. int m;
  519. char buf[64];
  520. if(statcheck(s, n) < 0)
  521. error(Ebadstat);
  522. /* verify that name entry is acceptable */
  523. s += STATFIXLEN - 4*BIT16SZ; /* location of first string */
  524. /*
  525. * s now points at count for first string.
  526. * if it's too long, let the server decide; this is
  527. * only for his protection anyway. otherwise
  528. * we'd have to allocate and waserror.
  529. */
  530. m = GBIT16(s);
  531. s += BIT16SZ;
  532. if(m+1 > sizeof buf)
  533. return;
  534. memmove(buf, s, m);
  535. buf[m] = '\0';
  536. /* name could be '/' */
  537. if(strcmp(buf, "/") != 0)
  538. validname(buf, 0);
  539. }
  540. long
  541. sysfstat(ulong *arg)
  542. {
  543. Chan *c;
  544. uint l;
  545. l = arg[2];
  546. validaddr(arg[1], l, 1);
  547. c = fdtochan(arg[0], -1, 0, 1);
  548. if(waserror()) {
  549. cclose(c);
  550. nexterror();
  551. }
  552. l = devtab[c->type]->stat(c, (uchar*)arg[1], l);
  553. poperror();
  554. cclose(c);
  555. return l;
  556. }
  557. long
  558. sysstat(ulong *arg)
  559. {
  560. Chan *c;
  561. uint l;
  562. l = arg[2];
  563. validaddr(arg[1], l, 1);
  564. validaddr(arg[0], 1, 0);
  565. c = namec((char*)arg[0], Aaccess, 0, 0);
  566. if(waserror()){
  567. cclose(c);
  568. nexterror();
  569. }
  570. l = devtab[c->type]->stat(c, (uchar*)arg[1], l);
  571. poperror();
  572. cclose(c);
  573. return l;
  574. }
  575. long
  576. syschdir(ulong *arg)
  577. {
  578. Chan *c;
  579. validaddr(arg[0], 1, 0);
  580. c = namec((char*)arg[0], Atodir, 0, 0);
  581. cclose(up->dot);
  582. up->dot = c;
  583. return 0;
  584. }
  585. long
  586. bindmount(int ismount, int fd, int afd, char* arg0, char* arg1, ulong flag, char* spec)
  587. {
  588. int ret;
  589. Chan *c0, *c1, *ac, *bc;
  590. struct{
  591. Chan *chan;
  592. Chan *authchan;
  593. char *spec;
  594. int flags;
  595. }bogus;
  596. if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER))
  597. error(Ebadarg);
  598. bogus.flags = flag & MCACHE;
  599. if(ismount){
  600. if(up->pgrp->noattach)
  601. error(Enoattach);
  602. ac = nil;
  603. bc = fdtochan(fd, ORDWR, 0, 1);
  604. if(waserror()) {
  605. if(ac)
  606. cclose(ac);
  607. cclose(bc);
  608. nexterror();
  609. }
  610. if(afd >= 0)
  611. ac = fdtochan(afd, ORDWR, 0, 1);
  612. bogus.chan = bc;
  613. bogus.authchan = ac;
  614. validaddr((ulong)spec, 1, 0);
  615. bogus.spec = spec;
  616. if(waserror())
  617. error(Ebadspec);
  618. validname(spec, 1);
  619. poperror();
  620. ret = devno('M', 0);
  621. c0 = devtab[ret]->attach((char*)&bogus);
  622. poperror();
  623. if(ac)
  624. cclose(ac);
  625. cclose(bc);
  626. }else{
  627. bogus.spec = 0;
  628. validaddr((ulong)arg0, 1, 0);
  629. c0 = namec(arg0, Abind, 0, 0);
  630. }
  631. if(waserror()){
  632. cclose(c0);
  633. nexterror();
  634. }
  635. validaddr((ulong)arg1, 1, 0);
  636. c1 = namec(arg1, Amount, 0, 0);
  637. if(waserror()){
  638. cclose(c1);
  639. nexterror();
  640. }
  641. ret = cmount(&c0, c1, flag, bogus.spec);
  642. poperror();
  643. cclose(c1);
  644. poperror();
  645. cclose(c0);
  646. if(ismount)
  647. fdclose(fd, 0);
  648. return ret;
  649. }
  650. long
  651. sysbind(ulong *arg)
  652. {
  653. return bindmount(0, -1, -1, (char*)arg[0], (char*)arg[1], arg[2], nil);
  654. }
  655. long
  656. sysmount(ulong *arg)
  657. {
  658. return bindmount(1, arg[0], arg[1], nil, (char*)arg[2], arg[3], (char*)arg[4]);
  659. }
  660. long
  661. sys_mount(ulong *arg)
  662. {
  663. return bindmount(1, arg[0], -1, nil, (char*)arg[1], arg[2], (char*)arg[3]);
  664. }
  665. long
  666. sysunmount(ulong *arg)
  667. {
  668. Chan *cmount, *cmounted;
  669. cmounted = 0;
  670. validaddr(arg[1], 1, 0);
  671. cmount = namec((char *)arg[1], Amount, 0, 0);
  672. if(arg[0]) {
  673. if(waserror()) {
  674. cclose(cmount);
  675. nexterror();
  676. }
  677. validaddr(arg[0], 1, 0);
  678. /*
  679. * This has to be namec(..., Aopen, ...) because
  680. * if arg[0] is something like /srv/cs or /fd/0,
  681. * opening it is the only way to get at the real
  682. * Chan underneath.
  683. */
  684. cmounted = namec((char*)arg[0], Aopen, OREAD, 0);
  685. poperror();
  686. }
  687. if(waserror()) {
  688. cclose(cmount);
  689. if(cmounted)
  690. cclose(cmounted);
  691. nexterror();
  692. }
  693. cunmount(cmount, cmounted);
  694. cclose(cmount);
  695. if(cmounted)
  696. cclose(cmounted);
  697. poperror();
  698. return 0;
  699. }
  700. long
  701. syscreate(ulong *arg)
  702. {
  703. int fd;
  704. Chan *c = 0;
  705. openmode(arg[1]&~OEXCL); /* error check only; OEXCL okay here */
  706. if(waserror()) {
  707. if(c)
  708. cclose(c);
  709. nexterror();
  710. }
  711. validaddr(arg[0], 1, 0);
  712. c = namec((char*)arg[0], Acreate, arg[1], arg[2]);
  713. fd = newfd(c);
  714. if(fd < 0)
  715. error(Enofd);
  716. poperror();
  717. return fd;
  718. }
  719. long
  720. sysremove(ulong *arg)
  721. {
  722. Chan *c;
  723. validaddr(arg[0], 1, 0);
  724. c = namec((char*)arg[0], Aremove, 0, 0);
  725. if(waserror()){
  726. c->type = 0; /* see below */
  727. cclose(c);
  728. nexterror();
  729. }
  730. devtab[c->type]->remove(c);
  731. /*
  732. * Remove clunks the fid, but we need to recover the Chan
  733. * so fake it up. rootclose() is known to be a nop.
  734. */
  735. c->type = 0;
  736. poperror();
  737. cclose(c);
  738. return 0;
  739. }
  740. long
  741. syswstat(ulong *arg)
  742. {
  743. Chan *c;
  744. uint l;
  745. l = arg[2];
  746. validaddr(arg[1], l, 0);
  747. validstat((uchar*)arg[1], l);
  748. validaddr(arg[0], 1, 0);
  749. c = namec((char*)arg[0], Aaccess, 0, 0);
  750. if(waserror()){
  751. cclose(c);
  752. nexterror();
  753. }
  754. l = devtab[c->type]->wstat(c, (uchar*)arg[1], l);
  755. poperror();
  756. cclose(c);
  757. return l;
  758. }
  759. long
  760. sysfwstat(ulong *arg)
  761. {
  762. Chan *c;
  763. uint l;
  764. l = arg[2];
  765. validaddr(arg[1], l, 0);
  766. validstat((uchar*)arg[1], l);
  767. c = fdtochan(arg[0], -1, 1, 1);
  768. if(waserror()) {
  769. cclose(c);
  770. nexterror();
  771. }
  772. l = devtab[c->type]->wstat(c, (uchar*)arg[1], l);
  773. poperror();
  774. cclose(c);
  775. return l;
  776. }
  777. static void
  778. packoldstat(uchar *buf, Dir *d)
  779. {
  780. uchar *p;
  781. ulong q;
  782. /* lay down old stat buffer - grotty code but it's temporary */
  783. p = buf;
  784. strncpy((char*)p, d->name, 28);
  785. p += 28;
  786. strncpy((char*)p, d->uid, 28);
  787. p += 28;
  788. strncpy((char*)p, d->gid, 28);
  789. p += 28;
  790. q = d->qid.path & ~DMDIR; /* make sure doesn't accidentally look like directory */
  791. if(d->qid.type & QTDIR) /* this is the real test of a new directory */
  792. q |= DMDIR;
  793. PBIT32(p, q);
  794. p += BIT32SZ;
  795. PBIT32(p, d->qid.vers);
  796. p += BIT32SZ;
  797. PBIT32(p, d->mode);
  798. p += BIT32SZ;
  799. PBIT32(p, d->atime);
  800. p += BIT32SZ;
  801. PBIT32(p, d->mtime);
  802. p += BIT32SZ;
  803. PBIT64(p, d->length);
  804. p += BIT64SZ;
  805. PBIT16(p, d->type);
  806. p += BIT16SZ;
  807. PBIT16(p, d->dev);
  808. }
  809. long
  810. sys_stat(ulong *arg)
  811. {
  812. Chan *c;
  813. uint l;
  814. uchar buf[128]; /* old DIRLEN plus a little should be plenty */
  815. char strs[128];
  816. Dir d;
  817. char old[] = "old stat system call - recompile";
  818. validaddr(arg[1], 116, 1);
  819. validaddr(arg[0], 1, 0);
  820. c = namec((char*)arg[0], Aaccess, 0, 0);
  821. if(waserror()){
  822. cclose(c);
  823. nexterror();
  824. }
  825. l = devtab[c->type]->stat(c, buf, sizeof buf);
  826. /* buf contains a new stat buf; convert to old. yuck. */
  827. if(l <= BIT16SZ) /* buffer too small; time to face reality */
  828. error(old);
  829. l = convM2D(buf, l, &d, strs);
  830. if(l == 0)
  831. error(old);
  832. packoldstat((uchar*)arg[1], &d);
  833. poperror();
  834. cclose(c);
  835. return 0;
  836. }
  837. long
  838. sys_fstat(ulong *arg)
  839. {
  840. Chan *c;
  841. uint l;
  842. uchar buf[128]; /* old DIRLEN plus a little should be plenty */
  843. char strs[128];
  844. Dir d;
  845. char old[] = "old fstat system call - recompile";
  846. validaddr(arg[1], 116, 1);
  847. c = fdtochan(arg[0], -1, 0, 1);
  848. if(waserror()){
  849. cclose(c);
  850. nexterror();
  851. }
  852. l = devtab[c->type]->stat(c, buf, sizeof buf);
  853. /* buf contains a new stat buf; convert to old. yuck. */
  854. if(l <= BIT16SZ) /* buffer too small; time to face reality */
  855. error(old);
  856. l = convM2D(buf, l, &d, strs);
  857. if(l == 0)
  858. error(old);
  859. packoldstat((uchar*)arg[1], &d);
  860. poperror();
  861. cclose(c);
  862. return 0;
  863. }
  864. long
  865. sys_wstat(ulong *)
  866. {
  867. error("old wstat system call - recompile");
  868. return -1;
  869. }
  870. long
  871. sys_fwstat(ulong *)
  872. {
  873. error("old fwstat system call - recompile");
  874. return -1;
  875. }