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