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