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