Move p->fgrp into p->open_files
[akaros.git] / kern / src / ns / sysfile.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 enum {
17         DIRSIZE = STATFIXLEN + 32 * 4,
18         DIRREADLIM = 2048,      /* should handle the largest reasonable directory entry */
19         DIRREADSIZE=8192,       /* Just read a lot. Memory is cheap, lots of bandwidth,
20                                  * and RPCs are very expensive. At the same time,
21                                  * let's not yet exceed a common MSIZE. */
22 };
23
24 static int growfd(struct fgrp *f, int fd)
25 {
26         int n;
27         struct chan **nfd, **ofd;
28
29         if (fd < f->nfd) {
30                 return 0;
31         }
32         /* want to grow by a reasonable amount (delta), but also make sure we can
33          * handle the fd we're asked for */
34         n = MAX(f->nfd, fd + 1) + DELTAFD;
35         if (n > MAXNFD)
36                 n = MAXNFD;
37         if (fd >= n) {
38                 set_errno(EMFILE);
39                 set_errstr("Asked for FD %d, more than %d\n", fd, MAXNFD);
40                 return -1;
41         }
42         nfd = kzmalloc(n * sizeof(struct chan *), 0);
43         if (nfd == NULL) {
44                 set_errno(ENOMEM);
45                 set_errstr("Failed to growfd for FD %d, OOM\n", fd);
46                 return -1;
47         }
48         ofd = f->fd;
49         memmove(nfd, ofd, f->nfd * sizeof(struct chan *));
50         f->fd = nfd;
51         f->nfd = n;
52         kfree(ofd);
53         return 0;
54 }
55
56 int newfd(struct chan *c, bool oflags)
57 {
58         int i;
59         struct fgrp *f = current->open_files.fgrp;
60
61         spin_lock(&f->lock);
62         if (f->closed) {
63                 spin_unlock(&f->lock);
64                 return -1;
65         }
66         /* VFS hack */
67         /* We'd like to ask it to start at f->minfd, but that would require us to
68          * know if we closed anything.  Since we share the FD numbers with the VFS,
69          * there is no way to know that. */
70 #if 1   // VFS hack
71         i = get_fd(&current->open_files, 0, oflags & O_CLOEXEC);
72 #else   // 9ns style
73         /* TODO: use a unique integer allocator */
74         for (i = f->minfd; i < f->nfd; i++)
75                 if (f->fd[i] == 0)
76                         break;
77 #endif
78         if (growfd(f, i) < 0) {
79                 spin_unlock(&f->lock);
80                 return -1;
81         }
82         assert(f->fd[i] == 0);
83         f->minfd = i + 1;
84         if (i > f->maxfd)
85                 f->maxfd = i;
86         f->fd[i] = c;
87         spin_unlock(&f->lock);
88         return i;
89 }
90
91 struct chan *fdtochan(struct fd_table *fdt, int fd, int mode, int chkmnt,
92                       int iref)
93 {
94         struct fgrp *f = fdt->fgrp;
95         
96         struct chan *c;
97
98         c = 0;
99
100         spin_lock(&f->lock);
101         if (f->closed) {
102                 spin_unlock(&f->lock);
103                 error("File group closed");
104         }
105         if (fd < 0 || f->maxfd < fd || (c = f->fd[fd]) == 0) {
106                 spin_unlock(&f->lock);
107                 set_errno(EBADF);
108                 error("Bad FD %d\n", fd);
109         }
110         if (iref)
111                 chan_incref(c);
112         spin_unlock(&f->lock);
113
114         if (chkmnt && (c->flag & CMSG)) {
115                 if (iref)
116                         cclose(c);
117                 error(Ebadusefd);
118         }
119
120         if (mode < 0 || c->mode == ORDWR) {
121                 return c;
122         }
123
124         if ((mode & OTRUNC) && IS_RDONLY(c->mode)) {
125                 if (iref)
126                         cclose(c);
127                 error(Ebadusefd);
128         }
129
130         /* TODO: this is probably wrong.  if you get this from a dev, in the dev's
131          * open, you are probably saving mode directly, without passing it through
132          * openmode. */
133         if ((mode & ~OTRUNC) != c->mode) {
134                 warn("Trunc mode issue: mode %o, mode minus trunc %o, chan mode %o\n",
135                          mode, mode & ~OTRUNC, c->mode);
136                 if (iref)
137                         cclose(c);
138                 error(Ebadusefd);
139         }
140
141         return c;
142 }
143
144 long kchanio(void *vc, void *buf, int n, int mode)
145 {
146         ERRSTACK(1);
147         int r;
148         struct chan *c;
149
150         c = vc;
151         if (waserror()) {
152                 poperror();
153                 return -1;
154         }
155
156         if (IS_RDONLY(mode))
157                 r = devtab[c->type].read(c, buf, n, c->offset);
158         else
159                 r = devtab[c->type].write(c, buf, n, c->offset);
160
161         spin_lock(&c->lock);
162         c->offset += r;
163         spin_unlock(&c->lock);
164         poperror();
165         return r;
166 }
167
168 int openmode(uint32_t omode)
169 {
170 /* GIANT WARNING: if this ever throws, ipopen (and probably many others) will
171  * screw up refcnts of Qctl, err, data, etc */
172 #if 0
173         /* this is the old plan9 style.  i think they want to turn exec into read,
174          * and strip off anything higher, and just return the RD/WR style bits.  not
175          * stuff like ORCLOSE.  the lack of OEXCL might be a bug on their part (it's
176          * the only one of their non-RW-related flags that isn't masked out) */
177         if (o >= (OTRUNC | OCEXEC | ORCLOSE | OEXEC))
178                 error(Ebadarg);
179         o &= ~(OTRUNC | OCEXEC | ORCLOSE);
180         if (o > OEXEC)
181                 error(Ebadarg);
182         if (o == OEXEC)
183                 return OREAD;
184         return o;
185 #endif
186         /* no error checking (we have a shitload of flags anyway), and we return the
187          * basic access modes (RD/WR/ETC) */
188         if (omode == O_EXEC) {
189         return O_RDONLY;
190         }
191         return omode & O_ACCMODE;
192 }
193
194 void fdclose(struct fd_table *fdt, int fd)
195 {
196         struct fgrp *f = fdt->fgrp;
197         
198         int i;
199         struct chan *c;
200
201         spin_lock(&f->lock);
202         if (f->closed) {
203                 spin_unlock(&f->lock);
204                 return;
205         }
206         c = f->fd[fd];
207         if (c == 0) {
208                 /* can happen for users with shared fd tables */
209                 spin_unlock(&f->lock);
210                 return;
211         }
212         f->fd[fd] = 0;
213         if (fd == f->maxfd)
214                 for (i = fd; --i >= 0 && f->fd[i] == 0;)
215                         f->maxfd = i;
216         if (fd < f->minfd)
217                 f->minfd = fd;
218         /* VFS hack: give the FD back to VFS */
219         put_fd(&current->open_files, fd);
220         spin_unlock(&f->lock);
221         cclose(c);
222 }
223
224 int syschdir(char *path)
225 {
226         ERRSTACK(1);
227         struct chan *c;
228         struct pgrp *pg;
229
230         if (waserror()) {
231                 poperror();
232                 return -1;
233         }
234
235         c = namec(path, Atodir, 0, 0);
236         pg = current->pgrp;
237         cclose(pg->dot);
238         pg->dot = c;
239         poperror();
240         return 0;
241 }
242
243 int fgrpclose(struct fd_table *fdt, int fd)
244 {
245         ERRSTACK(1);
246         if (waserror()) {
247                 poperror();
248                 return -1;
249         }
250
251         /*
252          * Take no reference on the chan because we don't really need the
253          * data structure, and are calling fdtochan only for error checks.
254          * fdclose takes care of processes racing through here.
255          */
256         fdtochan(fdt, fd, -1, 0, 0);
257         fdclose(fdt, fd);
258         poperror();
259         return 0;
260 }
261
262 int sysclose(int fd)
263 {
264         return fgrpclose(&current->open_files, fd);
265 }
266
267 int syscreate(char *path, int mode, uint32_t perm)
268 {
269         ERRSTACK(2);
270         int fd;
271         struct chan *c;
272
273         if (waserror()) {
274                 poperror();
275                 return -1;
276         }
277
278         openmode(mode & ~OEXCL);        /* error check only; OEXCL okay here */
279         c = namec(path, Acreate, mode, perm);
280         if (waserror()) {
281                 cclose(c);
282                 nexterror();
283         }
284         fd = newfd(c, mode);    /* 9ns mode is the O_FLAGS and perm is glibc mode */
285         if (fd < 0)
286                 error(Enofd);
287         poperror();
288
289         poperror();
290         return fd;
291 }
292
293 // This is in need of rework but for now just copy and convert.
294 int sysdup(int old, int new)
295 {
296         ERRSTACK(2);
297         int fd;
298         struct chan *c, *oc;
299         struct fgrp *f = current->open_files.fgrp;
300
301         if (waserror()) {
302                 poperror();
303                 return -1;
304         }
305
306         c = fdtochan(&current->open_files, old, -1, 0, 1);
307         if (c->qid.type & QTAUTH) {
308                 cclose(c);
309                 error(Eperm);
310         }
311         fd = new;
312         if (fd != -1) {
313                 /* ideally we'll be done with the VFS before we fix this */
314                 /* double check the ccloses when you fix this */
315                 panic("Need to sync with the VFS");
316                 spin_lock(&f->lock);
317                 if (f->closed) {
318                         spin_unlock(&f->lock);
319                         cclose(c);
320                         return -1;
321                 }
322                 if (fd < 0) {
323                         spin_unlock(&f->lock);
324                         cclose(c);
325                         set_errno(EBADF);
326                         error("Bad FD %d\n", fd);
327                 }
328                 if (growfd(f, fd) < 0) {
329                         spin_unlock(&f->lock);
330                         cclose(c);
331                         error(current_errstr());
332                 }
333                 if (fd > f->maxfd)
334                         f->maxfd = fd;
335                 oc = f->fd[fd];
336                 f->fd[fd] = c;
337                 spin_unlock(&f->lock);
338                 if (oc)
339                         cclose(oc);
340         } else {
341                 if (waserror()) {
342                         cclose(c);
343                         nexterror();
344                 }
345                 fd = newfd(c, 0);
346                 if (fd < 0)
347                         error(Enofd);
348                 poperror();
349         }
350         poperror();
351         return fd;
352 }
353
354 /* Could pass in the fgrp instead of the proc, but we need the to_proc for now
355  * so we can claim a VFS FD */
356 int sys_dup_to(struct proc *from_proc, unsigned int from_fd,
357                struct proc *to_proc, unsigned int to_fd)
358 {
359         ERRSTACK(1);
360         struct chan *c, *old_chan;
361         struct fgrp *to_fgrp = to_proc->open_files.fgrp;
362
363         if (waserror()) {
364                 poperror();
365                 return -1;
366         }
367
368         c = fdtochan(&from_proc->open_files, from_fd, -1, 0, 1);
369         if (c->qid.type & QTAUTH) {
370                 cclose(c);
371                 error(Eperm);
372         }
373
374         spin_lock(&to_fgrp->lock);
375         if (to_fgrp->closed) {
376                 spin_unlock(&to_fgrp->lock);
377                 cclose(c);
378                 error("Can't dup, FGRP closed");
379         }
380         if (claim_fd(&to_proc->open_files, to_fd)) {
381                 spin_unlock(&to_fgrp->lock);
382                 cclose(c);
383                 error("Can't claim FD %d", to_fd);
384         }
385         if (growfd(to_fgrp, to_fd) < 0) {
386                 spin_unlock(&to_fgrp->lock);
387                 cclose(c);
388                 error(current_errstr());
389         }
390         if (to_fd > to_fgrp->maxfd)
391                 to_fgrp->maxfd = to_fd;
392         old_chan = to_fgrp->fd[to_fd];
393         to_fgrp->fd[to_fd] = c;
394         spin_unlock(&to_fgrp->lock);
395         if (old_chan)
396                 cclose(old_chan);
397
398         poperror();
399         return 0;
400 }
401
402 char *sysfd2path(int fd)
403 {
404         ERRSTACK(1);
405         struct chan *c;
406         char *s;
407
408         if (waserror()) {
409                 poperror();
410                 return NULL;
411         }
412         c = fdtochan(&current->open_files, fd, -1, 0, 1);
413         s = NULL;
414         if (c->name != NULL) {
415                 s = kzmalloc(c->name->len + 1, 0);
416                 if (s == NULL) {
417                         cclose(c);
418                         error(Enomem);
419                 }
420                 memmove(s, c->name->s, c->name->len + 1);
421         }
422         cclose(c);
423         poperror();
424         return s;
425 }
426
427 int sysfauth(int fd, char *aname)
428 {
429         ERRSTACK(2);
430         struct chan *c, *ac;
431
432         if (waserror()) {
433                 poperror();
434                 return -1;
435         }
436
437         validname(aname, 0);
438         c = fdtochan(&current->open_files, fd, ORDWR, 0, 1);
439         if (waserror()) {
440                 cclose(c);
441                 nexterror();
442         }
443
444         ac = mntauth(c, aname);
445
446         /* at this point ac is responsible for keeping c alive */
447         poperror();     /* c */
448         cclose(c);
449
450         if (waserror()) {
451                 cclose(ac);
452                 nexterror();
453         }
454
455         fd = newfd(ac, 0);
456         if (fd < 0)
457                 error(Enofd);
458         poperror();     /* ac */
459
460         poperror();
461
462         return fd;
463 }
464
465 int sysfversion(int fd, unsigned int msize, char *vers, unsigned int arglen)
466 {
467         ERRSTACK(2);
468         int m;
469         struct chan *c;
470
471         if (waserror()) {
472                 poperror();
473                 return -1;
474         }
475
476         /* check there's a NUL in the version string */
477         if (arglen == 0 || memchr(vers, 0, arglen) == 0)
478                 error(Ebadarg);
479
480         c = fdtochan(&current->open_files, fd, ORDWR, 0, 1);
481         if (waserror()) {
482                 cclose(c);
483                 nexterror();
484         }
485
486         m = mntversion(c, vers, msize, arglen);
487
488         poperror();
489         cclose(c);
490
491         poperror();
492         return m;
493 }
494
495 int syspipe(int fd[2])
496 {
497         ERRSTACK(1);
498         struct dev *d;
499         struct fgrp *f;
500         struct chan *c[2];
501         static char *names[] = { "data", "data1" };
502
503         f = current->open_files.fgrp;
504
505         d = &devtab[devno('|', 0)];
506         c[0] = namec("#|", Atodir, 0, 0);
507         c[1] = 0;
508         fd[0] = -1;
509         fd[1] = -1;
510         if (waserror()) {
511                 if (c[0] != 0)
512                         cclose(c[0]);
513                 if (c[1] != 0)
514                         cclose(c[1]);
515                 if (fd[0] >= 0) {
516                         /* VFS hack */
517                         f->fd[fd[0]] = 0;
518                         put_fd(&current->open_files, fd[0]);
519                 }
520                 if (fd[1] >= 0) {
521                         /* VFS hack */
522                         f->fd[fd[1]] = 0;
523                         put_fd(&current->open_files, fd[1]);
524                 }
525                 poperror();
526                 return -1;
527         }
528         c[1] = cclone(c[0]);
529         if (walk(&c[0], &names[0], 1, 1, NULL) < 0)
530                 error(Egreg);
531         if (walk(&c[1], &names[1], 1, 1, NULL) < 0)
532                 error(Egreg);
533         c[0] = d->open(c[0], ORDWR);
534         c[1] = d->open(c[1], ORDWR);
535         fd[0] = newfd(c[0], 0);
536         if (fd[0] < 0)
537                 error(Enofd);
538         fd[1] = newfd(c[1], 0);
539         if (fd[1] < 0)
540                 error(Enofd);
541         poperror();
542         return 0;
543 }
544
545 int sysfwstat(int fd, uint8_t * buf, int n)
546 {
547         ERRSTACK(2);
548         struct chan *c;
549
550         if (waserror()) {
551                 poperror();
552                 return -1;
553         }
554
555         validstat(buf, n, 0);
556         c = fdtochan(&current->open_files, fd, -1, 1, 1);
557         if (waserror()) {
558                 cclose(c);
559                 nexterror();
560         }
561         n = devtab[c->type].wstat(c, buf, n);
562         poperror();
563         cclose(c);
564
565         poperror();
566         return n;
567 }
568
569 long bindmount(struct chan *c, char *old, int flag, char *spec)
570 {
571         ERRSTACK(1);
572         int ret;
573         struct chan *c1;
574
575         if (flag > MMASK || (flag & MORDER) == (MBEFORE | MAFTER))
576                 error(Ebadarg);
577
578         c1 = namec(old, Amount, 0, 0);
579         if (waserror()) {
580                 cclose(c1);
581                 nexterror();
582         }
583         ret = cmount(c, c1, flag, spec);
584
585         poperror();
586         cclose(c1);
587         return ret;
588 }
589
590 int sysbind(char *new, char *old, int flags)
591 {
592         ERRSTACK(2);
593         long r;
594         struct chan *c0;
595
596         if (waserror()) {
597                 poperror();
598                 return -1;
599         }
600
601         c0 = namec(new, Abind, 0, 0);
602         if (waserror()) {
603                 cclose(c0);
604                 nexterror();
605         }
606         r = bindmount(c0, old, flags, "");
607         poperror();
608         cclose(c0);
609
610         poperror();
611         return r;
612 }
613
614 int sysmount(int fd, int afd, char *old, int flags, char *spec)
615 {
616         ERRSTACK(1);
617         long r;
618         volatile struct {
619                 struct chan *c;
620         } c0;
621         volatile struct {
622                 struct chan *c;
623         } bc;
624         volatile struct {
625                 struct chan *c;
626         } ac;
627         struct mntparam mntparam;
628
629         ac.c = NULL;
630         bc.c = NULL;
631         c0.c = NULL;
632         if (waserror()) {
633                 cclose(ac.c);
634                 cclose(bc.c);
635                 cclose(c0.c);
636                 poperror();
637                 return -1;
638         }
639         bc.c = fdtochan(&current->open_files, fd, ORDWR, 0, 1);
640         if (afd >= 0)
641                 ac.c = fdtochan(&current->open_files, afd, ORDWR, 0, 1);
642         mntparam.chan = bc.c;
643         mntparam.authchan = ac.c;
644         mntparam.spec = spec;
645         mntparam.flags = flags;
646         c0.c = devtab[devno('M', 0)].attach((char *)&mntparam);
647
648         r = bindmount(c0.c, old, flags, spec);
649         poperror();
650         cclose(ac.c);
651         cclose(bc.c);
652         cclose(c0.c);
653
654         return r;
655 }
656
657 int sysunmount(char *src_path, char *onto_path)
658 {
659         ERRSTACK(1);
660         volatile struct {
661                 struct chan *c;
662         } cmount;
663         volatile struct {
664                 struct chan *c;
665         } cmounted;
666
667         cmount.c = NULL;
668         cmounted.c = NULL;
669         if (waserror()) {
670                 cclose(cmount.c);
671                 cclose(cmounted.c);
672                 poperror();
673                 return -1;
674         }
675
676         cmount.c = namec(onto_path, Amount, 0, 0);
677         if (src_path != NULL && src_path[0] != '\0') {
678                 /*
679                  * This has to be namec(..., Aopen, ...) because
680                  * if arg[0] is something like /srv/cs or /fd/0,
681                  * opening it is the only way to get at the real
682                  * Chan underneath.
683                  */
684                 cmounted.c = namec(src_path, Aopen, OREAD, 0);
685         }
686
687         cunmount(cmount.c, cmounted.c);
688         poperror();
689         cclose(cmount.c);
690         cclose(cmounted.c);
691         return 0;
692 }
693
694 int sysopen(char *path, int vfs_flags)
695 {
696         ERRSTACK(2);
697         int fd;
698         struct chan *c;
699
700         if (waserror()) {
701                 poperror();
702                 return -1;
703         }
704
705         openmode(vfs_flags);    /* error check only */
706         c = namec(path, Aopen, vfs_flags, 0);
707         if (waserror()) {
708                 cclose(c);
709                 nexterror();
710         }
711         fd = newfd(c, vfs_flags);
712         if (fd < 0)
713                 error(Enofd);
714         poperror();
715
716         poperror();
717         return fd;
718 }
719
720 long unionread(struct chan *c, void *va, long n)
721 {
722         ERRSTACK(1);
723         int i;
724         long nr;
725         struct mhead *m;
726         struct mount *mount;
727
728         qlock(&c->umqlock);
729         m = c->umh;
730         rlock(&m->lock);
731         mount = m->mount;
732         /* bring mount in sync with c->uri and c->umc */
733         for (i = 0; mount != NULL && i < c->uri; i++)
734                 mount = mount->next;
735
736         nr = 0;
737         while (mount != NULL) {
738                 /* Error causes component of union to be skipped */
739                 if (mount->to) {
740                         /* normally we want to discard the error, but for our ghetto kdirent
741                          * hack, we need to repeat unionread if we saw a Eshort */
742                         if (waserror()) {
743                                 if (!strcmp(current_errstr(), Eshort)) {
744                                         runlock(&m->lock);
745                                         qunlock(&c->umqlock);
746                                         nexterror();
747                                 }
748                                 /* poperror done below for either branch */
749                         } else {
750                                 if (c->umc == NULL) {
751                                         c->umc = cclone(mount->to);
752                                         c->umc = devtab[c->umc->type].open(c->umc, OREAD);
753                                 }
754
755                                 nr = devtab[c->umc->type].read(c->umc, va, n, c->umc->offset);
756                                 if (nr < 0)
757                                         nr = 0; /* dev.c can return -1 */
758                                 c->umc->offset += nr;
759                         }
760                         poperror();     /* pop regardless */
761                 }
762                 if (nr > 0)
763                         break;
764
765                 /* Advance to next element */
766                 c->uri++;
767                 if (c->umc) {
768                         cclose(c->umc);
769                         c->umc = NULL;
770                 }
771                 mount = mount->next;
772         }
773         runlock(&m->lock);
774         qunlock(&c->umqlock);
775         return nr;
776 }
777
778 static void unionrewind(struct chan *c)
779 {
780         qlock(&c->umqlock);
781         c->uri = 0;
782         if (c->umc) {
783                 cclose(c->umc);
784                 c->umc = NULL;
785         }
786         qunlock(&c->umqlock);
787 }
788
789 static long rread(int fd, void *va, long n, int64_t * offp)
790 {
791         ERRSTACK(3);
792         int dir;
793         struct chan *c;
794         int64_t off;
795
796         /* dirty dirent hack */
797         void *real_va = va;
798
799         if (waserror()) {
800                 poperror();
801                 return -1;
802         }
803
804         c = fdtochan(&current->open_files, fd, OREAD, 1, 1);
805         if (waserror()) {
806                 cclose(c);
807                 nexterror();
808         }
809
810         if (n < 0)
811                 error(Etoosmall);
812
813         dir = c->qid.type & QTDIR;
814
815         /* kdirent hack: userspace is expecting kdirents, but all of 9ns
816          * produces Ms.  Just save up what we don't use and append the
817          * new stuff later. Allocate DIRREADSIZE bytes for that purpose.
818          */
819         if (dir) {
820                 int amt;
821                 /* expecting only one dirent at a time, o/w we're busted */
822                 assert(n >= sizeof(struct kdirent));
823                 if (!c->buf) {
824                         c->buf=kmalloc(DIRREADSIZE, KMALLOC_WAIT);
825                         c->bufused = 0;
826                 }
827                 /* Attempt to extract an M, in case there was some already */
828                 amt = convM2kdirent(c->buf, c->bufused, real_va, 0);
829                 if (amt) {
830                         c->bufused -= amt;
831                         memmove(c->buf, c->buf + amt, c->bufused);
832                         n = sizeof(struct kdirent);
833                         goto out;
834                 }
835                 /* debugging */
836                 if (waserror()) {
837                         printk("Well, sysread of a dir sucks.%s \n", current_errstr());
838                         nexterror();
839                 }
840                 va = c->buf + c->bufused;
841                 n = DIRREADSIZE - c->bufused;
842         }
843
844         /* this is the normal plan9 read */
845         if (dir && c->umh)
846                 n = unionread(c, va, n);
847         else {
848                 if (offp == NULL) {
849                         spin_lock(&c->lock);    /* lock for int64_t assignment */
850                         off = c->offset;
851                         spin_unlock(&c->lock);
852                 } else
853                         off = *offp;
854                 if (off < 0)
855                         error(Enegoff);
856                 if (off == 0) {
857                         if (offp == NULL) {
858                                 spin_lock(&c->lock);
859                                 c->offset = 0;
860                                 c->dri = 0;
861                                 spin_unlock(&c->lock);
862                         }
863                         unionrewind(c);
864                 }
865                 if (! c->ateof) {
866                         n = devtab[c->type].read(c, va, n, off);
867                         if (n == 0 && dir)
868                                 c->ateof = 1;
869                 } else {
870                         n = 0;
871                 }
872                 spin_lock(&c->lock);
873                 c->offset += n;
874                 spin_unlock(&c->lock);
875         }
876
877         /* dirty kdirent hack */
878         if (dir) {
879                 int amt;
880                 c->bufused = c->bufused + n;
881                 /* extract an M from the front, then shift the remainder back */
882                 amt = convM2kdirent(c->buf, c->bufused, real_va, 0);
883                 c->bufused -= amt;
884                 memmove(c->buf, c->buf + amt, c->bufused);
885                 n = amt ? sizeof(struct kdirent) : 0;
886                 poperror();     /* matching our debugging waserror */
887         }
888
889 out:
890         poperror();
891         cclose(c);
892
893         poperror();
894         return n;
895 }
896
897 /* Reads exactly n bytes from chan c, starting at its offset.  Can block, but if
898  * we get 0 back too soon (EOF or error), then we'll error out with Eshort.
899  * That might need a little work - if there was a previous error, then we
900  * clobbered it and only know Eshort but not why we completed early. */
901 void read_exactly_n(struct chan *c, void *vp, long n)
902 {
903         char *p;
904         long nn;
905         int total = 0, want = n;
906
907         p = vp;
908         while (n > 0) {
909                 nn = devtab[c->type].read(c, p, n, c->offset);
910                 printd("readn: Got %d@%lld\n", nn, c->offset);
911                 if (nn == 0)
912                         error("%s: wanted %d, got %d", Eshort, want, total);
913                 spin_lock(&c->lock);
914                 c->offset += nn;
915                 spin_unlock(&c->lock);
916                 p += nn;
917                 n -= nn;
918                 total += nn;
919         }
920 }
921
922 long sysread(int fd, void *va, long n)
923 {
924         return rread(fd, va, n, NULL);
925 }
926
927 long syspread(int fd, void *va, long n, int64_t off)
928 {
929         return rread(fd, va, n, &off);
930 }
931
932 int sysremove(char *path)
933 {
934         ERRSTACK(2);
935         struct chan *c;
936
937         if (waserror()) {
938                 poperror();
939                 return -1;
940         }
941
942         c = namec(path, Aremove, 0, 0);
943         if (waserror()) {
944                 c->type = -1;   /* see below */
945                 cclose(c);
946                 nexterror();
947         }
948         devtab[c->type].remove(c);
949         /*
950          * Remove clunks the fid, but we need to recover the Chan
951          * so fake it up.  -1 aborts the dev's close.
952          */
953         c->type = -1;
954         poperror();
955         cclose(c);
956
957         poperror();
958         return 0;
959 }
960
961 int64_t sysseek(int fd, int64_t off, int whence)
962 {
963         ERRSTACK(2);
964         struct dir *dir;
965         struct chan *c;
966
967         if (waserror()) {
968                 poperror();
969                 return -1;
970         }
971
972         c = fdtochan(&current->open_files, fd, -1, 1, 1);
973         if (waserror()) {
974                 cclose(c);
975                 nexterror();
976         }
977
978         if (devtab[c->type].dc == '|')
979                 error(Eisstream);
980
981         switch (whence) {
982                 case 0:
983                         if (c->qid.type & QTDIR) {
984                                 if (off != 0)
985                                         error(Eisdir);
986                                 unionrewind(c);
987                         } else if (off < 0)
988                                 error(Enegoff);
989                         spin_lock(&c->lock);    /* lock for int64_t assignment */
990                         c->offset = off;
991                         spin_unlock(&c->lock);
992                         break;
993
994                 case 1:
995                         if (c->qid.type & QTDIR)
996                                 error(Eisdir);
997                         spin_lock(&c->lock);    /* lock for read/write update */
998                         off += c->offset;
999                         if (off < 0) {
1000                                 spin_unlock(&c->lock);
1001                                 error(Enegoff);
1002                         }
1003                         c->offset = off;
1004                         spin_unlock(&c->lock);
1005                         break;
1006
1007                 case 2:
1008                         if (c->qid.type & QTDIR)
1009                                 error(Eisdir);
1010                         dir = chandirstat(c);
1011                         if (dir == NULL)
1012                                 error("internal error: stat error in seek");
1013                         off += dir->length;
1014                         kfree(dir);
1015                         if (off < 0)
1016                                 error(Enegoff);
1017                         spin_lock(&c->lock);    /* lock for read/write update */
1018                         c->offset = off;
1019                         spin_unlock(&c->lock);
1020                         break;
1021
1022                 default:
1023                         error(Ebadarg);
1024                         break;
1025         }
1026         poperror();
1027         c->dri = 0;
1028         cclose(c);
1029         poperror();
1030         return off;
1031 }
1032
1033 void validstat(uint8_t * s, int n, int slashok)
1034 {
1035         
1036         int m;
1037         char buf[64];
1038
1039         if (statcheck(s, n) < 0)
1040                 error(Ebadstat);
1041         /* verify that name entry is acceptable */
1042         s += STATFIXLEN - 4 * BIT16SZ;  /* location of first string */
1043         /*
1044          * s now points at count for first string.
1045          * if it's too long, let the server decide; this is
1046          * only for his protection anyway. otherwise
1047          * we'd have to allocate and waserror.
1048          */
1049         m = GBIT16(s);
1050         s += BIT16SZ;
1051         if (m + 1 > sizeof buf) {
1052                 return;
1053         }
1054         memmove(buf, s, m);
1055         buf[m] = '\0';
1056         /* name could be '/' */
1057         if (strcmp(buf, "/") != 0)
1058                 validname(buf, slashok);
1059 }
1060
1061 int sysfstat(int fd, uint8_t *buf, int n)
1062 {
1063         ERRSTACK(2);
1064         struct chan *c;
1065
1066         if (waserror()) {
1067                 poperror();
1068                 return -1;
1069         }
1070
1071         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1072         if (waserror()) {
1073                 cclose(c);
1074                 nexterror();
1075         }
1076         devtab[c->type].stat(c, buf, n);
1077
1078         poperror();
1079         cclose(c);
1080
1081         poperror();
1082         return n;
1083 }
1084
1085 int sysfstatakaros(int fd, struct kstat *ks)
1086 {
1087         
1088         int n = 4096;
1089         uint8_t *buf;
1090         buf = kmalloc(n, KMALLOC_WAIT);
1091         n = sysfstat(fd, buf, n);
1092         if (n > 0) {
1093                 convM2kstat(buf, n, ks);
1094                 n = 0;
1095         }
1096         kfree(buf);
1097         return n;
1098 }
1099
1100 int sysstat(char *path, uint8_t *buf, int n)
1101 {
1102         ERRSTACK(2);
1103         struct chan *c;
1104
1105         if (waserror()) {
1106                 poperror();
1107                 return -1;
1108         }
1109
1110         c = namec(path, Aaccess, 0, 0);
1111         if (waserror()) {
1112                 cclose(c);
1113                 nexterror();
1114         }
1115         devtab[c->type].stat(c, buf, n);
1116         poperror();
1117         cclose(c);
1118
1119         poperror();
1120
1121         return n;
1122 }
1123
1124 int sysstatakaros(char *path, struct kstat *ks)
1125 {
1126         
1127         int n = 4096;
1128         uint8_t *buf;
1129         buf = kmalloc(n, KMALLOC_WAIT);
1130         n = sysstat(path, buf, n);
1131         if (n > 0) {
1132                 convM2kstat(buf, n, ks);
1133                 n = 0;
1134         }
1135         kfree(buf);
1136         return n;
1137 }
1138
1139 static long rwrite(int fd, void *va, long n, int64_t * offp)
1140 {
1141         ERRSTACK(3);
1142         struct chan *c;
1143         struct dir *dir;
1144         int64_t off;
1145         long m;
1146
1147         if (waserror()) {
1148                 poperror();
1149                 return -1;
1150         }
1151         c = fdtochan(&current->open_files, fd, OWRITE, 1, 1);
1152         if (waserror()) {
1153                 cclose(c);
1154                 nexterror();
1155         }
1156         if (c->qid.type & QTDIR)
1157                 error(Eisdir);
1158
1159         if (n < 0)
1160                 error(Etoosmall);
1161
1162         if (offp == NULL) {
1163                 /* append changes the offset to the end, and even if we fail later, this
1164                  * change will persist */
1165                 if (c->flag & CAPPEND) {
1166                         dir = chandirstat(c);
1167                         if (!dir)
1168                                 error("internal error: stat error in append write");
1169                         spin_lock(&c->lock);    /* legacy lock for int64 assignment */
1170                         c->offset = dir->length;
1171                         spin_unlock(&c->lock);
1172                         kfree(dir);
1173                 }
1174                 spin_lock(&c->lock);
1175                 off = c->offset;
1176                 c->offset += n;
1177                 spin_unlock(&c->lock);
1178         } else
1179                 off = *offp;
1180
1181         if (waserror()) {
1182                 if (offp == NULL) {
1183                         spin_lock(&c->lock);
1184                         c->offset -= n;
1185                         spin_unlock(&c->lock);
1186                 }
1187                 nexterror();
1188         }
1189         if (off < 0)
1190                 error(Enegoff);
1191         m = devtab[c->type].write(c, va, n, off);
1192         poperror();
1193
1194         if (offp == NULL && m < n) {
1195                 spin_lock(&c->lock);
1196                 c->offset -= n - m;
1197                 spin_unlock(&c->lock);
1198         }
1199
1200         poperror();
1201         cclose(c);
1202
1203         poperror();
1204         return n;
1205 }
1206
1207 long syswrite(int fd, void *va, long n)
1208 {
1209         return rwrite(fd, va, n, NULL);
1210 }
1211
1212 long syspwrite(int fd, void *va, long n, int64_t off)
1213 {
1214         return rwrite(fd, va, n, &off);
1215 }
1216
1217 int syswstat(char *path, uint8_t * buf, int n)
1218 {
1219         ERRSTACK(2);
1220         struct chan *c;
1221
1222         if (waserror()) {
1223                 poperror();
1224                 return -1;
1225         }
1226
1227         validstat(buf, n, 0);
1228         c = namec(path, Aaccess, 0, 0);
1229         if (waserror()) {
1230                 cclose(c);
1231                 nexterror();
1232         }
1233         n = devtab[c->type].wstat(c, buf, n);
1234         poperror();
1235         cclose(c);
1236
1237         poperror();
1238         return n;
1239 }
1240
1241 struct dir *chandirstat(struct chan *c)
1242 {
1243         ERRSTACK(1);
1244         struct dir *d;
1245         uint8_t *buf;
1246         int n, nd, i;
1247
1248         nd = DIRSIZE;
1249         for (i = 0; i < 2; i++) {       /* should work by the second try */
1250                 d = kzmalloc(sizeof(struct dir) + nd, 0);
1251                 buf = (uint8_t *) & d[1];
1252                 if (waserror()) {
1253                         kfree(d);
1254                         poperror();
1255                         return NULL;
1256                 }
1257                 n = devtab[c->type].stat(c, buf, nd);
1258                 poperror();
1259                 if (n < BIT16SZ) {
1260                         kfree(d);
1261                         return NULL;
1262                 }
1263                 nd = GBIT16((uint8_t *) buf) + BIT16SZ; /* size needed to store whole stat buffer including count */
1264                 if (nd <= n) {
1265                         convM2D(buf, n, d, (char *)&d[1]);
1266                         return d;
1267                 }
1268                 /* else sizeof(Dir)+nd is plenty */
1269                 kfree(d);
1270         }
1271         return NULL;
1272
1273 }
1274
1275 struct dir *sysdirstat(char *name)
1276 {
1277         ERRSTACK(2);
1278         struct chan *c;
1279         struct dir *d;
1280
1281         if (waserror()) {
1282                 poperror();
1283                 return NULL;
1284         }
1285
1286         c = namec(name, Aaccess, 0, 0);
1287         if (waserror()) {
1288                 cclose(c);
1289                 nexterror();
1290         }
1291         d = chandirstat(c);
1292         poperror();
1293         cclose(c);
1294
1295         poperror();
1296         return d;
1297 }
1298
1299 struct dir *sysdirfstat(int fd)
1300 {
1301         ERRSTACK(2);
1302         struct chan *c;
1303         struct dir *d;
1304
1305         if (waserror()) {
1306                 poperror();
1307                 return NULL;
1308         }
1309
1310         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1311         if (waserror()) {
1312                 cclose(c);
1313                 nexterror();
1314         }
1315         d = chandirstat(c);
1316         poperror();
1317         cclose(c);
1318
1319         poperror();
1320         return d;
1321 }
1322
1323 int sysdirwstat(char *name, struct dir *dir)
1324 {
1325         
1326         uint8_t *buf;
1327         int r;
1328
1329         r = sizeD2M(dir);
1330         buf = kzmalloc(r, 0);
1331         convD2M(dir, buf, r);
1332         r = syswstat(name, buf, r);
1333         kfree(buf);
1334         return r < 0 ? r : 0;
1335 }
1336
1337 int sysdirfwstat(int fd, struct dir *dir)
1338 {
1339         
1340         uint8_t *buf;
1341         int r;
1342
1343         r = sizeD2M(dir);
1344         buf = kzmalloc(r, 0);
1345         convD2M(dir, buf, r);
1346         r = sysfwstat(fd, buf, r);
1347         kfree(buf);
1348         return r < 0 ? r : 0;
1349 }
1350
1351 static long dirpackage(uint8_t * buf, long ts, struct kdirent **d)
1352 {
1353         
1354         char *s;
1355         long ss, i, n, nn, m = 0;
1356
1357         *d = NULL;
1358         if (ts <= 0) {
1359                 return ts;
1360         }
1361
1362         /*
1363          * first find number of all stats, check they look like stats, & size all associated strings
1364          */
1365         ss = 0;
1366         n = 0;
1367         for (i = 0; i < ts; i += m) {
1368                 m = BIT16SZ + GBIT16(&buf[i]);
1369                 if (statcheck(&buf[i], m) < 0)
1370                         break;
1371                 ss += m;
1372                 n++;
1373         }
1374
1375         if (i != ts)
1376                 error("bad directory format");
1377
1378         *d = kzmalloc(n * sizeof(**d) + ss, 0);
1379         if (*d == NULL)
1380                 error(Enomem);
1381
1382         /*
1383          * then convert all buffers
1384          */
1385         s = (char *)*d + n * sizeof(**d);
1386         nn = 0;
1387         for (i = 0; i < ts; i += m) {
1388                 m = BIT16SZ + GBIT16((uint8_t *) & buf[i]);
1389                 if (nn >= n || /*convM2D */ convM2kdirent(&buf[i], m, *d + nn, s) != m) {
1390                         kfree(*d);
1391                         *d = NULL;
1392                         error("bad directory entry");
1393                 }
1394                 nn++;
1395                 s += m;
1396         }
1397
1398         return nn;
1399 }
1400
1401 long sysdirread(int fd, struct kdirent **d)
1402 {
1403         ERRSTACK(2);
1404         uint8_t *buf;
1405         long ts;
1406
1407         *d = NULL;
1408         if (waserror()) {
1409                 poperror();
1410                 return -1;
1411         }
1412         buf = kzmalloc(DIRREADLIM, 0);
1413         if (buf == NULL)
1414                 error(Enomem);
1415         if (waserror()) {
1416                 kfree(buf);
1417                 nexterror();
1418         }
1419         ts = sysread(fd, buf, DIRREADLIM);
1420         if (ts >= 0)
1421                 ts = dirpackage(buf, ts, d);
1422         poperror();
1423         kfree(buf);
1424         poperror();
1425         return ts;
1426 }
1427
1428 int sysiounit(int fd)
1429 {
1430         ERRSTACK(1);
1431         struct chan *c;
1432         int n;
1433
1434         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1435         if (waserror()) {
1436                 cclose(c);
1437                 poperror();
1438                 return 0;       /* n.b. */
1439         }
1440         n = c->iounit;
1441         poperror();
1442         cclose(c);
1443         return n;
1444 }
1445
1446 /* Notes on concurrency:
1447  * - Can't hold spinlocks while we call cclose, since it might sleep eventually.
1448  * - We're called from proc_destroy, so we could have concurrent openers trying
1449  *   to add to the group (other syscalls), hence the "closed" flag.
1450  * - dot and slash chans are dealt with in proc_free.  its difficult to close
1451  *   and zero those with concurrent syscalls, since those are a source of krefs.
1452  * - the memory is freed in proc_free().  need to wait to do it, since we can
1453  *   have concurrent accesses to fgrp before free.
1454  * - Once we lock and set closed, no further additions can happen.  To simplify
1455  *   our closes, we also allow multiple calls to this func (though that should
1456  *   never happen with the current code). */
1457 void close_9ns_files(struct proc *p, bool only_cloexec)
1458 {
1459         
1460         struct fgrp *f = p->open_files.fgrp;
1461
1462         spin_lock(&f->lock);
1463         if (f->closed) {
1464                 spin_unlock(&f->lock);
1465                 warn("Unexpected double-close");
1466                 return;
1467         }
1468         if (!only_cloexec)
1469                 f->closed = TRUE;
1470         spin_unlock(&f->lock);
1471
1472         /* maxfd is a legit val, not a +1 */
1473         for (int i = 0; i <= f->maxfd; i++) {
1474                 if (!f->fd[i])
1475                         continue;
1476                 if (only_cloexec && !(f->fd[i]->flag & CCEXEC))
1477                         continue;
1478                 cclose(f->fd[i]);
1479                 f->fd[i] = 0;
1480         }
1481 }
1482
1483 void print_chaninfo(struct chan *c)
1484 {
1485         
1486         char buf[64] = { 0 };
1487         bool has_dev = c->type != -1;
1488         if (has_dev && !devtab[c->type].chaninfo) {
1489                 printk("Chan type %d has no chaninfo!\n", c->type);
1490                 has_dev = FALSE;
1491         }
1492         printk("Chan pathname: %s ref %d, Dev: %s, Devinfo: %s",
1493                    c->name ? c->name->s : "no cname",
1494                    kref_refcnt(&c->ref),
1495                    has_dev ? devtab[c->type].name : "no dev",
1496                    has_dev ? devtab[c->type].chaninfo(c, buf, sizeof(buf)) : "");
1497         if (!has_dev)
1498                 printk("qid.path: %p\n", c->qid.path);
1499         printk("\n");
1500 }
1501
1502 void print_9ns_files(struct proc *p)
1503 {
1504         
1505         struct fgrp *f = p->open_files.fgrp;
1506         spin_lock(&f->lock);
1507         printk("9ns files for proc %d:\n", p->pid);
1508         /* maxfd is a legit val, not a +1 */
1509         for (int i = 0; i <= f->maxfd; i++) {
1510                 if (!f->fd[i])
1511                         continue;
1512                 printk("\t9fs %4d, ", i);
1513                 print_chaninfo(f->fd[i]);
1514         }
1515         spin_unlock(&f->lock);
1516 }
1517
1518 /* TODO: 9ns ns inheritance flags: Shared, copied, or empty.  Looks like we're
1519  * copying the fgrp, and sharing the pgrp. */
1520 int plan9setup(struct proc *new_proc, struct proc *parent, int flags)
1521 {
1522         
1523         struct proc *old_current;
1524         struct kref *new_dot_ref;
1525         ERRSTACK(1);
1526         if (waserror()) {
1527                 printk("plan9setup failed, %s\n", current_errstr());
1528                 poperror();
1529                 return -1;
1530         }
1531         if (!parent) {
1532                 /* We are probably spawned by the kernel directly, and have no parent to
1533                  * inherit from.  Be sure to set up fgrp/pgrp before calling namec().
1534                  *
1535                  * TODO: One problem is namec wants a current set for things like
1536                  * genbuf.  So we'll use new_proc for this bootstrapping.  Note
1537                  * switch_to() also loads the cr3. */
1538                 new_proc->open_files.fgrp = newfgrp();
1539                 new_proc->pgrp = newpgrp();
1540                 old_current = switch_to(new_proc);
1541                 new_proc->slash = namec("#r", Atodir, 0, 0);
1542                 if (!new_proc->slash)
1543                         panic("no root device");
1544                 switch_back(new_proc, old_current);
1545                 /* Want the name to be "/" instead of "#r" */
1546                 cnameclose(new_proc->slash->name);
1547                 new_proc->slash->name = newcname("/");
1548                 new_proc->dot = cclone(new_proc->slash);
1549                 poperror();
1550                 return 0;
1551         }
1552         /* When we use the old fgrp, we have copy semantics: do not change this
1553          * without revisiting proc_destroy, close_9ns_files, and closefgrp. */
1554         if (flags & PROC_DUP_FGRP)
1555                 new_proc->open_files.fgrp = dupfgrp(new_proc, parent->open_files.fgrp);
1556         else
1557                 new_proc->open_files.fgrp = newfgrp();
1558         /* Shared semantics */
1559         kref_get(&parent->pgrp->ref, 1);
1560         new_proc->pgrp = parent->pgrp;
1561         /* copy semantics on / and . (doesn't make a lot of sense in akaros o/w) */
1562         /* / should never disappear while we hold a ref to parent */
1563         chan_incref(parent->slash);
1564         new_proc->slash = parent->slash;
1565         /* dot could change concurrently, and we could fail to gain a ref if whoever
1566          * decref'd dot triggered the release.  if that did happen, new_proc->dot
1567          * should update and we can try again. */
1568         while (!(new_dot_ref = kref_get_not_zero(&parent->dot->ref, 1)))
1569                 cpu_relax();
1570         /* And now, we can't trust parent->dot, and need to determine our dot from
1571          * the ref we obtained. */
1572         new_proc->dot = container_of(new_dot_ref, struct chan, ref);
1573         poperror();
1574         return 0;
1575 }
1576
1577 /* Open flags, create modes, access types, file flags, and all that...
1578  *
1579  * there are a bunch of things here:
1580  *              1) file creation flags (e.g. O_TRUNC)
1581  *              2) file status flags (e.g. O_APPEND)
1582  *              3) file open modes (e.g. O_RDWR)
1583  *              4) file descriptor flags (e.g. CLOEXEC)
1584  *              5) file creation mode (e.g. S_IRWXU)
1585  * the 1-4 are passed in via open's vfs_flags, and the 5 via mode only when
1586  * O_CREATE is set.
1587  *
1588  * file creation flags (1) only matter when creating, but aren't permanent.
1589  * O_EXCL, O_DIRECTORY, O_TRUNC, etc.
1590  *
1591  * file status flags (2) are per struct file/chan.  stuff like O_APPEND,
1592  * O_ASYNC, etc.  we convert those to an internal flag bit and store in c->flags
1593  *
1594  * the open mode (3) matters for a given FD/chan (chan->mode), and should be
1595  * stored in the chan. (c->mode) stuff like O_RDONLY.
1596  *
1597  * the file descriptor flags (4) clearly are in the FD.  note that the same
1598  * file/chan can be opened by two different FDs, with different flags.  the only
1599  * one anyone uses is CLOEXEC.  while exec may not last long in akaros, i can
1600  * imagine similar "never pass to children" flags/meanings.
1601  *
1602  * the file creation mode (5) matters for the device's permissions; given this,
1603  * it should be stored in the device/inode.  ACLs fall under this category.
1604  *
1605  * finally, only certain categories can be edited afterwards: file status flags
1606  * (2), FD flags (4), and file permissions (5). */
1607 int fd_getfl(int fd)
1608 {
1609         ERRSTACK(1);
1610         struct chan *c;
1611         int ret;
1612
1613         if (waserror()) {
1614                 poperror();
1615                 return -1;
1616         }
1617         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1618
1619         ret = c->mode;
1620         ret |= c->flag & CEXTERNAL_FLAGS;
1621
1622         cclose(c);
1623         poperror();
1624         return ret;
1625 }
1626
1627 static bool cexternal_flags_differ(int set1, int set2, int flags)
1628 {
1629         flags &= CEXTERNAL_FLAGS;
1630         return (set1 & flags) ^ (set2 & flags);
1631 }
1632
1633 int fd_setfl(int fd, int flags)
1634 {
1635         ERRSTACK(1);
1636         struct chan *c;
1637
1638         if (waserror()) {
1639                 poperror();
1640                 return -1;
1641         }
1642         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1643         if (cexternal_flags_differ(flags, c->flag, O_CLOEXEC)) {
1644                 /* TODO: The whole CCEXEC / O_CLOEXEC on 9ns needs work */
1645                 set_errno(EINVAL);
1646                 error("can't toggle O_CLOEXEC with setfl");
1647         }
1648         if (cexternal_flags_differ(flags, c->flag, O_NONBLOCK)) {
1649                 /* If we want to let them toggle NONBLOCK, it'd require a device op */
1650                 set_errno(EINVAL);
1651                 error("can't set O_NONBLOCK, use a device-specific ctl command");
1652         }
1653         c->flag = (c->flag & ~CEXTERNAL_FLAGS) | (flags & CEXTERNAL_FLAGS);
1654         cclose(c);
1655         poperror();
1656         return 0;
1657 }