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