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