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