sys_fcntl()
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 17 Aug 2010 22:53:27 +0000 (15:53 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:52 +0000 (17:35 -0700)
Doesn't support DUPing yet, and probably will never support any of the
more painful POSIX things, like file locking.

kern/include/vfs.h
kern/src/syscall.c

index f2af661..15c8d1e 100644 (file)
@@ -145,6 +145,15 @@ struct nameidata {
 #define S_IWOTH 00002  /* others have write permission */
 #define S_IXOTH 00001  /* others have execute permission */
 
+/* fcntl flags that we support, keep in sync with glibc */
+#define F_DUPFD                0       /* Duplicate file descriptor */
+#define F_GETFD                1       /* Get file descriptor flags */
+#define F_SETFD                2       /* Set file descriptor flags */
+#define F_GETFL                3       /* Get file status flags */
+#define F_SETFL                4       /* Set file status flags */
+/* For F_[GET|SET]FD */
+#define FD_CLOEXEC     1
+
 /* Every object that has pages, like an inode or the swap (or even direct block
  * devices) has a page_map, tracking which of its pages are currently in memory.
  * It is a map, per object, from index to physical page frame. */
index bac8834..c0d2685 100644 (file)
@@ -932,7 +932,38 @@ 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, int arg)
 {
-       return ufe(fcntl,fd,cmd,arg,0);
+       int retval = 0;
+       struct file *file = get_file_from_fd(&p->open_files, fd);
+       if (!file) {
+               set_errno(EBADF);
+               return -1;
+       }
+       switch (cmd) {
+               case (F_DUPFD):
+                       printk("[kernel] dup not supported yet\n");
+                       break;
+               case (F_GETFD):
+                       /* GET and SETFD just care about CLOEXEC.  We don't have a separate
+                        * flag variable for the FD (we might need to, technically). */
+                       if (file->f_flags & O_CLOEXEC)
+                               retval = FD_CLOEXEC;
+                       break;
+               case (F_SETFD):
+                       if (arg == FD_CLOEXEC)
+                               file->f_flags |= O_CLOEXEC;
+                       break;
+               case (F_GETFL):
+                       retval = file->f_flags;
+                       break;
+               case (F_SETFL):
+                       /* only allowed to set certain flags. */
+                       arg &= O_APPEND | O_ASYNC | O_DIRECT | O_NOATIME | O_NONBLOCK;
+                       break;
+               default:
+                       warn("Unsupported fcntl cmd %d\n", cmd);
+       }
+       kref_put(&file->f_kref);
+       return 0;
 }
 
 static intreg_t sys_access(struct proc *p, const char *path, size_t path_l,