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