Implement sys_open() with sys_openat() (XCC)
[akaros.git] / kern / src / ns / sysfile.c
index 511fefc..af0224c 100644 (file)
@@ -335,8 +335,8 @@ int syspipe(int fd[2])
        struct chan *c[2];
        static char *names[] = { "data", "data1" };
 
-       d = &devtab[devno('|', 0)];
-       c[0] = namec("#|", Atodir, 0, 0);
+       d = &devtab[devno("pipe", 0)];
+       c[0] = 0;
        c[1] = 0;
        fd[0] = -1;
        fd[1] = -1;
@@ -356,10 +356,11 @@ int syspipe(int fd[2])
                poperror();
                return -1;
        }
+       c[0] = namec("#pipe", Atodir, 0, 0);
        c[1] = cclone(c[0]);
-       if (walk(&c[0], &names[0], 1, 1, NULL) < 0)
+       if (walk(&c[0], &names[0], 1, FALSE, NULL) < 0)
                error(Egreg);
-       if (walk(&c[1], &names[1], 1, 1, NULL) < 0)
+       if (walk(&c[1], &names[1], 1, FALSE, NULL) < 0)
                error(Egreg);
        c[0] = d->open(c[0], O_RDWR);
        c[1] = d->open(c[1], O_RDWR);
@@ -474,7 +475,7 @@ int sysmount(int fd, int afd, char *old, int flags, char *spec)
        mntparam.authchan = ac.c;
        mntparam.spec = spec;
        mntparam.flags = flags;
-       c0.c = devtab[devno('M', 0)].attach((char *)&mntparam);
+       c0.c = devtab[devno("mnt", 0)].attach((char *)&mntparam);
 
        r = bindmount(c0.c, old, flags, spec);
        poperror();
@@ -522,32 +523,40 @@ int sysunmount(char *src_path, char *onto_path)
        return 0;
 }
 
-int sysopen(char *path, int vfs_flags)
+int sysopenat(int fromfd, char *path, int vfs_flags)
 {
-       ERRSTACK(2);
+       ERRSTACK(1);
        int fd;
-       struct chan *c;
+       struct chan *c = 0, *from = 0;
 
        if (waserror()) {
+               cclose(c);
                poperror();
                return -1;
        }
-
        openmode(vfs_flags);    /* error check only */
-       c = namec(path, Aopen, vfs_flags, 0);
-       if (waserror()) {
-               cclose(c);
-               nexterror();
+       if ((path[0] == '/') || (fromfd == AT_FDCWD)) {
+               c = namec(path, Aopen, vfs_flags, 0);
+       } else {
+               /* We don't cclose from.  namec_from will convert it to the new chan
+                * during the walk process (c).  It'll probably close from internally,
+                * and give us something new for c.  On error, namec_from will cclose
+                * from. */
+               from = fdtochan(&current->open_files, fromfd, -1, FALSE, TRUE);
+               c = namec_from(from, path, Aopen, vfs_flags, 0);
        }
        fd = newfd(c, vfs_flags);
        if (fd < 0)
                error(Enofd);
        poperror();
-
-       poperror();
        return fd;
 }
 
+int sysopen(char *path, int vfs_flags)
+{
+       return sysopenat(AT_FDCWD, path, vfs_flags);
+}
+
 long unionread(struct chan *c, void *va, long n)
 {
        ERRSTACK(1);
@@ -807,7 +816,9 @@ int64_t sysseek(int fd, int64_t off, int whence)
                nexterror();
        }
 
-       if (devtab[c->type].dc == '|')
+       /* TODO: WTF is this?  Is pipe magically the only device that isn't
+        * seekable? */
+       if (!strcmp(devtab[c->type].name, "pipe"))
                error(Eisstream);
 
        switch (whence) {
@@ -1317,11 +1328,11 @@ int plan9setup(struct proc *new_proc, struct proc *parent, int flags)
                 * switch_to() also loads the cr3. */
                new_proc->pgrp = newpgrp();
                old_current = switch_to(new_proc);
-               new_proc->slash = namec("#r", Atodir, 0, 0);
+               new_proc->slash = namec("#root", Atodir, 0, 0);
                if (!new_proc->slash)
                        panic("no root device");
                switch_back(new_proc, old_current);
-               /* Want the name to be "/" instead of "#r" */
+               /* Want the name to be "/" instead of "#root" */
                cnameclose(new_proc->slash->name);
                new_proc->slash->name = newcname("/");
                new_proc->dot = cclone(new_proc->slash);
@@ -1418,6 +1429,10 @@ int fd_setfl(int fd, int flags)
                set_errno(EINVAL);
                error("can't toggle O_CLOEXEC with setfl");
        }
+       if (cexternal_flags_differ(flags, c->flag, O_PATH)) {
+               set_errno(EINVAL);
+               error("can't toggle O_PATH with setfl");
+       }
        if (cexternal_flags_differ(flags, c->flag, O_NONBLOCK)) {
                /* If we want to let them toggle NONBLOCK, it'd require a device op */
                set_errno(EINVAL);