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