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