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