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