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