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