getfl and setfl for 9ns
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 28 Jan 2014 22:45:51 +0000 (14:45 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 28 Jan 2014 22:45:51 +0000 (14:45 -0800)
Check out the comments about fd_getfl() for my overall thoughts on the
matter

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

index 17accae..fdc55c0 100644 (file)
@@ -322,6 +322,8 @@ enum
        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 */
 };
 
 enum
@@ -1018,6 +1020,8 @@ void print_chaninfo(struct chan *ch);
 void print_9ns_files(struct proc *p);
 int plan9setup(struct proc *new_proc, struct proc *parent);
 int iseve(void);
+int fd_getfl(int fd);
+int fd_setfl(int fd, int flags);
 
 static inline int abs(int a)
 {
index 8ceaab5..1f3ff29 100644 (file)
@@ -1175,7 +1175,10 @@ if(c->umh != NULL){
                                c->flag &= ~CCACHE;
 
                        c = devtab[c->type].open(c, omode&~OCEXEC);
-
+                       /* 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)
@@ -1279,6 +1282,8 @@ if(c->umh != NULL){
 
                        devtab[cnew->type].create(cnew, e.elems[e.ARRAY_SIZEs-1], omode&~(OEXCL|OCEXEC), perm);
                        poperror();
+                       if (omode & O_APPEND)
+                               cnew->flag |= CAPPEND;
                        if(omode & OCEXEC)
                                cnew->flag |= CCEXEC;
                        if(omode & ORCLOSE)
index a330b39..4ba2736 100644 (file)
@@ -1440,3 +1440,72 @@ int plan9setup(struct proc *new_proc, struct proc *parent)
        return 0;
 }
 
+/* Open flags, create modes, access types, file flags, and all that...
+ *
+ * there are a bunch of things here:
+ *             1) file creation flags (e.g. O_TRUNC)
+ *             2) file status flags (e.g. O_APPEND)
+ *             3) file open modes (e.g. O_RDWR)
+ *             4) file descriptor flags (e.g. CLOEXEC)
+ *             5) file creation mode (e.g. S_IRWXU)
+ * the 1-4 are passed in via open's vfs_flags, and the 5 via mode only when
+ * O_CREATE is set.
+ *
+ * file creation flags (1) only matter when creating, but aren't permanent.
+ * O_EXCL, O_DIRECTORY, O_TRUNC, etc.
+ *
+ * file status flags (2) are per struct file/chan.  stuff like O_APPEND,
+ * O_ASYNC, etc.  we convert those to an internal flag bit and store in c->flags
+ *
+ * the open mode (3) matters for a given FD/chan (chan->mode), and should be
+ * stored in the chan. (c->mode) stuff like O_RDONLY.
+ *
+ * the file descriptor flags (4) clearly are in the FD.  note that the same
+ * file/chan can be opened by two different FDs, with different flags.  the only
+ * one anyone uses is CLOEXEC.  while exec may not last long in akaros, i can
+ * imagine similar "never pass to children" flags/meanings.
+ *
+ * the file creation mode (5) matters for the device's permissions; given this,
+ * it should be stored in the device/inode.  ACLs fall under this category.
+ *
+ * finally, only certain categories can be edited afterwards: file status flags
+ * (2), FD flags (4), and file permissions (5).        */
+int fd_getfl(int fd)
+{
+       ERRSTACK(1);
+       struct chan *c;
+       int ret;
+
+       if (waserror()) {
+               poperror();
+               return -1;
+       }
+       c = fdtochan(current->fgrp, fd, -1, 0, 1);
+
+       ret = c->mode;
+       if (c->flag & CAPPEND)
+               ret |= O_APPEND;
+
+       cclose(c);
+       poperror();
+       return ret;
+}
+
+int fd_setfl(int fd, int flags)
+{
+       ERRSTACK(1);
+       struct chan *c;
+
+       if (waserror()) {
+               poperror();
+               return -1;
+       }
+       c = fdtochan(current->fgrp, fd, -1, 0, 1);
+
+       if (flags & O_APPEND)
+               c->flag |= CAPPEND;
+
+       cclose(c);
+       poperror();
+       return 0;
+}
index 617d41b..d117643 100644 (file)
@@ -1204,9 +1204,11 @@ intreg_t sys_fcntl(struct proc *p, int fd, int cmd, int arg)
                                return sysdup(fd, -1);
                        case (F_GETFD):
                        case (F_SETFD):
+                               return 0;
                        case (F_GETFL):
+                               return fd_getfl(fd);
                        case (F_SETFL):
-                               return 0;
+                               return fd_setfl(fd, arg);
                        default:
                                warn("Unsupported fcntl cmd %d\n", cmd);
                }