]> Zhao Yanbai Git Server - minix.git/commitdiff
libc: support for deprecated FIO* ioctl(2) calls 80/3180/2
authorDavid van Moolenbroek <david@minix3.org>
Sat, 19 Sep 2015 21:59:19 +0000 (21:59 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Wed, 23 Sep 2015 12:03:06 +0000 (12:03 +0000)
Various generic file IOCTL calls should be processed by VFS rather
than individual drivers.  For this reason, we rewrite them to use
fcntl(2) instead.

Change-Id: I38a5f3c7b21943a897114a51678a800f7e7f0a77

minix/lib/libc/sys/ioctl.c

index a0929526cb8204df9818b214792b72fd8b0f8b20..6e2875ced1483a3cff2bf7c48196fac1d9c8b9c1 100644 (file)
@@ -8,6 +8,7 @@
 #include <string.h>
 #include <sys/ioccom.h>
 #include <stdarg.h>
+#include <fcntl.h>
 
 static void rewrite_i2c_netbsd_to_minix(minix_i2c_ioctl_exec_t *out,
     i2c_ioctl_exec_t *in);
@@ -44,6 +45,69 @@ static void rewrite_i2c_minix_to_netbsd(i2c_ioctl_exec_t *out,
   }
 }
 
+/*
+ * Library implementation of FIOCLEX and FIONCLEX.
+ */
+static int
+ioctl_to_setfd(int fd, int mask, int val)
+{
+       int fl;
+
+       if ((fl = fcntl(fd, F_GETFD)) == -1)
+               return -1;
+
+       fl = (fl & ~mask) | val;
+
+       return fcntl(fd, F_SETFD, fl);
+}
+
+/*
+ * Library implementation of FIONBIO and FIOASYNC.
+ */
+static int
+ioctl_to_setfl(int fd, void * data, int sfl)
+{
+       int arg, fl;
+
+       arg = *(int *)data;
+
+       if ((fl = fcntl(fd, F_GETFL)) == -1)
+               return -1;
+
+       if (arg)
+               fl |= sfl;
+       else
+               fl &= ~sfl;
+
+       return fcntl(fd, F_SETFL, fl & ~O_ACCMODE);
+}
+
+/*
+ * Library implementation of various deprecated IOCTLs.  These particular IOCTL
+ * calls change how the file descriptors behave, and have nothing to do with
+ * the actual open file.  They should therefore be handled by VFS rather than
+ * individual device drivers.  We rewrite them to use fcntl(2) instead here.
+ */
+static int
+ioctl_to_fcntl(int fd, unsigned long request, void * data)
+{
+       switch (request) {
+       case FIOCLEX:
+               return ioctl_to_setfd(fd, FD_CLOEXEC, FD_CLOEXEC);
+       case FIONCLEX:
+               return ioctl_to_setfd(fd, FD_CLOEXEC, 0);
+       case FIONBIO:
+               return ioctl_to_setfl(fd, data, O_NONBLOCK);
+       case FIOASYNC:
+               return ioctl_to_setfl(fd, data, O_ASYNC);
+       case FIOSETOWN: /* XXX TODO */
+       case FIOGETOWN: /* XXX TODO */
+       default:
+               errno = ENOTTY;
+               return -1;
+       }
+}
+
 int     ioctl(int fd, unsigned long request, ...)
 {
   int r, request_save;
@@ -54,6 +118,7 @@ int     ioctl(int fd, unsigned long request, ...)
 
   va_start(ap, request);
   data = va_arg(ap, void *);
+  va_end(ap);
 
   /*
    * To support compatibility with interfaces on other systems, certain
@@ -64,6 +129,14 @@ int     ioctl(int fd, unsigned long request, ...)
   request_save = request;
 
   switch (request) {
+       case FIOCLEX:
+       case FIONCLEX:
+       case FIONBIO:
+       case FIOASYNC:
+       case FIOSETOWN:
+       case FIOGETOWN:
+               return ioctl_to_fcntl(fd, request, data);
+
        case I2C_IOCTL_EXEC:
                rewrite_i2c_netbsd_to_minix(&i2c, data);
                addr = (vir_bytes) &i2c;
@@ -92,7 +165,5 @@ int     ioctl(int fd, unsigned long request, ...)
                break;
   }
 
-  va_end(ap);
-
   return r;
 }