Add a bulk interface to sem_down()
[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 <slab.h>
30 #include <kmalloc.h>
31 #include <kref.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <assert.h>
35 #include <error.h>
36 #include <cpio.h>
37 #include <pmap.h>
38 #include <smp.h>
39 #include <net/ip.h>
40 #include <rcu.h>
41
42 /* TODO: these sizes are hokey.  DIRSIZE is used in chandirstat, and it looks
43  * like it's the size of a common-case stat. */
44 enum {
45         DIRSIZE = STAT_FIX_LEN_AK + 32 * STAT_NR_STRINGS_AK,
46         DIRREADLIM = 2048,      /* should handle the largest reasonable directory entry */
47         DIRREADSIZE=8192,       /* Just read a lot. Memory is cheap, lots of bandwidth,
48                                  * and RPCs are very expensive. At the same time,
49                                  * let's not yet exceed a common MSIZE. */
50 };
51
52 int newfd(struct chan *c, int low_fd, int oflags, bool must_use_low)
53 {
54         int ret = insert_obj_fdt(&current->open_files, c, low_fd,
55                                  oflags & O_CLOEXEC ? FD_CLOEXEC : 0,
56                                  must_use_low);
57         if (ret >= 0)
58                 cclose(c);
59         return ret;
60 }
61
62 struct chan *fdtochan(struct fd_table *fdt, int fd, int mode, int chkmnt,
63                       int iref)
64 {
65         struct chan *c;
66
67         c = lookup_fd(fdt, fd, iref);
68         if (!c) {
69                 /* We lost the info about why there was a problem (we used to track file
70                  * group closed too, can add that in later). */
71                 error(EBADF, ERROR_FIXME);
72         }
73         if (chkmnt && (c->flag & CMSG)) {
74                 if (iref)
75                         cclose(c);
76                 error(EBADF, ERROR_FIXME);
77         }
78         if (mode < 0)
79                 return c;
80         if ((mode & c->mode) != mode) {
81                 if (iref)
82                         cclose(c);
83                 error(EBADF,
84                       "FD access mode failure: chan mode 0x%x, wanted 0x%x (opened with 0 instead of O_READ?)",
85                       c->mode, mode);
86         }
87         return c;
88 }
89
90 long kchanio(void *vc, void *buf, int n, int mode)
91 {
92         ERRSTACK(1);
93         int r;
94         struct chan *c;
95
96         c = vc;
97         if (waserror()) {
98                 poperror();
99                 return -1;
100         }
101
102         if (mode == O_READ)
103                 r = devtab[c->type].read(c, buf, n, c->offset);
104         else if (mode == O_WRITE)
105                 r = devtab[c->type].write(c, buf, n, c->offset);
106         else
107                 error(ENOSYS, "kchanio: use only O_READ xor O_WRITE");
108
109         spin_lock(&c->lock);
110         c->offset += r;
111         spin_unlock(&c->lock);
112         poperror();
113         return r;
114 }
115
116 int openmode(uint32_t omode)
117 {
118 /* GIANT WARNING: if this ever throws, ipopen (and probably many others) will
119  * screw up refcnts of Qctl, err, data, etc */
120 #if 0
121         /* this is the old plan9 style.  i think they want to turn exec into read,
122          * and strip off anything higher, and just return the RD/WR style bits.  not
123          * stuff like ORCLOSE.  the lack of OEXCL might be a bug on their part (it's
124          * the only one of their non-RW-related flags that isn't masked out).
125          *
126          * Note that we no longer convert OEXEC/O_EXEC to O_READ, and instead return
127          * just the O_ACCMODE bits. */
128         if (o >= (OTRUNC | OCEXEC | ORCLOSE | OEXEC))
129                 error(EINVAL, ERROR_FIXME);
130         o &= ~(OTRUNC | OCEXEC | ORCLOSE);
131         if (o > OEXEC)
132                 error(EINVAL, ERROR_FIXME);
133         if (o == OEXEC)
134                 return OREAD;
135         return o;
136 #endif
137         /* no error checking (we have a shitload of flags anyway), and we return the
138          * basic access modes (RD/WR/ETC) */
139         return omode & O_ACCMODE;
140 }
141
142 void fdclose(struct fd_table *fdt, int fd)
143 {
144         close_fd(fdt, fd);
145 }
146
147 static void set_dot(struct chan *c)
148 {
149         c = atomic_swap_ptr((void**)&current->dot, c);
150         synchronize_rcu();
151         cclose(c);
152 }
153
154 int syschdir(char *path)
155 {
156         ERRSTACK(1);
157         struct chan *c;
158
159         if (waserror()) {
160                 poperror();
161                 return -1;
162         }
163         c = namec(path, Atodir, 0, 0, NULL);
164         poperror();
165         set_dot(c);
166         return 0;
167 }
168
169 int sysfchdir(int fd)
170 {
171         ERRSTACK(1);
172         struct chan *c;
173
174         if (waserror()) {
175                 poperror();
176                 return -1;
177         }
178         c = fdtochan(&current->open_files, fd, -1, 0, 1);
179         poperror();
180         set_dot(c);
181         return 0;
182 }
183
184 int sysclose(int fd)
185 {
186         ERRSTACK(1);
187         struct fd_table *fdt = &current->open_files;
188
189         if (waserror()) {
190                 poperror();
191                 return -1;
192         }
193         /*
194          * Take no reference on the chan because we don't really need the
195          * data structure, and are calling fdtochan only for error checks.
196          * fdclose takes care of processes racing through here.
197          */
198         fdtochan(fdt, fd, -1, 0, 0);
199         fdclose(fdt, fd);
200         poperror();
201         return 0;
202 }
203
204 int syscreate(char *path, int mode, uint32_t perm)
205 {
206         ERRSTACK(2);
207         int fd;
208         struct chan *c;
209
210         if (waserror()) {
211                 poperror();
212                 return -1;
213         }
214
215         openmode(mode & ~O_EXCL);       /* error check only; OEXCL okay here */
216         c = namec(path, Acreate, mode, perm, NULL);
217         if (waserror()) {
218                 cclose(c);
219                 nexterror();
220         }
221         /* 9ns mode is the O_FLAGS and perm is glibc mode */
222         fd = newfd(c, 0, mode, FALSE);
223         if (fd < 0)
224                 error(-fd, ERROR_FIXME);
225         poperror();
226
227         poperror();
228         return fd;
229 }
230
231 int sysdup(int old, int low_fd, bool must_use_low)
232 {
233         ERRSTACK(1);
234         int fd;
235         struct chan *c;
236
237         if (waserror()) {
238                 poperror();
239                 return -1;
240         }
241         c = fdtochan(&current->open_files, old, -1, 0, 1);
242         if (c->qid.type & QTAUTH) {
243                 cclose(c);
244                 error(EPERM, ERROR_FIXME);
245         }
246         fd = newfd(c, low_fd, 0, must_use_low);
247         if (fd < 0) {
248                 cclose(c);
249                 error(-fd, ERROR_FIXME);
250         }
251         poperror();
252         return fd;
253 }
254
255 /* Could pass in the fdt instead of the proc, but we used to need the to_proc
256  * for now so we can claim a VFS FD.  Careful, we don't close the old chan. */
257 int sys_dup_to(struct proc *from_proc, unsigned int from_fd,
258                struct proc *to_proc, unsigned int to_fd)
259 {
260         ERRSTACK(1);
261         int ret;
262         struct chan *c;
263
264         if (waserror()) {
265                 poperror();
266                 return -1;
267         }
268         c = fdtochan(&from_proc->open_files, from_fd, -1, 0, 1);
269         if (c->qid.type & QTAUTH) {
270                 cclose(c);
271                 error(EPERM, ERROR_FIXME);
272         }
273         ret = insert_obj_fdt(&to_proc->open_files, c, to_fd, 0, TRUE);
274         /* drop the ref from fdtochan.  if insert succeeded, there is one other ref
275          * stored in the FDT */
276         cclose(c);
277         if (ret < 0)
278                 error(EFAIL, "Can't insert FD %d into FDG", to_fd);
279         poperror();
280         return 0;
281 }
282
283 char *sysfd2path(int fd)
284 {
285         ERRSTACK(1);
286         struct chan *c;
287         char *s;
288
289         if (waserror()) {
290                 poperror();
291                 return NULL;
292         }
293         c = fdtochan(&current->open_files, fd, -1, 0, 1);
294         s = NULL;
295         if (c->name != NULL) {
296                 s = kzmalloc(c->name->len + 1, 0);
297                 if (s == NULL) {
298                         cclose(c);
299                         error(ENOMEM, ERROR_FIXME);
300                 }
301                 memmove(s, c->name->s, c->name->len + 1);
302         }
303         cclose(c);
304         poperror();
305         return s;
306 }
307
308 char *sysgetcwd(void)
309 {
310         char *s = NULL;
311         struct chan *dot;
312
313         rcu_read_lock();
314         dot = rcu_dereference(current->dot);
315         kref_get(&dot->ref, 1);
316         rcu_read_unlock();
317         if (dot->name)
318                 kstrdup(&s, dot->name->s);
319         cclose(dot);
320         return s;
321 }
322
323 int sysfauth(int fd, char *aname)
324 {
325         ERRSTACK(2);
326         struct chan *c, *ac;
327
328         if (waserror()) {
329                 poperror();
330                 return -1;
331         }
332
333         validname(aname, 0);
334         c = fdtochan(&current->open_files, fd, O_RDWR, 0, 1);
335         if (waserror()) {
336                 cclose(c);
337                 nexterror();
338         }
339
340         ac = mntauth(c, aname);
341
342         /* at this point ac is responsible for keeping c alive */
343         poperror();     /* c */
344         cclose(c);
345
346         if (waserror()) {
347                 cclose(ac);
348                 nexterror();
349         }
350
351         fd = newfd(ac, 0, 0, FALSE);
352         if (fd < 0)
353                 error(-fd, ERROR_FIXME);
354         poperror();     /* ac */
355
356         poperror();
357
358         return fd;
359 }
360
361 int sysfversion(int fd, unsigned int msize, char *vers, unsigned int arglen)
362 {
363         ERRSTACK(2);
364         int m;
365         struct chan *c;
366
367         if (waserror()) {
368                 poperror();
369                 return -1;
370         }
371
372         /* check there's a NUL in the version string */
373         if (arglen == 0 || memchr(vers, 0, arglen) == 0)
374                 error(EINVAL, ERROR_FIXME);
375
376         c = fdtochan(&current->open_files, fd, O_RDWR, 0, 1);
377         if (waserror()) {
378                 cclose(c);
379                 nexterror();
380         }
381
382         m = mntversion(c, vers, msize, arglen);
383
384         poperror();
385         cclose(c);
386
387         poperror();
388         return m;
389 }
390
391 int sysfwstat(int fd, uint8_t * buf, int n)
392 {
393         ERRSTACK(2);
394         struct chan *c;
395
396         if (waserror()) {
397                 poperror();
398                 return -1;
399         }
400
401         validstat(buf, n, 0);
402         c = fdtochan(&current->open_files, fd, -1, 1, 1);
403         if (waserror()) {
404                 cclose(c);
405                 nexterror();
406         }
407         n = devtab[c->type].wstat(c, buf, n);
408         poperror();
409         cclose(c);
410
411         poperror();
412         return n;
413 }
414
415 long bindmount(struct chan *c, char *old, int flag, char *spec)
416 {
417         ERRSTACK(1);
418         int ret;
419         struct chan *c1;
420
421         if (flag > MMASK || (flag & MORDER) == (MBEFORE | MAFTER))
422                 error(EINVAL, ERROR_FIXME);
423
424         c1 = namec(old, Amount, 0, 0, NULL);
425         if (waserror()) {
426                 cclose(c1);
427                 nexterror();
428         }
429         ret = cmount(c, c1, flag, spec);
430
431         poperror();
432         cclose(c1);
433         return ret;
434 }
435
436 int sysbind(char *new, char *old, int flags)
437 {
438         ERRSTACK(2);
439         long r;
440         struct chan *c0;
441
442         if (waserror()) {
443                 poperror();
444                 return -1;
445         }
446
447         c0 = namec(new, Abind, 0, 0, NULL);
448         if (waserror()) {
449                 cclose(c0);
450                 nexterror();
451         }
452         r = bindmount(c0, old, flags, "");
453         poperror();
454         cclose(c0);
455
456         poperror();
457         return r;
458 }
459
460 int syssymlink(char *new_path, char *old_path)
461 {
462         ERRSTACK(1);
463         struct chan *c;
464
465         if (waserror()) {
466                 poperror();
467                 return -1;
468         }
469         validname(old_path, true);
470         c = namec(new_path, Acreate, O_EXCL,
471                   DMSYMLINK | S_IRWXU | S_IRWXG | S_IRWXO, old_path);
472         cclose(c);
473         poperror();
474         return 0;
475 }
476
477 int sysmount(int fd, int afd, char *old, int flags, char *spec)
478 {
479         ERRSTACK(1);
480         long r;
481         volatile struct {
482                 struct chan *c;
483         } c0;
484         volatile struct {
485                 struct chan *c;
486         } bc;
487         volatile struct {
488                 struct chan *c;
489         } ac;
490         struct mntparam mntparam;
491
492         ac.c = NULL;
493         bc.c = NULL;
494         c0.c = NULL;
495         if (waserror()) {
496                 cclose(ac.c);
497                 cclose(bc.c);
498                 cclose(c0.c);
499                 poperror();
500                 return -1;
501         }
502         bc.c = fdtochan(&current->open_files, fd, O_RDWR, 0, 1);
503         if (afd >= 0)
504                 ac.c = fdtochan(&current->open_files, afd, O_RDWR, 0, 1);
505         mntparam.chan = bc.c;
506         mntparam.authchan = ac.c;
507         mntparam.spec = spec;
508         c0.c = devtab[devno("mnt", 0)].attach((char *)&mntparam);
509         if (flags & MCACHE)
510                 c0.c = devtab[devno("gtfs", 0)].attach((char*)c0.c);
511         r = bindmount(c0.c, old, flags, spec);
512         poperror();
513         cclose(ac.c);
514         cclose(bc.c);
515         cclose(c0.c);
516
517         return r;
518 }
519
520 int sysunmount(char *src_path, char *onto_path)
521 {
522         ERRSTACK(1);
523         volatile struct {
524                 struct chan *c;
525         } cmount;
526         volatile struct {
527                 struct chan *c;
528         } cmounted;
529
530         cmount.c = NULL;
531         cmounted.c = NULL;
532         if (waserror()) {
533                 cclose(cmount.c);
534                 cclose(cmounted.c);
535                 poperror();
536                 return -1;
537         }
538
539         cmount.c = namec(onto_path, Amount, 0, 0, NULL);
540         if (src_path != NULL && src_path[0] != '\0') {
541                 /*
542                  * This has to be namec(..., Aopen, ...) because
543                  * if arg[0] is something like /srv/cs or /fd/0,
544                  * opening it is the only way to get at the real
545                  * Chan underneath.
546                  */
547                 cmounted.c = namec(src_path, Aopen, O_READ, 0, NULL);
548         }
549
550         cunmount(cmount.c, cmounted.c);
551         poperror();
552         cclose(cmount.c);
553         cclose(cmounted.c);
554         return 0;
555 }
556
557 int sysopenat(int fromfd, char *path, int vfs_flags)
558 {
559         ERRSTACK(1);
560         int fd;
561         struct chan *c = 0, *from = 0;
562
563         if (waserror()) {
564                 cclose(c);
565                 poperror();
566                 return -1;
567         }
568         openmode(vfs_flags);    /* error check only */
569         if ((path[0] == '/') || (fromfd == AT_FDCWD)) {
570                 c = namec(path, Aopen, vfs_flags, 0, NULL);
571         } else {
572                 /* We don't cclose from.  namec_from will convert it to the new chan
573                  * during the walk process (c).  It'll probably close from internally,
574                  * and give us something new for c.  On error, namec_from will cclose
575                  * from. */
576                 from = fdtochan(&current->open_files, fromfd, -1, FALSE, TRUE);
577                 if (!(from->flag & O_PATH))
578                         error(EINVAL, "Cannot openat from a non-O_PATH FD");
579                 c = namec_from(from, path, Aopen, vfs_flags, 0, NULL);
580         }
581         /* Devices should catch this, but just in case, we'll catch it. */
582         if ((c->qid.type & QTSYMLINK) && (vfs_flags & O_NOFOLLOW))
583                 error(ELOOP, "no-follow open of a symlink");
584         fd = newfd(c, 0, vfs_flags, FALSE);
585         if (fd < 0)
586                 error(-fd, ERROR_FIXME);
587         poperror();
588         return fd;
589 }
590
591 int sysopen(char *path, int vfs_flags)
592 {
593         return sysopenat(AT_FDCWD, path, vfs_flags);
594 }
595
596 long unionread(struct chan *c, void *va, long n)
597 {
598         ERRSTACK(1);
599         int i;
600         long nr;
601         struct mhead *m;
602         struct mount *mount;
603
604         qlock(&c->umqlock);
605         m = c->umh;
606         rlock(&m->lock);
607         mount = m->mount;
608         /* bring mount in sync with c->uri and c->umc */
609         for (i = 0; mount != NULL && i < c->uri; i++)
610                 mount = mount->next;
611
612         nr = 0;
613         while (mount != NULL) {
614                 /* Error causes component of union to be skipped */
615                 if (mount->to) {
616                         /* normally we want to discard the error, but for our ghetto kdirent
617                          * hack, we need to repeat unionread if we saw a ENODATA */
618                         if (waserror()) {
619                                 if (get_errno() == ENODATA) {
620                                         runlock(&m->lock);
621                                         qunlock(&c->umqlock);
622                                         nexterror();
623                                 }
624                                 /* poperror done below for either branch */
625                         } else {
626                                 if (c->umc == NULL) {
627                                         c->umc = cclone(mount->to);
628                                         c->umc = devtab[c->umc->type].open(c->umc,
629                                                                            O_READ);
630                                 }
631
632                                 nr = devtab[c->umc->type].read(c->umc, va, n, c->umc->offset);
633                                 if (nr < 0)
634                                         nr = 0; /* dev.c can return -1 */
635                                 c->umc->offset += nr;
636                         }
637                         poperror();     /* pop regardless */
638                 }
639                 if (nr > 0)
640                         break;
641
642                 /* Advance to next element */
643                 c->uri++;
644                 if (c->umc) {
645                         cclose(c->umc);
646                         c->umc = NULL;
647                 }
648                 mount = mount->next;
649         }
650         runlock(&m->lock);
651         qunlock(&c->umqlock);
652         return nr;
653 }
654
655 static void unionrewind(struct chan *c)
656 {
657         qlock(&c->umqlock);
658         c->uri = 0;
659         if (c->umc) {
660                 cclose(c->umc);
661                 c->umc = NULL;
662         }
663         qunlock(&c->umqlock);
664 }
665
666 static long rread(int fd, void *va, long n, int64_t * offp)
667 {
668         ERRSTACK(3);
669         int dir;
670         struct chan *c;
671         int64_t off;
672
673         /* dirty dirent hack */
674         void *real_va = va;
675
676         if (waserror()) {
677                 poperror();
678                 return -1;
679         }
680
681         c = fdtochan(&current->open_files, fd, O_READ, 1, 1);
682         if (waserror()) {
683                 cclose(c);
684                 nexterror();
685         }
686
687         if (n < 0)
688                 error(EINVAL, ERROR_FIXME);
689
690         dir = c->qid.type & QTDIR;
691
692         /* kdirent hack: userspace is expecting kdirents, but all of 9ns
693          * produces Ms.  Just save up what we don't use and append the
694          * new stuff later. Allocate DIRREADSIZE bytes for that purpose.
695          */
696         if (dir) {
697                 int amt;
698                 /* expecting only one dirent at a time, o/w we're busted */
699                 assert(n >= sizeof(struct kdirent));
700                 if (!c->buf) {
701                         c->buf = kmalloc(DIRREADSIZE, MEM_WAIT);
702                         c->bufused = 0;
703                 }
704                 /* Attempt to extract an M, in case there was some already */
705                 amt = convM2kdirent(c->buf, c->bufused, real_va, 0);
706                 if (amt) {
707                         c->bufused -= amt;
708                         memmove(c->buf, c->buf + amt, c->bufused);
709                         n = sizeof(struct kdirent);
710                         goto out;
711                 }
712                 /* debugging */
713                 if (waserror()) {
714                         printk("Well, sysread of a dir sucks.%s \n", current_errstr());
715                         nexterror();
716                 }
717                 va = c->buf + c->bufused;
718                 n = DIRREADSIZE - c->bufused;
719         }
720
721         /* this is the normal plan9 read */
722         if (dir && c->umh)
723                 n = unionread(c, va, n);
724         else {
725                 if (offp == NULL) {
726                         spin_lock(&c->lock);    /* lock for int64_t assignment */
727                         off = c->offset;
728                         spin_unlock(&c->lock);
729                 } else
730                         off = *offp;
731                 if (off < 0)
732                         error(EINVAL, ERROR_FIXME);
733                 if (off == 0) {
734                         if (offp == NULL) {
735                                 spin_lock(&c->lock);
736                                 c->offset = 0;
737                                 c->dri = 0;
738                                 spin_unlock(&c->lock);
739                         }
740                         unionrewind(c);
741                 }
742                 if (! c->ateof) {
743                         n = devtab[c->type].read(c, va, n, off);
744                         if (n == 0 && dir)
745                                 c->ateof = 1;
746                 } else {
747                         n = 0;
748                 }
749                 spin_lock(&c->lock);
750                 c->offset += n;
751                 spin_unlock(&c->lock);
752         }
753
754         /* dirty kdirent hack */
755         if (dir) {
756                 int amt;
757                 c->bufused = c->bufused + n;
758                 /* extract an M from the front, then shift the remainder back */
759                 amt = convM2kdirent(c->buf, c->bufused, real_va, 0);
760                 c->bufused -= amt;
761                 memmove(c->buf, c->buf + amt, c->bufused);
762                 n = amt ? sizeof(struct kdirent) : 0;
763                 poperror();     /* matching our debugging waserror */
764         }
765
766 out:
767         poperror();
768         cclose(c);
769
770         poperror();
771         return n;
772 }
773
774 /* Reads exactly n bytes from chan c, starting at its offset.  Can block, but if
775  * we get 0 back too soon (EOF or error), then we'll error out with ENODATA.
776  * That might need a little work - if there was a previous error, then we
777  * clobbered it and only know ENODATA but not why we completed early. */
778 void read_exactly_n(struct chan *c, void *vp, long n)
779 {
780         char *p;
781         long nn;
782         int total = 0, want = n;
783
784         p = vp;
785         while (n > 0) {
786                 nn = devtab[c->type].read(c, p, n, c->offset);
787                 printd("readn: Got %d@%lld\n", nn, c->offset);
788                 if (nn == 0)
789                         error(ENODATA, "wanted %d, got %d", want, total);
790                 spin_lock(&c->lock);
791                 c->offset += nn;
792                 spin_unlock(&c->lock);
793                 p += nn;
794                 n -= nn;
795                 total += nn;
796         }
797 }
798
799 long sysread(int fd, void *va, long n)
800 {
801         return rread(fd, va, n, NULL);
802 }
803
804 long syspread(int fd, void *va, long n, int64_t off)
805 {
806         return rread(fd, va, n, &off);
807 }
808
809 int sysremove(char *path)
810 {
811         ERRSTACK(2);
812         struct chan *c;
813
814         if (waserror()) {
815                 poperror();
816                 return -1;
817         }
818
819         c = namec(path, Aremove, 0, 0, NULL);
820         if (waserror()) {
821                 c->type = -1;   /* see below */
822                 cclose(c);
823                 nexterror();
824         }
825         devtab[c->type].remove(c);
826         /*
827          * Remove clunks the fid, but we need to recover the Chan
828          * so fake it up.  -1 aborts the dev's close.
829          */
830         c->type = -1;
831         poperror();
832         cclose(c);
833
834         poperror();
835         return 0;
836 }
837
838 int sysrename(char *from_path, char *to_path)
839 {
840         ERRSTACK(1);
841         struct chan *volatile renamee = NULL;
842         struct chan *parent_chan;
843
844         if (waserror()) {
845                 cclose(renamee);
846                 poperror();
847                 return -1;
848         }
849         renamee = namec(from_path, Aremove, 0, 0, NULL);
850         /* We might need to support wstat for 'short' rename (intra-directory, with
851          * no slashes).  Til then, we can just go with EXDEV. */
852         if (!devtab[renamee->type].rename)
853                 error(EXDEV, "device does not support rename");
854         parent_chan = namec(to_path, Arename, 0, 0, (char*)renamee);
855         /* When we're done, renamee still points to the file, but it's in the new
856          * location.  Its cname is still the old location, similar to remove.  If
857          * anyone cares, we can change it.  parent_chan still points to the parent -
858          * it didn't get moved like create does.  Though it does have the name of
859          * the new location.  If we want, we can hand that to renamee.  It's a moot
860          * point, since they are both getting closed. */
861         cclose(renamee);
862         cclose(parent_chan);
863         poperror();
864         return 0;
865 }
866
867 int64_t sysseek(int fd, int64_t off, int whence)
868 {
869         ERRSTACK(2);
870         struct dir *dir;
871         struct chan *c;
872
873         if (waserror()) {
874                 poperror();
875                 return -1;
876         }
877
878         c = fdtochan(&current->open_files, fd, -1, 1, 1);
879         if (waserror()) {
880                 cclose(c);
881                 nexterror();
882         }
883         switch (whence) {
884                 case 0:
885                         if (c->qid.type & QTDIR) {
886                                 if (off != 0)
887                                         error(EISDIR, ERROR_FIXME);
888                                 unionrewind(c);
889                         } else if (off < 0)
890                                 error(EINVAL, ERROR_FIXME);
891                         spin_lock(&c->lock);    /* lock for int64_t assignment */
892                         c->offset = off;
893                         spin_unlock(&c->lock);
894                         break;
895
896                 case 1:
897                         if (c->qid.type & QTDIR)
898                                 error(EISDIR, ERROR_FIXME);
899                         spin_lock(&c->lock);    /* lock for read/write update */
900                         off += c->offset;
901                         if (off < 0) {
902                                 spin_unlock(&c->lock);
903                                 error(EINVAL, ERROR_FIXME);
904                         }
905                         c->offset = off;
906                         spin_unlock(&c->lock);
907                         break;
908
909                 case 2:
910                         if (c->qid.type & QTDIR)
911                                 error(EISDIR, ERROR_FIXME);
912                         dir = chandirstat(c);
913                         if (dir == NULL)
914                                 error(EFAIL, "internal error: stat error in seek");
915                         off += dir->length;
916                         kfree(dir);
917                         if (off < 0)
918                                 error(EINVAL, ERROR_FIXME);
919                         spin_lock(&c->lock);    /* lock for read/write update */
920                         c->offset = off;
921                         spin_unlock(&c->lock);
922                         break;
923
924                 default:
925                         error(EINVAL, ERROR_FIXME);
926                         break;
927         }
928         poperror();
929         c->dri = 0;
930         cclose(c);
931         poperror();
932         return off;
933 }
934
935 void validstat(uint8_t * s, int n, int slashok)
936 {
937
938         int m;
939         char buf[64];
940
941         if (statcheck(s, n) < 0)
942                 error(EINVAL, ERROR_FIXME);
943         /* verify that name entry is acceptable */
944         s += STAT_FIX_LEN_9P - STAT_NR_STRINGS_9P * BIT16SZ;
945         /*
946          * s now points at count for first string.
947          * if it's too long, let the server decide; this is
948          * only for his protection anyway. otherwise
949          * we'd have to allocate and waserror.
950          */
951         m = GBIT16(s);
952         s += BIT16SZ;
953         if (m + 1 > sizeof buf) {
954                 return;
955         }
956         memmove(buf, s, m);
957         buf[m] = '\0';
958         /* name could be '/' */
959         if (strcmp(buf, "/") != 0)
960                 validname(buf, slashok);
961 }
962
963 int sysfstat(int fd, uint8_t *buf, int n)
964 {
965         ERRSTACK(2);
966         struct chan *c;
967
968         if (waserror()) {
969                 poperror();
970                 return -1;
971         }
972
973         c = fdtochan(&current->open_files, fd, -1, 0, 1);
974         if (waserror()) {
975                 cclose(c);
976                 nexterror();
977         }
978         devtab[c->type].stat(c, buf, n);
979
980         poperror();
981         cclose(c);
982
983         poperror();
984         return n;
985 }
986
987 int sysfstatakaros(int fd, struct kstat *ks)
988 {
989
990         int n = 4096;
991         uint8_t *buf;
992         buf = kmalloc(n, MEM_WAIT);
993         n = sysfstat(fd, buf, n);
994         if (n > 0) {
995                 convM2kstat(buf, n, ks);
996                 n = 0;
997         }
998         kfree(buf);
999         return n;
1000 }
1001
1002 static int __stat(char *path, uint8_t *buf, int n, int flags)
1003 {
1004         ERRSTACK(2);
1005         struct chan *c;
1006
1007         if (waserror()) {
1008                 poperror();
1009                 return -1;
1010         }
1011
1012         c = namec(path, Aaccess, flags, 0, NULL);
1013         if (waserror()) {
1014                 cclose(c);
1015                 nexterror();
1016         }
1017         devtab[c->type].stat(c, buf, n);
1018         poperror();
1019         cclose(c);
1020
1021         poperror();
1022
1023         return n;
1024 }
1025
1026 int sysstat(char *path, uint8_t *buf, int n)
1027 {
1028         return __stat(path, buf, n, 0);
1029 }
1030
1031 int syslstat(char *path, uint8_t *buf, int n)
1032 {
1033         return __stat(path, buf, n, O_NOFOLLOW);
1034 }
1035
1036 int sysstatakaros(char *path, struct kstat *ks, int flags)
1037 {
1038
1039         int n = 4096;
1040         uint8_t *buf;
1041         buf = kmalloc(n, MEM_WAIT);
1042         n = __stat(path, buf, n, flags);
1043         if (n > 0) {
1044                 convM2kstat(buf, n, ks);
1045                 n = 0;
1046         }
1047         kfree(buf);
1048         return n;
1049 }
1050
1051 static long rwrite(int fd, void *va, long n, int64_t * offp)
1052 {
1053         ERRSTACK(3);
1054         struct chan *c;
1055         struct dir *dir;
1056         int64_t off;
1057         long m;
1058
1059         if (waserror()) {
1060                 poperror();
1061                 return -1;
1062         }
1063         c = fdtochan(&current->open_files, fd, O_WRITE, 1, 1);
1064         if (waserror()) {
1065                 cclose(c);
1066                 nexterror();
1067         }
1068         if (c->qid.type & QTDIR)
1069                 error(EISDIR, ERROR_FIXME);
1070
1071         if (n < 0)
1072                 error(EINVAL, ERROR_FIXME);
1073
1074         if (offp == NULL) {
1075                 /* append changes the offset to the end, and even if we fail later, this
1076                  * change will persist */
1077                 if (c->flag & O_APPEND) {
1078                         dir = chandirstat(c);
1079                         if (!dir)
1080                                 error(EFAIL, "internal error: stat error in append write");
1081                         spin_lock(&c->lock);    /* legacy lock for int64 assignment */
1082                         c->offset = dir->length;
1083                         spin_unlock(&c->lock);
1084                         kfree(dir);
1085                 }
1086                 spin_lock(&c->lock);
1087                 off = c->offset;
1088                 c->offset += n;
1089                 spin_unlock(&c->lock);
1090         } else
1091                 off = *offp;
1092
1093         if (waserror()) {
1094                 if (offp == NULL) {
1095                         spin_lock(&c->lock);
1096                         c->offset -= n;
1097                         spin_unlock(&c->lock);
1098                 }
1099                 nexterror();
1100         }
1101         if (off < 0)
1102                 error(EINVAL, ERROR_FIXME);
1103         m = devtab[c->type].write(c, va, n, off);
1104         poperror();
1105
1106         if (offp == NULL && m < n) {
1107                 spin_lock(&c->lock);
1108                 c->offset -= n - m;
1109                 spin_unlock(&c->lock);
1110         }
1111
1112         poperror();
1113         cclose(c);
1114
1115         poperror();
1116         return m;
1117 }
1118
1119 long syswrite(int fd, void *va, long n)
1120 {
1121         return rwrite(fd, va, n, NULL);
1122 }
1123
1124 long syspwrite(int fd, void *va, long n, int64_t off)
1125 {
1126         return rwrite(fd, va, n, &off);
1127 }
1128
1129 int syswstat(char *path, uint8_t * buf, int n)
1130 {
1131         ERRSTACK(2);
1132         struct chan *c;
1133
1134         if (waserror()) {
1135                 poperror();
1136                 return -1;
1137         }
1138
1139         validstat(buf, n, 0);
1140         c = namec(path, Aaccess, 0, 0, NULL);
1141         if (waserror()) {
1142                 cclose(c);
1143                 nexterror();
1144         }
1145         n = devtab[c->type].wstat(c, buf, n);
1146         poperror();
1147         cclose(c);
1148
1149         poperror();
1150         return n;
1151 }
1152
1153 struct dir *chandirstat(struct chan *c)
1154 {
1155         ERRSTACK(1);
1156         struct dir *d;
1157         uint8_t *buf;
1158         int n, nd, i;
1159
1160         nd = DIRSIZE;
1161         for (i = 0; i < 2; i++) {       /* should work by the second try */
1162                 d = kzmalloc(sizeof(struct dir) + nd, MEM_WAIT);
1163                 buf = (uint8_t *) & d[1];
1164                 if (waserror()) {
1165                         kfree(d);
1166                         poperror();
1167                         return NULL;
1168                 }
1169                 n = devtab[c->type].stat(c, buf, nd);
1170                 poperror();
1171                 if (n < BIT16SZ) {
1172                         kfree(d);
1173                         return NULL;
1174                 }
1175                 nd = GBIT16((uint8_t *) buf) + BIT16SZ; /* size needed to store whole stat buffer including count */
1176                 if (nd <= n) {
1177                         convM2D(buf, n, d, (char *)&d[1]);
1178                         return d;
1179                 }
1180                 /* else sizeof(Dir)+nd is plenty */
1181                 kfree(d);
1182         }
1183         return NULL;
1184
1185 }
1186
1187 static struct dir *__dir_stat(char *name, int flags)
1188 {
1189         ERRSTACK(2);
1190         struct chan *c;
1191         struct dir *d;
1192
1193         if (waserror()) {
1194                 poperror();
1195                 return NULL;
1196         }
1197
1198         c = namec(name, Aaccess, flags, 0, NULL);
1199         if (waserror()) {
1200                 cclose(c);
1201                 nexterror();
1202         }
1203         d = chandirstat(c);
1204         poperror();
1205         cclose(c);
1206
1207         poperror();
1208         return d;
1209 }
1210
1211 struct dir *sysdirstat(char *name)
1212 {
1213         return __dir_stat(name, 0);
1214 }
1215
1216 struct dir *sysdirlstat(char *name)
1217 {
1218         return __dir_stat(name, O_NOFOLLOW);
1219 }
1220
1221 struct dir *sysdirfstat(int fd)
1222 {
1223         ERRSTACK(2);
1224         struct chan *c;
1225         struct dir *d;
1226
1227         if (waserror()) {
1228                 poperror();
1229                 return NULL;
1230         }
1231
1232         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1233         if (waserror()) {
1234                 cclose(c);
1235                 nexterror();
1236         }
1237         d = chandirstat(c);
1238         poperror();
1239         cclose(c);
1240
1241         poperror();
1242         return d;
1243 }
1244
1245 int sysdirwstat(char *name, struct dir *dir)
1246 {
1247
1248         uint8_t *buf;
1249         int r;
1250
1251         r = sizeD2M(dir);
1252         buf = kzmalloc(r, MEM_WAIT);
1253         convD2M(dir, buf, r);
1254         r = syswstat(name, buf, r);
1255         kfree(buf);
1256         return r < 0 ? r : 0;
1257 }
1258
1259 int sysdirfwstat(int fd, struct dir *dir)
1260 {
1261
1262         uint8_t *buf;
1263         int r;
1264
1265         r = sizeD2M(dir);
1266         buf = kzmalloc(r, MEM_WAIT);
1267         convD2M(dir, buf, r);
1268         r = sysfwstat(fd, buf, r);
1269         kfree(buf);
1270         return r < 0 ? r : 0;
1271 }
1272
1273 static long dirpackage(uint8_t * buf, long ts, struct kdirent **d)
1274 {
1275
1276         char *s;
1277         long ss, i, n, nn, m = 0;
1278
1279         *d = NULL;
1280         if (ts <= 0) {
1281                 return ts;
1282         }
1283
1284         /*
1285          * first find number of all stats, check they look like stats, & size all associated strings
1286          */
1287         ss = 0;
1288         n = 0;
1289         for (i = 0; i < ts; i += m) {
1290                 m = BIT16SZ + GBIT16(&buf[i]);
1291                 if (statcheck(&buf[i], m) < 0)
1292                         break;
1293                 ss += m;
1294                 n++;
1295         }
1296
1297         if (i != ts)
1298                 error(EFAIL, "bad directory format");
1299
1300         *d = kzmalloc(n * sizeof(**d) + ss, 0);
1301         if (*d == NULL)
1302                 error(ENOMEM, ERROR_FIXME);
1303
1304         /*
1305          * then convert all buffers
1306          */
1307         s = (char *)*d + n * sizeof(**d);
1308         nn = 0;
1309         for (i = 0; i < ts; i += m) {
1310                 m = BIT16SZ + GBIT16((uint8_t *) & buf[i]);
1311                 /* Note 's' is ignored by convM2kdirent */
1312                 if (nn >= n || /*convM2D */ convM2kdirent(&buf[i], m, *d + nn, s) != m) {
1313                         kfree(*d);
1314                         *d = NULL;
1315                         error(EFAIL, "bad directory entry");
1316                 }
1317                 nn++;
1318                 s += m;
1319         }
1320
1321         return nn;
1322 }
1323
1324 long sysdirread(int fd, struct kdirent **d)
1325 {
1326         ERRSTACK(2);
1327         uint8_t *buf;
1328         long ts;
1329
1330         *d = NULL;
1331         if (waserror()) {
1332                 poperror();
1333                 return -1;
1334         }
1335         buf = kzmalloc(DIRREADLIM, 0);
1336         if (buf == NULL)
1337                 error(ENOMEM, ERROR_FIXME);
1338         if (waserror()) {
1339                 kfree(buf);
1340                 nexterror();
1341         }
1342         ts = sysread(fd, buf, DIRREADLIM);
1343         if (ts >= 0)
1344                 ts = dirpackage(buf, ts, d);
1345         poperror();
1346         kfree(buf);
1347         poperror();
1348         return ts;
1349 }
1350
1351 int sysiounit(int fd)
1352 {
1353         ERRSTACK(1);
1354         struct chan *c;
1355         int n;
1356
1357         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1358         if (waserror()) {
1359                 cclose(c);
1360                 poperror();
1361                 return 0;       /* n.b. */
1362         }
1363         n = c->iounit;
1364         poperror();
1365         cclose(c);
1366         return n;
1367 }
1368
1369 void print_chaninfo(struct chan *c)
1370 {
1371
1372         char buf[128] = { 0 };
1373         bool has_dev = c->type != -1;
1374         bool has_chaninfo = has_dev && devtab[c->type].chaninfo;
1375
1376         printk("Chan flags: %p, pathname: %s, ref: %d, Dev: %s, Devinfo: %s",
1377                    c->flag,
1378                    c->name ? c->name->s : "no cname",
1379                    kref_refcnt(&c->ref),
1380                    has_dev ? devtab[c->type].name : "no dev",
1381                    has_chaninfo ? devtab[c->type].chaninfo(c, buf, sizeof(buf)) : "");
1382         if (!has_chaninfo)
1383                 printk("qid.path: %p\n", c->qid.path);
1384         printk("\n");
1385 }
1386
1387 /* TODO: 9ns ns inheritance flags: Shared, copied, or empty.  The old fgrp is
1388  * managed by the fd_table, which is handled outside this function.  We share
1389  * the pgrp. */
1390 int plan9setup(struct proc *new_proc, struct proc *parent, int flags)
1391 {
1392
1393         struct chan *new_dot;
1394
1395         ERRSTACK(1);
1396         if (waserror()) {
1397                 printk("plan9setup failed, %s\n", current_errstr());
1398                 poperror();
1399                 return -1;
1400         }
1401         if (!parent) {
1402                 /* We are probably spawned by the kernel directly, and have no parent to
1403                  * inherit from. */
1404                 new_proc->pgrp = newpgrp();
1405                 new_proc->slash = namec("#kfs", Atodir, 0, 0, NULL);
1406                 if (!new_proc->slash)
1407                         panic("no kfs device");
1408                 /* Want the name to be "/" instead of "#kfs" */
1409                 cnameclose(new_proc->slash->name);
1410                 new_proc->slash->name = newcname("/");
1411                 new_proc->dot = cclone(new_proc->slash);
1412                 poperror();
1413                 return 0;
1414         }
1415         /* Shared semantics */
1416         kref_get(&parent->pgrp->ref, 1);
1417         new_proc->pgrp = parent->pgrp;
1418         /* copy semantics on / and . (doesn't make a lot of sense in akaros o/w) */
1419         /* / should never disappear while we hold a ref to parent */
1420         chan_incref(parent->slash);
1421         new_proc->slash = parent->slash;
1422
1423         rcu_read_lock();
1424         new_dot = rcu_dereference(parent->dot);
1425         kref_get(&new_dot->ref, 1);
1426         rcu_read_unlock();
1427         new_proc->dot = new_dot;
1428
1429         poperror();
1430         return 0;
1431 }
1432
1433 /* Open flags, create modes, access types, file flags, and all that...
1434  *
1435  * there are a bunch of things here:
1436  *              1) file creation flags (e.g. O_TRUNC)
1437  *              2) file status flags (e.g. O_APPEND)
1438  *              3) file open modes (e.g. O_RDWR)
1439  *              4) file descriptor flags (e.g. CLOEXEC)
1440  *              5) file creation mode (e.g. S_IRWXU)
1441  * the 1-4 are passed in via open's vfs_flags, and the 5 via mode only when
1442  * O_CREATE is set.
1443  *
1444  * file creation flags (1) only matter when creating, but aren't permanent.
1445  * O_EXCL, O_DIRECTORY, O_TRUNC, etc.
1446  *
1447  * file status flags (2) are per struct file/chan.  stuff like O_APPEND,
1448  * O_ASYNC, etc.  we convert those to an internal flag bit and store in c->flags
1449  *
1450  * the open mode (3) matters for a given FD/chan (chan->mode), and should be
1451  * stored in the chan. (c->mode) stuff like O_RDONLY.
1452  *
1453  * the file descriptor flags (4) clearly are in the FD.  note that the same
1454  * file/chan can be opened by two different FDs, with different flags.  the only
1455  * one anyone uses is CLOEXEC.  while exec may not last long in akaros, i can
1456  * imagine similar "never pass to children" flags/meanings.
1457  *
1458  * the file creation mode (5) matters for the device's permissions; given this,
1459  * it should be stored in the device/inode.  ACLs fall under this category.
1460  *
1461  * finally, only certain categories can be edited afterwards: file status flags
1462  * (2), FD flags (4), and file permissions (5). */
1463 int fd_getfl(int fd)
1464 {
1465         ERRSTACK(1);
1466         struct chan *c;
1467         int ret;
1468
1469         if (waserror()) {
1470                 poperror();
1471                 return -1;
1472         }
1473         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1474
1475         ret = c->mode;
1476         ret |= c->flag & CEXTERNAL_FLAGS;
1477
1478         cclose(c);
1479         poperror();
1480         return ret;
1481 }
1482
1483 static bool cexternal_flags_differ(int set1, int set2, int flags)
1484 {
1485         flags &= CEXTERNAL_FLAGS;
1486         return (set1 & flags) ^ (set2 & flags);
1487 }
1488
1489 int fd_setfl(int fd, int flags)
1490 {
1491         ERRSTACK(2);
1492         struct chan *c;
1493         int ret = 0;
1494
1495         if (waserror()) {
1496                 poperror();
1497                 return -1;
1498         }
1499         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1500         if (waserror()) {
1501                 cclose(c);
1502                 nexterror();
1503         }
1504         if (cexternal_flags_differ(flags, c->flag, O_CLOEXEC)) {
1505                 /* TODO: The whole CCEXEC / O_CLOEXEC on 9ns needs work */
1506                 error(EINVAL, "can't toggle O_CLOEXEC with setfl");
1507         }
1508         if (cexternal_flags_differ(flags, c->flag, O_REMCLO))
1509                 error(EINVAL, "can't toggle O_REMCLO with setfl");
1510         if (cexternal_flags_differ(flags, c->flag, O_PATH))
1511                 error(EINVAL, "can't toggle O_PATH with setfl");
1512         if (!devtab[c->type].chan_ctl)
1513                 error(EINVAL, "can't setfl, %s has no chan_ctl", chan_dev_name(c));
1514         ret = devtab[c->type].chan_ctl(c, CCTL_SET_FL, flags & CEXTERNAL_FLAGS,
1515                                        0, 0, 0);
1516         c->flag = (c->flag & ~CEXTERNAL_FLAGS) | (flags & CEXTERNAL_FLAGS);
1517         poperror();
1518         cclose(c);
1519         poperror();
1520         return ret;
1521 }
1522
1523 int fd_sync(int fd)
1524 {
1525         ERRSTACK(2);
1526         struct chan *c;
1527         int ret = 0;
1528
1529         if (waserror()) {
1530                 poperror();
1531                 return -1;
1532         }
1533         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1534         if (waserror()) {
1535                 cclose(c);
1536                 nexterror();
1537         }
1538         if (!devtab[c->type].chan_ctl)
1539                 error(EINVAL, "can't fsync, %s has no chan_ctl", chan_dev_name(c));
1540         ret = devtab[c->type].chan_ctl(c, CCTL_SYNC, 0, 0, 0, 0);
1541         poperror();
1542         cclose(c);
1543         poperror();
1544         return ret;
1545 }
1546
1547 ssize_t kread_file(struct file_or_chan *file, void *buf, size_t sz)
1548 {
1549         /* TODO: (KFOP) (VFS kernel read/writes need to be from a ktask) */
1550         uintptr_t old_ret = switch_to_ktask();
1551         off64_t dummy = 0;
1552         ssize_t cpy_amt = foc_read(file, buf, sz, dummy);
1553
1554         switch_back_from_ktask(old_ret);
1555         return cpy_amt;
1556 }
1557
1558 /* Reads the contents of an entire file into a buffer, returning that buffer.
1559  * On error, prints something useful and returns 0 */
1560 void *kread_whole_file(struct file_or_chan *file)
1561 {
1562         size_t size;
1563         void *contents;
1564         ssize_t cpy_amt;
1565
1566         size = foc_get_len(file);
1567         contents = kmalloc(size, MEM_WAIT);
1568         cpy_amt = kread_file(file, contents, size);
1569         if (cpy_amt < 0) {
1570                 printk("Error %d reading file %s\n", get_errno(), foc_to_name(file));
1571                 kfree(contents);
1572                 return 0;
1573         }
1574         if (cpy_amt != size) {
1575                 printk("Read %d, needed %d for file %s\n", cpy_amt, size,
1576                        foc_to_name(file));
1577                 kfree(contents);
1578                 return 0;
1579         }
1580         return contents;
1581 }
1582
1583 /* Process-related File management functions */
1584
1585 /* Given any FD, get the appropriate object, 0 o/w. Set incref if you want a
1586  * reference count (which is a 9ns thing, you can't use the pointer if you
1587  * didn't incref). */
1588 void *lookup_fd(struct fd_table *fdt, int fd, bool incref)
1589 {
1590         void *retval = 0;
1591
1592         if (fd < 0)
1593                 return 0;
1594         spin_lock(&fdt->lock);
1595         if (fdt->closed) {
1596                 spin_unlock(&fdt->lock);
1597                 return 0;
1598         }
1599         if (fd < fdt->max_fdset) {
1600                 if (GET_BITMASK_BIT(fdt->open_fds->fds_bits, fd)) {
1601                         /* while max_files and max_fdset might not line up, we should never
1602                          * have a valid fdset higher than files */
1603                         assert(fd < fdt->max_files);
1604                         retval = fdt->fd[fd].fd_chan;
1605                         if (incref)
1606                                 chan_incref((struct chan*)retval);
1607                 }
1608         }
1609         spin_unlock(&fdt->lock);
1610         return retval;
1611 }
1612
1613 /* Grow the vfs fd set */
1614 static int grow_fd_set(struct fd_table *open_files)
1615 {
1616         int n;
1617         struct file_desc *nfd, *ofd;
1618
1619         /* Only update open_fds once. If currently pointing to open_fds_init, then
1620          * update it to point to a newly allocated fd_set with space for
1621          * NR_FILE_DESC_MAX */
1622         if (open_files->open_fds == (struct fd_set*)&open_files->open_fds_init) {
1623                 open_files->open_fds = kzmalloc(sizeof(struct fd_set), 0);
1624                 memmove(open_files->open_fds, &open_files->open_fds_init,
1625                         sizeof(struct small_fd_set));
1626         }
1627
1628         /* Grow the open_files->fd array in increments of NR_OPEN_FILES_DEFAULT */
1629         n = open_files->max_files + NR_OPEN_FILES_DEFAULT;
1630         if (n > NR_FILE_DESC_MAX)
1631                 return -EMFILE;
1632         nfd = kzmalloc(n * sizeof(struct file_desc), 0);
1633         if (nfd == NULL)
1634                 return -ENOMEM;
1635
1636         /* Move the old array on top of the new one */
1637         ofd = open_files->fd;
1638         memmove(nfd, ofd, open_files->max_files * sizeof(struct file_desc));
1639
1640         /* Update the array and the maxes for both max_files and max_fdset */
1641         open_files->fd = nfd;
1642         open_files->max_files = n;
1643         open_files->max_fdset = n;
1644
1645         /* Only free the old one if it wasn't pointing to open_files->fd_array */
1646         if (ofd != open_files->fd_array)
1647                 kfree(ofd);
1648         return 0;
1649 }
1650
1651 /* Free the vfs fd set if necessary */
1652 static void free_fd_set(struct fd_table *open_files)
1653 {
1654         void *free_me;
1655
1656         if (open_files->open_fds != (struct fd_set*)&open_files->open_fds_init) {
1657                 assert(open_files->fd != open_files->fd_array);
1658                 /* need to reset the pointers to the internal addrs, in case we take a
1659                  * look while debugging.  0 them out, since they have old data.  our
1660                  * current versions should all be closed. */
1661                 memset(&open_files->open_fds_init, 0, sizeof(struct small_fd_set));
1662                 memset(&open_files->fd_array, 0, sizeof(open_files->fd_array));
1663
1664                 free_me = open_files->open_fds;
1665                 open_files->open_fds = (struct fd_set*)&open_files->open_fds_init;
1666                 kfree(free_me);
1667
1668                 free_me = open_files->fd;
1669                 open_files->fd = open_files->fd_array;
1670                 kfree(free_me);
1671         }
1672 }
1673
1674 /* If FD is in the group, remove it, decref it, and return TRUE. */
1675 bool close_fd(struct fd_table *fdt, int fd)
1676 {
1677         struct chan *chan = 0;
1678         struct fd_tap *tap = 0;
1679         bool ret = FALSE;
1680
1681         if (fd < 0)
1682                 return FALSE;
1683         spin_lock(&fdt->lock);
1684         if (fd < fdt->max_fdset) {
1685                 if (GET_BITMASK_BIT(fdt->open_fds->fds_bits, fd)) {
1686                         /* while max_files and max_fdset might not line up, we should never
1687                          * have a valid fdset higher than files */
1688                         assert(fd < fdt->max_files);
1689                         chan = fdt->fd[fd].fd_chan;
1690                         tap = fdt->fd[fd].fd_tap;
1691                         fdt->fd[fd].fd_chan = 0;
1692                         fdt->fd[fd].fd_tap = 0;
1693                         CLR_BITMASK_BIT(fdt->open_fds->fds_bits, fd);
1694                         if (fd < fdt->hint_min_fd)
1695                                 fdt->hint_min_fd = fd;
1696                         ret = TRUE;
1697                 }
1698         }
1699         spin_unlock(&fdt->lock);
1700         /* Need to decref/cclose outside of the lock; they could sleep */
1701         cclose(chan);
1702         if (tap)
1703                 kref_put(&tap->kref);
1704         return ret;
1705 }
1706
1707 static int __get_fd(struct fd_table *open_files, int low_fd, bool must_use_low)
1708 {
1709         int slot = -1;
1710         int error;
1711         bool update_hint = TRUE;
1712
1713         if ((low_fd < 0) || (low_fd > NR_FILE_DESC_MAX))
1714                 return -EINVAL;
1715         if (open_files->closed)
1716                 return -EINVAL; /* won't matter, they are dying */
1717         if (must_use_low && GET_BITMASK_BIT(open_files->open_fds->fds_bits, low_fd))
1718                 return -ENFILE;
1719         if (low_fd > open_files->hint_min_fd)
1720                 update_hint = FALSE;
1721         else
1722                 low_fd = open_files->hint_min_fd;
1723         /* Loop until we have a valid slot (we grow the fd_array at the bottom of
1724          * the loop if we haven't found a slot in the current array */
1725         while (slot == -1) {
1726                 for (low_fd; low_fd < open_files->max_fdset; low_fd++) {
1727                         if (GET_BITMASK_BIT(open_files->open_fds->fds_bits, low_fd))
1728                                 continue;
1729                         slot = low_fd;
1730                         SET_BITMASK_BIT(open_files->open_fds->fds_bits, slot);
1731                         assert(slot < open_files->max_files &&
1732                                open_files->fd[slot].fd_chan == 0);
1733                         /* We know slot >= hint, since we started with the hint */
1734                         if (update_hint)
1735                                 open_files->hint_min_fd = slot + 1;
1736                         break;
1737                 }
1738                 if (slot == -1) {
1739                         if ((error = grow_fd_set(open_files)))
1740                                 return error;
1741                 }
1742         }
1743         return slot;
1744 }
1745
1746 /* Insert a file or chan (obj, chosen by vfs) into the fd group with fd_flags.
1747  * If must_use_low, then we have to insert at FD = low_fd.  o/w we start looking
1748  * for empty slots at low_fd. */
1749 int insert_obj_fdt(struct fd_table *fdt, void *obj, int low_fd, int fd_flags,
1750                    bool must_use_low)
1751 {
1752         int slot;
1753
1754         spin_lock(&fdt->lock);
1755         slot = __get_fd(fdt, low_fd, must_use_low);
1756         if (slot < 0) {
1757                 spin_unlock(&fdt->lock);
1758                 return slot;
1759         }
1760         assert(slot < fdt->max_files &&
1761                fdt->fd[slot].fd_chan == 0);
1762         chan_incref((struct chan*)obj);
1763         fdt->fd[slot].fd_chan = obj;
1764         fdt->fd[slot].fd_flags = fd_flags;
1765         spin_unlock(&fdt->lock);
1766         return slot;
1767 }
1768
1769 /* Closes all open files.  Mostly just a "put" for all files.  If cloexec, it
1770  * will only close the FDs with FD_CLOEXEC (opened with O_CLOEXEC or fcntld).
1771  *
1772  * Notes on concurrency:
1773  * - Can't hold spinlocks while we call cclose, since it might sleep eventually.
1774  * - We're called from proc_destroy, so we could have concurrent openers trying
1775  *   to add to the group (other syscalls), hence the "closed" flag.
1776  * - dot and slash chans are dealt with in proc_free.  its difficult to close
1777  *   and zero those with concurrent syscalls, since those are a source of krefs.
1778  * - Once we lock and set closed, no further additions can happen.  To simplify
1779  *   our closes, we also allow multiple calls to this func (though that should
1780  *   never happen with the current code). */
1781 void close_fdt(struct fd_table *fdt, bool cloexec)
1782 {
1783         struct chan *chan;
1784         struct file_desc *to_close;
1785         int idx = 0;
1786
1787         to_close = kzmalloc(sizeof(struct file_desc) * fdt->max_files,
1788                             MEM_WAIT);
1789         spin_lock(&fdt->lock);
1790         if (fdt->closed) {
1791                 spin_unlock(&fdt->lock);
1792                 kfree(to_close);
1793                 return;
1794         }
1795         for (int i = 0; i < fdt->max_fdset; i++) {
1796                 if (GET_BITMASK_BIT(fdt->open_fds->fds_bits, i)) {
1797                         /* while max_files and max_fdset might not line up, we should never
1798                          * have a valid fdset higher than files */
1799                         assert(i < fdt->max_files);
1800                         if (cloexec && !(fdt->fd[i].fd_flags & FD_CLOEXEC))
1801                                 continue;
1802                         chan = fdt->fd[i].fd_chan;
1803                         to_close[idx].fd_tap = fdt->fd[i].fd_tap;
1804                         fdt->fd[i].fd_tap = 0;
1805                         fdt->fd[i].fd_chan = 0;
1806                         to_close[idx++].fd_chan = chan;
1807                         CLR_BITMASK_BIT(fdt->open_fds->fds_bits, i);
1808                 }
1809         }
1810         /* it's just a hint, we can build back up from being 0 */
1811         fdt->hint_min_fd = 0;
1812         if (!cloexec) {
1813                 free_fd_set(fdt);
1814                 fdt->closed = TRUE;
1815         }
1816         spin_unlock(&fdt->lock);
1817         /* We go through some hoops to close/decref outside the lock.  Nice for not
1818          * holding the lock for a while; critical in case the decref/cclose sleeps
1819          * (it can) */
1820         for (int i = 0; i < idx; i++) {
1821                 cclose(to_close[i].fd_chan);
1822                 if (to_close[i].fd_tap)
1823                         kref_put(&to_close[i].fd_tap->kref);
1824         }
1825         kfree(to_close);
1826 }
1827
1828 /* Inserts all of the files from src into dst, used by sys_fork(). */
1829 void clone_fdt(struct fd_table *src, struct fd_table *dst)
1830 {
1831         struct chan *chan;
1832         int ret;
1833
1834         spin_lock(&src->lock);
1835         if (src->closed) {
1836                 spin_unlock(&src->lock);
1837                 return;
1838         }
1839         spin_lock(&dst->lock);
1840         if (dst->closed) {
1841                 warn("Destination closed before it opened");
1842                 spin_unlock(&dst->lock);
1843                 spin_unlock(&src->lock);
1844                 return;
1845         }
1846         while (src->max_files > dst->max_files) {
1847                 ret = grow_fd_set(dst);
1848                 if (ret < 0) {
1849                         set_error(-ret, "Failed to grow for a clone_fdt");
1850                         spin_unlock(&dst->lock);
1851                         spin_unlock(&src->lock);
1852                         return;
1853                 }
1854         }
1855         for (int i = 0; i < src->max_fdset; i++) {
1856                 if (GET_BITMASK_BIT(src->open_fds->fds_bits, i)) {
1857                         /* while max_files and max_fdset might not line up, we should never
1858                          * have a valid fdset higher than files */
1859                         assert(i < src->max_files);
1860                         chan = src->fd[i].fd_chan;
1861                         assert(i < dst->max_files && dst->fd[i].fd_chan == 0);
1862                         SET_BITMASK_BIT(dst->open_fds->fds_bits, i);
1863                         dst->fd[i].fd_chan = chan;
1864                         chan_incref(chan);
1865                 }
1866         }
1867         dst->hint_min_fd = src->hint_min_fd;
1868         spin_unlock(&dst->lock);
1869         spin_unlock(&src->lock);
1870 }
1871
1872 int fd_get_fd_flags(struct fd_table *fdt, int fd)
1873 {
1874         int ret = -1;
1875
1876         if (fd < 0)
1877                 return -1;
1878         spin_lock(&fdt->lock);
1879         if (fdt->closed) {
1880                 spin_unlock(&fdt->lock);
1881                 return -1;
1882         }
1883         if ((fd < fdt->max_fdset) && GET_BITMASK_BIT(fdt->open_fds->fds_bits, fd))
1884                 ret = fdt->fd[fd].fd_flags;
1885         spin_unlock(&fdt->lock);
1886         if (ret == -1)
1887                 set_error(EBADF, "FD was not open");
1888         return ret;
1889 }
1890
1891 int fd_set_fd_flags(struct fd_table *fdt, int fd, int new_fl)
1892 {
1893         int ret = -1;
1894
1895         if (fd < 0)
1896                 return -1;
1897         spin_lock(&fdt->lock);
1898         if (fdt->closed) {
1899                 spin_unlock(&fdt->lock);
1900                 return -1;
1901         }
1902         if ((fd < fdt->max_fdset) && GET_BITMASK_BIT(fdt->open_fds->fds_bits, fd))
1903                 fdt->fd[fd].fd_flags = new_fl;
1904         spin_unlock(&fdt->lock);
1905         if (ret == -1)
1906                 set_error(EBADF, "FD was not open");
1907         return ret;
1908 }