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