9ns: Support setting FD flags (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 6 Apr 2018 19:14:52 +0000 (15:14 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 30 Apr 2018 18:37:05 +0000 (14:37 -0400)
Similar to back in the VFS code, I'm not entirely happy supporting the
toggling of these flags.  Ideally, we wouldn't even have e.g. FD_CLOEXEC.

Reinstall your kernel headers

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/ns.h
kern/include/ros/fs.h
kern/src/ns/sysfile.c
kern/src/syscall.c

index 68985ac..f3463f8 100644 (file)
@@ -1126,6 +1126,8 @@ int iseve(void);
 int fd_getfl(int fd);
 int fd_setfl(int fd, int flags);
 int fd_sync(int fd);
+int fd_get_fd_flags(struct fd_table *fdt, int fd);
+int fd_set_fd_flags(struct fd_table *fdt, int fd, int new_fl);
 
 /* kern/drivers/dev/srv.c */
 char *srvname(struct chan *c);
index 3f34935..0206351 100644 (file)
@@ -73,8 +73,11 @@ struct kstat {
 #define F_SETFL                4       /* Set file status flags */
 #define F_SYNC         101     /* fsync() */
 #define F_ADVISE       102     /* posix_fadvise{,64}() */
+
 /* For F_[GET|SET]FD */
 #define FD_CLOEXEC     1
+#define FD_VALID_FLAGS (FD_CLOEXEC)
+
 /* Advise to `posix_fadvise'.  */
 #define POSIX_FADV_NORMAL              0       /* No further special treatment */
 #define POSIX_FADV_RANDOM              1       /* Expect random page references */
index 9ad7d46..78e395e 100644 (file)
@@ -1869,3 +1869,41 @@ void clone_fdt(struct fd_table *src, struct fd_table *dst)
        spin_unlock(&dst->lock);
        spin_unlock(&src->lock);
 }
+
+int fd_get_fd_flags(struct fd_table *fdt, int fd)
+{
+       int ret = -1;
+
+       if (fd < 0)
+               return -1;
+       spin_lock(&fdt->lock);
+       if (fdt->closed) {
+               spin_unlock(&fdt->lock);
+               return -1;
+       }
+       if ((fd < fdt->max_fdset) && GET_BITMASK_BIT(fdt->open_fds->fds_bits, fd))
+               ret = fdt->fd[fd].fd_flags;
+       spin_unlock(&fdt->lock);
+       if (ret == -1)
+               set_error(EBADF, "FD was not open");
+       return ret;
+}
+
+int fd_set_fd_flags(struct fd_table *fdt, int fd, int new_fl)
+{
+       int ret = -1;
+
+       if (fd < 0)
+               return -1;
+       spin_lock(&fdt->lock);
+       if (fdt->closed) {
+               spin_unlock(&fdt->lock);
+               return -1;
+       }
+       if ((fd < fdt->max_fdset) && GET_BITMASK_BIT(fdt->open_fds->fds_bits, fd))
+               fdt->fd[fd].fd_flags = new_fl;
+       spin_unlock(&fdt->lock);
+       if (ret == -1)
+               set_error(EBADF, "FD was not open");
+       return ret;
+}
index 95eaee3..8293981 100644 (file)
@@ -1881,23 +1881,19 @@ static intreg_t sys_lstat(struct proc *p, const char *path, size_t path_l,
 intreg_t sys_fcntl(struct proc *p, int fd, int cmd, unsigned long arg1,
                    unsigned long arg2, unsigned long arg3, unsigned long arg4)
 {
-       int retval = 0;
-       int newfd;
-
        switch (cmd) {
        case (F_DUPFD):
-               newfd = arg1;
-               if (newfd < 0) {
-                       set_errno(EBADF);
-                       return -1;
-               }
                /* TODO: glibc uses regular DUPFD for dup2, which is racy. */
-               return sysdup(fd, newfd, FALSE);
+               return sysdup(fd, arg1, FALSE);
        case (F_GETFD):
+               return fd_get_fd_flags(&p->open_files, fd);
        case (F_SETFD):
-       case (F_ADVISE):
-               /* TODO: 9ns versions */
-               return 0;
+               if (arg1 & ~FD_VALID_FLAGS) {
+                       set_error(EINVAL, "Bad FD flags %p, valid are %p", arg1,
+                                 FD_VALID_FLAGS);
+                       return -1;
+               }
+               return fd_set_fd_flags(&p->open_files, fd, arg1);
        case (F_SYNC):
                return fd_sync(fd);
        case (F_GETFL):
@@ -1905,7 +1901,7 @@ intreg_t sys_fcntl(struct proc *p, int fd, int cmd, unsigned long arg1,
        case (F_SETFL):
                return fd_setfl(fd, arg1);
        }
-       set_errno(EBADF);
+       set_error(EINVAL, "Unsupported fcntl cmd %d", cmd);
        return -1;
 }