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