Set up what we think is the right way to read directories
[akaros.git] / kern / src / ns / sysfile.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 static int
17 growfd(struct fgrp *f, int fd)
18 {
19         int n;
20         struct chan **nfd, **ofd;
21
22         if(fd < f->nfd)
23                 return 0;
24         n = f->nfd+DELTAFD;
25         if(n > MAXNFD)
26                 n = MAXNFD;
27         if(fd >= n)
28                 return -1;
29         nfd = kzmalloc(n * sizeof(struct chan *), 0);
30         if(nfd == NULL)
31                 return -1;
32         ofd = f->fd;
33         memmove(nfd, ofd, f->nfd*sizeof(struct chan *));
34         f->fd = nfd;
35         f->nfd = n;
36         kfree(ofd);
37         return 0;
38 }
39
40 int
41 newfd(struct chan *c)
42 {
43         int i;
44         struct fgrp *f = current->fgrp;
45
46         spin_lock(&f->lock);
47         if (f->closed) {
48                 spin_unlock(&f->lock);
49                 return -1;
50         }
51         /* VFS hack */
52         i = get_fd(&current->open_files, f->minfd);
53         assert(f->fd[i] == 0);
54         #if 0 // 9ns style
55         /* TODO: use a unique integer allocator */
56         for(i=f->minfd; i<f->nfd; i++)
57                 if(f->fd[i] == 0)
58                         break;
59         if(i >= f->nfd && growfd(f, i) < 0){
60                 spin_unlock(&f->lock);
61                 exhausted("file descriptors");
62                 return -1;
63         }
64         #endif
65         f->minfd = i + 1;
66         if(i > f->maxfd)
67                 f->maxfd = i;
68         f->fd[i] = c;
69         spin_unlock(&f->lock);
70         return i;
71 }
72
73 struct chan*
74 fdtochan(struct fgrp *f, int fd, int mode, int chkmnt, int iref)
75 {
76         struct chan *c;
77
78         c = 0;
79
80         spin_lock(&f->lock);
81         if (f->closed) {
82                 spin_unlock(&f->lock);
83                 error("File group closed");
84         }
85         if(fd<0 || f->maxfd<fd || (c = f->fd[fd])==0) {
86                 spin_unlock(&f->lock);
87                 error(Ebadfd);
88         }
89         if(iref)
90                 kref_get(&c->ref, 1);
91         spin_unlock(&f->lock);
92
93         if(chkmnt && (c->flag&CMSG)) {
94                 if(iref)
95                         cclose(c);
96                 error(Ebadusefd);
97         }
98
99         if(mode<0 || c->mode==ORDWR)
100                 return c;
101
102         if((mode&OTRUNC) && c->mode==OREAD) {
103                 if(iref)
104                         cclose(c);
105                 error(Ebadusefd);
106         }
107
108         if((mode&~OTRUNC) != c->mode) {
109                 if(iref)
110                         cclose(c);
111                 error(Ebadusefd);
112         }
113
114         return c;
115 }
116
117 long
118 kchanio(void *vc, void *buf, int n, int mode)
119 {
120         ERRSTACK(1);
121         int r;
122         struct chan *c;
123
124         c = vc;
125         if (waserror()) {
126                 poperror();
127                 return -1;
128         }
129
130         if(mode == OREAD)
131                 r = devtab[c->type]->read(c, buf, n, c->offset);
132         else
133                 r = devtab[c->type]->write(c, buf, n, c->offset);
134
135         spin_lock(&c->lock);
136         c->offset += r;
137         spin_unlock(&c->lock);
138         poperror();
139         return r;
140 }
141
142 int
143 openmode(uint32_t o)
144 {
145         if(o >= (OTRUNC|OCEXEC|ORCLOSE|OEXEC))
146                 error(Ebadarg);
147         o &= ~(OTRUNC|OCEXEC|ORCLOSE);
148         if(o > OEXEC)
149                 error(Ebadarg);
150         if(o == OEXEC)
151                 return OREAD;
152         return o;
153 }
154
155 void
156 fdclose(struct fgrp *f, int fd)
157 {
158         int i;
159         struct chan *c;
160
161         spin_lock(&f->lock);
162         if (f->closed) {
163                 spin_unlock(&f->lock);
164                 return;
165         }
166         c = f->fd[fd];
167         if(c == 0){
168                 /* can happen for users with shared fd tables */
169                 spin_unlock(&f->lock);
170                 return;
171         }
172         f->fd[fd] = 0;
173         if(fd == f->maxfd)
174                 for(i=fd; --i>=0 && f->fd[i]==0; )
175                         f->maxfd = i;
176         if(fd < f->minfd)
177                 f->minfd = fd;
178         /* VFS hack: give the FD back to VFS */
179         put_fd(&current->open_files, fd);
180         spin_unlock(&f->lock);
181         cclose(c);
182 }
183
184 int
185 syschdir(char *path)
186 {
187         ERRSTACK(1);
188         struct chan *c;
189         struct pgrp *pg;
190
191         if (waserror()) {
192                 poperror();
193                 return -1;
194         }
195
196         c = namec(path, Atodir, 0, 0);
197         pg = current->pgrp;
198         cclose(pg->dot);
199         pg->dot = c;
200         poperror();
201         return 0;
202 }
203
204 int
205 fgrpclose(struct fgrp *f, int fd)
206 {
207         ERRSTACK(1);
208         if (waserror()) {
209                 poperror();
210                 return -1;
211         }
212
213         /*
214          * Take no reference on the chan because we don't really need the
215          * data structure, and are calling fdtochan only for error checks.
216          * fdclose takes care of processes racing through here.
217          */
218         fdtochan(f, fd, -1, 0, 0);
219         fdclose(f, fd);
220         poperror();
221         return 0;
222 }
223
224 int
225 sysclose(int fd)
226 {
227         return fgrpclose(current->fgrp, fd);
228 }
229
230 int
231 syscreate(char *path, int mode, uint32_t perm)
232 {
233         ERRSTACK(2);
234         int fd;
235         struct chan *c;
236
237         if (waserror()) {
238                 poperror();
239                 return -1;
240         }
241
242         openmode(mode&~OEXCL);  /* error check only; OEXCL okay here */
243         c = namec(path, Acreate, mode, perm);
244         if(waserror()) {
245                 cclose(c);
246                 nexterror();
247         }
248         fd = newfd(c);
249         if(fd < 0)
250                 error(Enofd);
251         poperror();
252
253         poperror();
254         return fd;
255 }
256
257 int
258 sysdup(int old, int new)
259 {
260         ERRSTACK(2);
261         int fd;
262         struct chan *c, *oc;
263         struct fgrp *f = current->fgrp;
264
265         if (waserror()) {
266                 poperror();
267                 return -1;
268         }
269
270         c = fdtochan(current->fgrp, old, -1, 0, 1);
271         if(c->qid.type & QTAUTH)
272                 error(Eperm);
273         fd = new;
274         if(fd != -1){
275                 /* ideally we'll be done with the VFS before we fix this */
276                 panic("Need to sync with the VFS");
277                 spin_lock(&f->lock);
278                 if (f->closed) {
279                         spin_unlock(&f->lock);
280                         return -1;
281                 }
282                 if(fd<0 || growfd(f, fd) < 0) {
283                         spin_unlock(&f->lock);
284                         cclose(c);
285                         error(Ebadfd);
286                 }
287                 if(fd > f->maxfd)
288                         f->maxfd = fd;
289                 oc = f->fd[fd];
290                 f->fd[fd] = c;
291                 spin_unlock(&f->lock);
292                 if(oc)
293                         cclose(oc);
294         }else{
295                 if(waserror()) {
296                         cclose(c);
297                         nexterror();
298                 }
299                 fd = newfd(c);
300                 if(fd < 0)
301                         error(Enofd);
302                 poperror();
303         }
304         poperror();
305         return fd;
306 }
307
308 int
309 sysfstat(int fd, uint8_t *buf, int n)
310 {
311         ERRSTACK(2);
312         struct chan *c;
313
314         if (waserror()) {
315                 poperror();
316                 return -1;
317         }
318
319         c = fdtochan(current->fgrp, fd, -1, 0, 1);
320         if(waserror()) {
321                 cclose(c);
322                 nexterror();
323         }
324         devtab[c->type]->stat(c, buf, n);
325
326         poperror();
327         cclose(c);
328
329         poperror();
330         return n;
331 }
332
333 char*
334 sysfd2path(int fd)
335 {
336         ERRSTACK(1);
337         struct chan *c;
338         char *s;
339
340         if (waserror()) {
341                 poperror();
342                 return NULL;
343         }
344         c = fdtochan(current->fgrp, fd, -1, 0, 1);
345         s = NULL;
346         if(c->name != NULL){
347                 s = kzmalloc(c->name->len + 1, 0);
348                 if(s == NULL){
349                         cclose(c);
350                         error(Enomem);
351                 }
352                 memmove(s, c->name->s, c->name->len+1);
353                 cclose(c);
354         }
355         poperror();
356         return s;
357 }
358
359 int
360 sysfauth(int fd, char *aname)
361 {
362         ERRSTACK(2);
363         struct chan *c, *ac;
364
365         if (waserror()) {
366                 poperror();
367                 return -1;
368         }
369
370         validname(aname, 0);
371         c = fdtochan(current->fgrp, fd, ORDWR, 0, 1);
372         if(waserror()){
373                 cclose(c);
374                 nexterror();
375         }
376
377         ac = mntauth(c, aname);
378
379         /* at this point ac is responsible for keeping c alive */
380         poperror();     /* c */
381         cclose(c);
382
383         if(waserror()){
384                 cclose(ac);
385                 nexterror();
386         }
387
388         fd = newfd(ac);
389         if(fd < 0)
390                 error(Enofd);
391         poperror();     /* ac */
392
393         poperror();
394
395         return fd;
396 }
397
398 int
399 sysfversion(int fd, unsigned int msize, char *vers, unsigned int arglen)
400 {
401         ERRSTACK(2);
402         int m;
403         struct chan *c;
404
405         if (waserror()) {
406                 poperror();
407                 return -1;
408         }
409
410         /* check there's a NUL in the version string */
411         if(arglen==0 || memchr(vers, 0, arglen)==0)
412                 error(Ebadarg);
413
414         c = fdtochan(current->fgrp, fd, ORDWR, 0, 1);
415         if(waserror()){
416                 cclose(c);
417                 nexterror();
418         }
419
420         m = mntversion(c, vers, msize, arglen);
421
422         poperror();
423         cclose(c);
424
425         poperror();
426         return m;
427 }
428
429 int
430 syspipe(int fd[2])
431 {
432         ERRSTACK(1);
433         struct dev *d;
434         struct fgrp *f;
435         struct chan *c[2];
436         static char *names[] = {"data", "data1"};
437
438         f = current->fgrp;
439
440         d = devtab[devno('|', 0)];
441         c[0] = namec("#|", Atodir, 0, 0);
442         c[1] = 0;
443         fd[0] = -1;
444         fd[1] = -1;
445         if(waserror()) {
446                 if(c[0] != 0)
447                         cclose(c[0]);
448                 if(c[1] != 0)
449                         cclose(c[1]);
450                 if(fd[0] >= 0) {
451                         /* VFS hack */
452                         put_fd(&current->open_files, fd[0]);
453                         f->fd[fd[0]]=0;
454                 }
455                 if(fd[1] >= 0) {
456                         /* VFS hack */
457                         put_fd(&current->open_files, fd[1]);
458                         f->fd[fd[1]]=0;
459                 }
460                 poperror();
461                 return -1;
462         }
463         c[1] = cclone(c[0]);
464         if(walk(&c[0], &names[0], 1, 1, NULL) < 0)
465                 error(Egreg);
466         if(walk(&c[1], &names[1], 1, 1, NULL) < 0)
467                 error(Egreg);
468         c[0] = d->open(c[0], ORDWR);
469         c[1] = d->open(c[1], ORDWR);
470         fd[0] = newfd(c[0]);
471         if(fd[0] < 0)
472                 error(Enofd);
473         fd[1] = newfd(c[1]);
474         if(fd[1] < 0)
475                 error(Enofd);
476         poperror();
477         return 0;
478 }
479
480 int
481 sysfwstat(int fd, uint8_t *buf, int n)
482 {
483         ERRSTACK(2);
484         struct chan *c;
485
486         if (waserror()) {
487                 poperror();
488                 return -1;
489         }
490
491         validstat(buf, n);
492         c = fdtochan(current->fgrp, fd, -1, 1, 1);
493         if(waserror()) {
494                 cclose(c);
495                 nexterror();
496         }
497         n = devtab[c->type]->wstat(c, buf, n);
498         poperror();
499         cclose(c);
500
501         poperror();
502         return n;
503 }
504
505 long
506 bindmount(struct chan *c, char *old, int flag, char *spec)
507 {
508         ERRSTACK(1);
509         int ret;
510         struct chan *c1;
511
512         if(flag>MMASK || (flag&MORDER) == (MBEFORE|MAFTER))
513                 error(Ebadarg);
514
515         c1 = namec(old, Amount, 0, 0);
516         if(waserror()){
517                 cclose(c1);
518                 nexterror();
519         }
520         ret = cmount(c, c1, flag, spec);
521
522         poperror();
523         cclose(c1);
524         return ret;
525 }
526
527 int
528 sysbind(char *new, char *old, int flags)
529 {
530         ERRSTACK(2);
531         long r;
532         struct chan *c0;
533
534         if (waserror()) {
535                 poperror();
536                 return -1;
537         }
538
539         c0 = namec(new, Abind, 0, 0);
540         if(waserror()) {
541                 cclose(c0);
542                 nexterror();
543         }
544         r = bindmount(c0, old, flags, "");
545         poperror();
546         cclose(c0);
547
548         poperror();
549         return r;
550 }
551
552 int
553 sysmount(int fd, int afd, char *old, int flags, char *spec)
554 {
555         ERRSTACK(1);
556         long r;
557         volatile struct { struct chan *c; } c0;
558         volatile struct { struct chan *c; } bc;
559         volatile struct { struct chan *c; } ac;
560         struct mntparam mntparam;
561
562         ac.c = NULL;
563         bc.c = NULL;
564         c0.c = NULL;
565         if(waserror()) {
566                 cclose(ac.c);
567                 cclose(bc.c);
568                 cclose(c0.c);
569                 poperror();
570                 return -1;
571         }
572         bc.c = fdtochan(current->fgrp, fd, ORDWR, 0, 1);
573         if(afd >= 0)
574                 ac.c = fdtochan(current->fgrp, afd, ORDWR, 0, 1);
575         mntparam.chan = bc.c;
576         mntparam.authchan = ac.c;
577         mntparam.spec = spec;
578         mntparam.flags = flags;
579         c0.c = devtab[devno('M', 0)]->attach(( char *)&mntparam);
580
581         r = bindmount(c0.c, old, flags, spec);
582         poperror();
583         cclose(ac.c);
584         cclose(bc.c);
585         cclose(c0.c);
586
587         return r;
588 }
589
590 int
591 sysunmount(char *old, char *new)
592 {
593         ERRSTACK(1);
594         volatile struct { struct chan *c; } cmount;
595         volatile struct { struct chan *c; } cmounted;
596
597         cmount.c = NULL;
598         cmounted.c = NULL;
599         if(waserror()) {
600                 cclose(cmount.c);
601                 cclose(cmounted.c);
602                 poperror();
603                 return -1;
604         }
605
606         cmount.c = namec(new, Amount, 0, 0);
607         if(old != NULL && old[0] != '\0') {
608                 /*
609                  * This has to be namec(..., Aopen, ...) because
610                  * if arg[0] is something like /srv/cs or /fd/0,
611                  * opening it is the only way to get at the real
612                  * Chan underneath.
613                  */
614                 cmounted.c = namec(old, Aopen, OREAD, 0);
615         }
616
617         cunmount(cmount.c, cmounted.c);
618         poperror();
619         cclose(cmount.c);
620         cclose(cmounted.c);
621         return 0;
622 }
623
624 int
625 sysopen(char *path, int mode)
626 {
627         ERRSTACK(2);
628         int fd;
629         struct chan *c;
630
631         if (waserror()) {
632                 poperror();
633                 return -1;
634         }
635
636         openmode(mode);                         /* error check only */
637         c = namec(path, Aopen, mode, 0);
638         if(waserror()){
639                 cclose(c);
640                 nexterror();
641         }
642         fd = newfd(c);
643         if(fd < 0)
644                 error(Enofd);
645         poperror();
646
647         poperror();
648         return fd;
649 }
650
651 long
652 unionread(struct chan *c, void *va, long n)
653 {
654         ERRSTACK(1);
655         int i;
656         long nr;
657         struct mhead *m;
658         struct mount *mount;
659
660         qlock(&c->umqlock);
661         m = c->umh;
662         rlock(&m->lock);
663         mount = m->mount;
664         /* bring mount in sync with c->uri and c->umc */
665         for(i = 0; mount != NULL && i < c->uri; i++)
666                 mount = mount->next;
667
668         nr = 0;
669         while(mount != NULL) {
670                 /* Error causes component of union to be skipped */
671                 if(mount->to) {
672                         if (!waserror()) { /* discard style */
673                                 if(c->umc == NULL){
674                                         c->umc = cclone(mount->to);
675                                         c->umc = devtab[c->umc->type]->open(c->umc, OREAD);
676                                 }
677         
678                                 nr = devtab[c->umc->type]->read(c->umc, va, n, c->umc->offset);
679                                 if(nr < 0)
680                                         nr = 0; /* dev.c can return -1 */
681                                 c->umc->offset += nr;
682                         }
683                         poperror(); /* pop regardless */
684                 }
685                 if(nr > 0)
686                         break;
687
688                 /* Advance to next element */
689                 c->uri++;
690                 if(c->umc) {
691                         cclose(c->umc);
692                         c->umc = NULL;
693                 }
694                 mount = mount->next;
695         }
696         runlock(&m->lock);
697         qunlock(&c->umqlock);
698         return nr;
699 }
700
701 static void
702 unionrewind(struct chan *c)
703 {
704         qlock(&c->umqlock);
705         c->uri = 0;
706         if(c->umc){
707                 cclose(c->umc);
708                 c->umc = NULL;
709         }
710         qunlock(&c->umqlock);
711 }
712
713 static long
714 rread(int fd, void *va, long n, int64_t *offp)
715 {
716         ERRSTACK(2);
717         int dir;
718         struct chan *c;
719         int64_t off;
720
721         if (waserror()) {
722                 poperror();
723                 return -1;
724         }
725
726         c = fdtochan(current->fgrp, fd, OREAD, 1, 1);
727         if(waserror()) {
728                 cclose(c);
729                 nexterror();
730         }
731
732         if(n < 0)
733                 error(Etoosmall);
734
735         dir = c->qid.type & QTDIR;
736         if(dir && c->umh)
737                 n = unionread(c, va, n);
738         else{
739                 if(offp == NULL){
740                         spin_lock(&c->lock);    /* lock for int64_t assignment */
741                         off = c->offset;
742                         spin_unlock(&c->lock);
743                 }else
744                         off = *offp;
745                 if(off < 0)
746                         error(Enegoff);
747                 if(off == 0){
748                         if(offp == NULL){
749                                 spin_lock(&c->lock);
750                                 c->offset = 0;
751                                 c->dri = 0;
752                                 spin_unlock(&c->lock);
753                         }
754                         unionrewind(c);
755                 }
756                 n = devtab[c->type]->read(c, va, n, off);
757                 spin_lock(&c->lock);
758                 c->offset += n;
759                 spin_unlock(&c->lock);
760         }
761
762         poperror();
763         cclose(c);
764
765         poperror();
766         return n;
767 }
768
769 long
770 sysread(int fd, void *va, long n)
771 {
772         return rread(fd, va, n, NULL);
773 }
774
775 long
776 syspread(int fd, void *va, long n, int64_t off)
777 {
778         return rread(fd, va, n, &off);
779 }
780
781 int
782 sysremove(char *path)
783 {
784         ERRSTACK(2);
785         struct chan *c;
786
787         if (waserror()) {
788                 poperror();
789                 return -1; 
790         }
791
792         c = namec(path, Aremove, 0, 0);
793         if(waserror()) {
794                 c->type = 0;    /* see below */
795                 cclose(c);
796                 nexterror();
797         }
798         devtab[c->type]->remove(c);
799         /*
800          * Remove clunks the fid, but we need to recover the Chan
801          * so fake it up.  rootclose() is known to be a nop.
802          */
803         c->type = 0;
804         poperror();
805         cclose(c);
806
807         poperror();
808         return 0;
809 }
810
811 int64_t
812 sysseek(int fd, int64_t off, int whence)
813 {
814         ERRSTACK(2);
815         struct dir *dir;
816         struct chan *c;
817
818         if (waserror()) {
819                 poperror();
820                 return -1;
821         }
822
823         c = fdtochan(current->fgrp, fd, -1, 1, 1);
824         if(waserror()) {
825                 cclose(c);
826                 nexterror();
827         }
828
829         if(devtab[c->type]->dc == '|')
830                 error(Eisstream);
831
832         switch(whence) {
833         case 0:
834                 if(c->qid.type & QTDIR){
835                         if(off != 0)
836                                 error(Eisdir);
837                         unionrewind(c);
838                 }else if(off < 0)
839                         error(Enegoff);
840                 spin_lock(&c->lock);    /* lock for int64_t assignment */
841                 c->offset = off;
842                 spin_unlock(&c->lock);
843                 break;
844
845         case 1:
846                 if(c->qid.type & QTDIR)
847                         error(Eisdir);
848                 spin_lock(&c->lock);    /* lock for read/write update */
849                 off += c->offset;
850                 if(off < 0){
851                         spin_unlock(&c->lock);
852                         error(Enegoff);
853                 }
854                 c->offset = off;
855                 spin_unlock(&c->lock);
856                 break;
857
858         case 2:
859                 if(c->qid.type & QTDIR)
860                         error(Eisdir);
861                 dir = chandirstat(c);
862                 if(dir == NULL)
863                         error("internal error: stat error in seek");
864                 off += dir->length;
865                 kfree(dir);
866                 if(off < 0)
867                         error(Enegoff);
868                 spin_lock(&c->lock);    /* lock for read/write update */
869                 c->offset = off;
870                 spin_unlock(&c->lock);
871                 break;
872
873         default:
874                 error(Ebadarg);
875                 break;
876         }
877         poperror();
878         c->dri = 0;
879         cclose(c);
880         poperror();
881         return off;
882 }
883
884 void
885 validstat(uint8_t *s, int n)
886 {
887         int m;
888         char buf[64];
889
890         if(statcheck(s, n) < 0)
891                 error(Ebadstat);
892         /* verify that name entry is acceptable */
893         s += STATFIXLEN - 4*BIT16SZ;    /* location of first string */
894         /*
895          * s now points at count for first string.
896          * if it's too long, let the server decide; this is
897          * only for his protection anyway. otherwise
898          * we'd have to allocate and waserror.
899          */
900         m = GBIT16(s);
901         s += BIT16SZ;
902         if(m+1 > sizeof buf)
903                 return;
904         memmove(buf, s, m);
905         buf[m] = '\0';
906         /* name could be '/' */
907         if(strcmp(buf, "/") != 0)
908                 validname(buf, 0);
909 }
910
911 int
912 sysstat(char *path, uint8_t *buf, int n)
913 {
914         ERRSTACK(2);
915         struct chan *c;
916
917         if (waserror()) {
918                 poperror();
919                 return -1;
920         }
921
922         c = namec(path, Aaccess, 0, 0);
923         if(waserror()){
924                 cclose(c);
925                 nexterror();
926         }
927         devtab[c->type]->stat(c, buf, n);
928         poperror();
929         cclose(c);
930
931         poperror();
932         return 0;
933 }
934
935 static long
936 rwrite(int fd, void *va, long n, int64_t *offp)
937 {
938         ERRSTACK(3);
939         struct chan *c;
940         int64_t off;
941         long m;
942
943         if (waserror()) {
944                 poperror();
945                 return -1;
946         }
947         c = fdtochan(current->fgrp, fd, OWRITE, 1, 1);
948         if(waserror()) {
949                 cclose(c);
950                 nexterror();
951         }
952         if(c->qid.type & QTDIR)
953                 error(Eisdir);
954
955         if(n < 0)
956                 error(Etoosmall);
957
958         if(offp == NULL){
959                 spin_lock(&c->lock);
960                 off = c->offset;
961                 c->offset += n;
962                 spin_unlock(&c->lock);
963         }else
964                 off = *offp;
965
966         if(waserror()){
967                 if(offp == NULL){
968                         spin_lock(&c->lock);
969                         c->offset -= n;
970                         spin_unlock(&c->lock);
971                 }
972                 nexterror();
973         }
974         if(off < 0)
975                 error(Enegoff);
976         m = devtab[c->type]->write(c, va, n, off);
977         poperror();
978
979         if(offp == NULL && m < n){
980                 spin_lock(&c->lock);
981                 c->offset -= n - m;
982                 spin_unlock(&c->lock);
983         }
984
985         poperror();
986         cclose(c);
987
988         poperror();
989         return n;
990 }
991
992 long
993 syswrite(int fd, void *va, long n)
994 {
995         return rwrite(fd, va, n, NULL);
996 }
997
998 long
999 syspwrite(int fd, void *va, long n, int64_t off)
1000 {
1001         return rwrite(fd, va, n, &off);
1002 }
1003
1004 int
1005 syswstat(char *path, uint8_t *buf, int n)
1006 {
1007         ERRSTACK(2);
1008         struct chan *c;
1009
1010         if (waserror()) {
1011                 poperror();
1012                 return -1;
1013         }
1014
1015         validstat(buf, n);
1016         c = namec(path, Aaccess, 0, 0);
1017         if(waserror()){
1018                 cclose(c);
1019                 nexterror();
1020         }
1021         n = devtab[c->type]->wstat(c, buf, n);
1022         poperror();
1023         cclose(c);
1024
1025         poperror();
1026         return n;
1027 }
1028
1029 enum
1030 {
1031         DIRSIZE = STATFIXLEN + 32 * 4,
1032         DIRREADLIM = 2048,      /* should handle the largest reasonable directory entry */
1033 };
1034
1035 struct dir*
1036 chandirstat(struct chan *c)
1037 {
1038         ERRSTACK(1);
1039         struct dir *d;
1040         uint8_t *buf;
1041         int n, nd, i;
1042
1043         nd = DIRSIZE;
1044         for(i=0; i<2; i++){     /* should work by the second try */
1045                 d = kzmalloc(sizeof(struct dir) + nd, 0);
1046                 buf = ( uint8_t *)&d[1];
1047                 if(waserror()){
1048                         kfree(d);
1049                         poperror();
1050                         return NULL;
1051                 }
1052                 n = devtab[c->type]->stat(c, buf, nd);
1053                 poperror();
1054                 if(n < BIT16SZ){
1055                         kfree(d);
1056                         return NULL;
1057                 }
1058                 nd = GBIT16(( uint8_t *)buf) + BIT16SZ; /* size needed to store whole stat buffer including count */
1059                 if(nd <= n){
1060                         convM2D(buf, n, d, ( char *)&d[1]);
1061                         return d;
1062                 }
1063                 /* else sizeof(Dir)+nd is plenty */
1064                 kfree(d);
1065         }
1066         return NULL;
1067
1068 }
1069
1070 struct dir*
1071 sysdirstat(char *name)
1072 {
1073         ERRSTACK(2);
1074         struct chan *c;
1075         struct dir *d;
1076
1077         if (waserror()) {
1078                 poperror();
1079                 return NULL;
1080         }
1081
1082         c = namec(name, Aaccess, 0, 0);
1083         if(waserror()){
1084                 cclose(c);
1085                 nexterror();
1086         }
1087         d = chandirstat(c);
1088         poperror();
1089         cclose(c);
1090
1091         poperror();
1092         return d;
1093 }
1094
1095 struct dir*
1096 sysdirfstat(int fd)
1097 {
1098         ERRSTACK(2);
1099         struct chan *c;
1100         struct dir *d;
1101
1102         if (waserror()) {
1103                 poperror();
1104                 return NULL;
1105         }
1106
1107         c = fdtochan(current->fgrp, fd, -1, 0, 1);
1108         if(waserror()) {
1109                 cclose(c);
1110                 nexterror();
1111         }
1112         d = chandirstat(c);
1113         poperror();
1114         cclose(c);
1115
1116         poperror();
1117         return d;
1118 }
1119
1120 int
1121 sysdirwstat(char *name, struct dir *dir)
1122 {
1123         uint8_t *buf;
1124         int r;
1125
1126         r = sizeD2M(dir);
1127         buf = kzmalloc(r, 0);
1128         convD2M(dir, buf, r);
1129         r = syswstat(name, buf, r);
1130         kfree(buf);
1131         return r < 0? r: 0;
1132 }
1133
1134 int
1135 sysdirfwstat(int fd, struct dir *dir)
1136 {
1137         uint8_t *buf;
1138         int r;
1139
1140         r = sizeD2M(dir);
1141         buf = kzmalloc(r, 0);
1142         convD2M(dir, buf, r);
1143         r = sysfwstat(fd, buf, r);
1144         kfree(buf);
1145         return r < 0? r: 0;
1146 }
1147
1148 static long
1149 dirpackage(uint8_t *buf, long ts, struct kdirent **d)
1150 {
1151         char *s;
1152         long ss, i, n, nn, m = 0;
1153
1154         *d = NULL;
1155         if(ts <= 0)
1156                 return ts;
1157
1158         /*
1159          * first find number of all stats, check they look like stats, & size all associated strings
1160          */
1161         ss = 0;
1162         n = 0;
1163         for(i = 0; i < ts; i += m){
1164                 m = BIT16SZ + GBIT16(&buf[i]);
1165                 if(statcheck(&buf[i], m) < 0)
1166                         break;
1167                 ss += m;
1168                 n++;
1169         }
1170
1171         if(i != ts)
1172                 error("bad directory format");
1173
1174         *d = kzmalloc(n * sizeof(**d) + ss, 0);
1175         if(*d == NULL)
1176                 error(Enomem);
1177
1178         /*
1179          * then convert all buffers
1180          */
1181         s = ( char *)*d + n * sizeof(**d);
1182         nn = 0;
1183         for(i = 0; i < ts; i += m){
1184                 m = BIT16SZ + GBIT16(( uint8_t *)&buf[i]);
1185                 if(nn >= n || /*convM2D*/convM2kdirent(&buf[i], m, *d + nn, s) != m){
1186                         kfree(*d);
1187                         *d = NULL;
1188                         error("bad directory entry");
1189                 }
1190                 nn++;
1191                 s += m;
1192         }
1193
1194         return nn;
1195 }
1196
1197 long
1198 sysdirread(int fd, struct kdirent **d)
1199 {
1200         ERRSTACK(2);
1201         uint8_t *buf;
1202         long ts;
1203
1204         *d = NULL;
1205         if (waserror()) {
1206                 poperror();
1207                 return -1;
1208         }
1209         buf = kzmalloc(DIRREADLIM, 0);
1210         if(buf == NULL)
1211                 error(Enomem);
1212         if(waserror()){
1213                 kfree(buf);
1214                 nexterror();
1215         }
1216         ts = sysread(fd, buf, DIRREADLIM);
1217         if(ts >= 0)
1218                 ts = dirpackage(buf, ts, d);
1219         poperror();
1220         kfree(buf);
1221         poperror();
1222         return ts;
1223 }
1224
1225 int
1226 sysiounit(int fd)
1227 {
1228         ERRSTACK(1);
1229         struct chan *c;
1230         int n;
1231
1232         c = fdtochan(current->fgrp, fd, -1, 0, 1);
1233         if(waserror()){
1234                 cclose(c);
1235                 poperror();
1236                 return 0;       /* n.b. */
1237         }
1238         n = c->iounit;
1239         poperror();
1240         cclose(c);
1241         return n;
1242 }
1243
1244 /* Notes on concurrency:
1245  * - Can't hold spinlocks while we call cclose, since it might sleep eventually.
1246  * - We're called from proc_destroy, so we could have concurrent openers trying
1247  *   to add to the group (other syscalls), hence the "closed" flag.
1248  * - dot and slash chans are dealt with in proc_free.  its difficult to close
1249  *   and zero those with concurrent syscalls, since those are a source of krefs.
1250  * - the memory is freed in proc_free().  need to wait to do it, since we can
1251  *   have concurrent accesses to fgrp before free.
1252  * - Once we lock and set closed, no further additions can happen.  To simplify
1253  *   our closes, we also allow multiple calls to this func (though that should
1254  *   never happen with the current code). */
1255 void close_9ns_files(struct proc *p, bool only_cloexec)
1256 {
1257         struct fgrp *f = p->fgrp;
1258
1259         spin_lock(&f->lock);
1260         if (f->closed) {
1261                 spin_unlock(&f->lock);
1262                 warn("Unexpected double-close");
1263                 return;
1264         }
1265         if (!only_cloexec)
1266                 f->closed = TRUE;
1267         spin_unlock(&f->lock);
1268
1269         /* maxfd is a legit val, not a +1 */
1270         for (int i = 0; i <= f->maxfd; i++) {
1271                 if (!f->fd[i])
1272                         continue;
1273                 if (only_cloexec && !(f->fd[i]->flag & CCEXEC))
1274                         continue;
1275                 cclose(f->fd[i]);
1276                 f->fd[i] = 0;
1277         }
1278 }
1279
1280 void print_chaninfo(struct chan *ch)
1281 {
1282         char buf[64] = {0};
1283 #if 0
1284 FIXME
1285         printk("Chan pathname: %s, Dev: %s, Devinfo: %s\n",
1286                "ch->path ? ch->path->s : \"no path",
1287                ch->dev ? ch->dev->name: "no dev",
1288                    ch->dev ? ch->dev->chaninfo(ch, buf, sizeof(buf)) : "no info");
1289         if (!ch->dev)
1290                 printk("No dev: intermediate chan? qid.path: %p\n", ch->qid.path);
1291 #endif
1292 }
1293
1294 void print_9ns_files(struct proc *p)
1295 {
1296         struct fgrp *f = p->fgrp;
1297         spin_lock(&f->lock);
1298         printk("9ns files for proc %d:\n", p->pid);
1299         /* maxfd is a legit val, not a +1 */
1300         for (int i = 0; i <= f->maxfd; i++) {
1301                 if (!f->fd[i])
1302                         continue;
1303                 printk("\t9fs %d, ", i);
1304                 print_chaninfo(f->fd[i]);
1305         }
1306         spin_unlock(&f->lock);
1307 }
1308
1309 /* TODO: 9ns ns inheritance flags: Shared, copied, or empty.  Looks like we're
1310  * copying the fgrp, and sharing the pgrp. */
1311 int plan9setup(struct proc *new_proc, struct proc *parent)
1312 {
1313         struct proc *old_current;
1314         struct kref *new_dot_ref;
1315         ERRSTACK(1);
1316         if (waserror()) {
1317                 printk("plan9setup failed, %s\n", current_errstr());
1318                 poperror();
1319                 return -1;
1320         }
1321         if (!parent) {
1322                 /* We are probably spawned by the kernel directly, and have no parent to
1323                  * inherit from.  Be sure to set up fgrp/pgrp before calling namec().
1324                  *
1325                  * TODO: One problem is namec wants a current set for things like
1326                  * genbuf.  So we'll use new_proc for this bootstrapping.  Note
1327                  * switch_to() also loads the cr3. */
1328                 new_proc->fgrp = newfgrp();
1329                 new_proc->pgrp = newpgrp();
1330                 old_current = switch_to(new_proc);
1331                 new_proc->slash = namec("#r", Atodir, 0, 0);
1332                 if (!new_proc->slash)
1333                         panic("no root device");
1334                 switch_back(new_proc, old_current);
1335                 /* Want the name to be "/" instead of "#r" */
1336                 cnameclose(new_proc->slash->name);
1337                 new_proc->slash->name = newcname("/");
1338                 new_proc->dot = cclone(new_proc->slash);
1339                 poperror();
1340                 return 0;
1341         }
1342         /* Copy semantics: do not change this without revisiting proc_destroy,
1343          * close_9ns_files, and closefgrp. */
1344         new_proc->fgrp = dupfgrp(parent->fgrp);
1345         /* Shared semantics */
1346         kref_get(&parent->pgrp->ref, 1);
1347         new_proc->pgrp = parent->pgrp;
1348         /* copy semantics on / and . (doesn't make a lot of sense in akaros o/w) */
1349         /* / should never disappear while we hold a ref to parent */
1350         kref_get(&parent->slash->ref, 1);
1351         new_proc->slash = parent->slash;
1352         /* dot could change concurrently, and we could fail to gain a ref if whoever
1353          * decref'd dot triggered the release.  if that did happen, new_proc->dot
1354          * should update and we can try again. */
1355         while (!(new_dot_ref = kref_get_not_zero(&parent->dot->ref, 1)))
1356                 cpu_relax();
1357         /* And now, we can't trust parent->dot, and need to determine our dot from
1358          * the ref we obtained. */
1359         new_proc->dot = container_of(new_dot_ref, struct chan, ref);
1360         poperror();
1361         return 0;
1362 }
1363