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