Change Chan flags to match open() file flags
authorBarret Rhoden <brho@cs.berkeley.edu>
Sun, 19 Jul 2015 13:35:19 +0000 (09:35 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 24 Jul 2015 07:05:13 +0000 (03:05 -0400)
Like with many parts of the VFS and 9ns, certain flags hold different
sets of flags.  omode has the mode (O_RDWR) as well as file/chan flags.
c->flag has some internal flags, such as COPEN, as well as some
file/chan flags that came in from open().

Now, the chan flags are explicitly split between these groups, such that
the internal and external flags are separate.  Further, the external
flags use the same values with 9ns as are used in the kernel interface.
This way, we can more easily set and get the flags.

Note that this also fixes a slight bug in setfl where we were not
clearing O_APPEND, in case someone was trying to toggle it off.

9ns CLOEXEC still needs some work.  I don't know think the device needs
to know about it, but I could be wrong.

kern/include/ns.h
kern/src/ns/chan.c
kern/src/ns/sysfile.c

index dd289dc..753d77e 100644 (file)
@@ -303,14 +303,19 @@ enum {
        Aremove,                                        /* will be removed by caller */
        Acreatechan,                                    /* return a chan for a create request. for sysrename. */
 
-       COPEN = 0x0001,                         /* for i/o */
-       CMSG = 0x0002,  /* the message channel for a mount */
-       CCEXEC = 0x0008,        /* close on exec */
-       CFREE = 0x0010, /* not in use */
-       CRCLOSE = 0x0020,       /* remove on close */
-       CCACHE = 0x0080,        /* client cache */
-       /* file/chan status flags, affected by setfl and reported in getfl */
-       CAPPEND = 0x0100,       /* append on write */
+       /* internal chan flags, used by the kernel only */
+       COPEN =                 0x0001, /* for i/o */
+       CMSG =                  0x0002, /* the message channel for a mount */
+       CFREE =                 0x0004, /* not in use */
+       CCACHE =                0x0008, /* client cache */
+       CINTERNAL_FLAGS = (COPEN | CMSG | CFREE | CCACHE),
+
+       /* chan/file flags, setably via open and sometimes fcntl/setfl.  these are
+        * the internal names used in some parts of 9ns */
+       CCEXEC =                O_CLOEXEC,      /* (prob should be on the FD, 9ns has it here) */
+       CRCLOSE =               O_REMCLO,       /* remove on close (also, maybe should be on FD) */
+       CAPPEND =               O_APPEND,       /* append on write */
+       CEXTERNAL_FLAGS = (CCEXEC | CRCLOSE | CAPPEND),
 };
 
 #define NS_IPCK_SHIFT  2
index 6deeaa6..f108f6c 100644 (file)
@@ -971,6 +971,8 @@ struct chan *namec(char *aname, int amode, int omode, uint32_t perm)
        char *name;
        // Rune r;
 
+       static_assert(!(CINTERNAL_FLAGS & CEXTERNAL_FLAGS));
+
        name = aname;
        if (name[0] == '\0')
                error("empty file name");
@@ -1164,14 +1166,10 @@ Open:
 
                                        if (omode == OEXEC)
                                                c->flag &= ~CCACHE;
-                                       /* here is where convert omode/vfs flags to c->flags */
-                                       if (omode & O_APPEND)
-                                               c->flag |= CAPPEND;
-                                       // CEXEC should be in the FD, not the chan, right?
-                                       if (omode & OCEXEC)
-                                               c->flag |= CCEXEC;
-                                       if (omode & ORCLOSE)
-                                               c->flag |= CRCLOSE;
+                                       /* here is where convert omode/vfs flags to c->flags.
+                                        * careful, O_CLOEXEC and O_REMCLO are in there.  might need
+                                        * to change that. */
+                                       c->flag |= omode & CEXTERNAL_FLAGS;
                                        c = devtab[c->type].open(c, omode & ~OCEXEC);
                                        break;
                        }
index 4696807..f71fdb4 100644 (file)
@@ -1614,14 +1614,19 @@ int fd_getfl(int fd)
        c = fdtochan(current->fgrp, fd, -1, 0, 1);
 
        ret = c->mode;
-       if (c->flag & CAPPEND)
-               ret |= O_APPEND;
+       ret |= c->flag & CEXTERNAL_FLAGS;
 
        cclose(c);
        poperror();
        return ret;
 }
 
+static bool cexternal_flags_differ(int set1, int set2, int flags)
+{
+       flags &= CEXTERNAL_FLAGS;
+       return (set1 & flags) ^ (set2 & flags);
+}
+
 int fd_setfl(int fd, int flags)
 {
        ERRSTACK(1);
@@ -1632,10 +1637,12 @@ int fd_setfl(int fd, int flags)
                return -1;
        }
        c = fdtochan(current->fgrp, fd, -1, 0, 1);
-
-       if (flags & O_APPEND)
-               c->flag |= CAPPEND;
-
+       if (cexternal_flags_differ(flags, c->flag, O_CLOEXEC)) {
+               /* TODO: The whole CCEXEC / O_CLOEXEC on 9ns needs work */
+               set_errno(EINVAL);
+               error("can't toggle O_CLOEXEC with setfl");
+       }
+       c->flag = (c->flag & ~CEXTERNAL_FLAGS) | (flags & CEXTERNAL_FLAGS);
        cclose(c);
        poperror();
        return 0;