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