[前][次][番号順一覧][スレッド一覧]

ruby-changes:25086

From: naruse <ko1@a...>
Date: Thu, 11 Oct 2012 15:47:48 +0900 (JST)
Subject: [ruby-changes:25086] naruse:r37138 (ruby_1_9_3): merge revision(s) 33711,33713,33714,33715,33716,33717,33718,33719,33720,33721,33724,33727,33728,33752,33753: [Backport #6127]

naruse	2012-10-11 15:47:36 +0900 (Thu, 11 Oct 2012)

  New Revision: 37138

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=37138

  Log:
    merge revision(s) 33711,33713,33714,33715,33716,33717,33718,33719,33720,33721,33724,33727,33728,33752,33753: [Backport #6127]
    
            * io.c (ioctl_req_t): Type of req argument of ioctl() depend on platform.
              Moreover almost all linux ioctl can't be represented by 32bit integer
              (i.e. MSB is 1). We need wrap ioctl argument type.
            [Bug #5429] [ruby-dev:44589]
            * io.c (struct ioctl_arg): ditto.
            * io.c (rb_ioctl): ditto.
            * test/ruby/test_io.rb (test_ioctl_linux): add a testcase for ioctl
            * backporting patch is created by Donovan Lampa.

  Modified files:
    branches/ruby_1_9_3/io.c

Index: ruby_1_9_3/io.c
===================================================================
--- ruby_1_9_3/io.c	(revision 37137)
+++ ruby_1_9_3/io.c	(revision 37138)
@@ -161,6 +161,62 @@
     if (max_file_descriptor < fd) max_file_descriptor = fd;
 }
 
+void
+rb_maygvl_fd_fix_cloexec(int fd)
+{
+  /* MinGW don't have F_GETFD and FD_CLOEXEC.  [ruby-core:40281] */
+#ifdef F_GETFD
+  int flags, flags2, ret;
+  flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
+  if (flags == -1) {
+    rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
+  }
+  if (fd <= 2)
+    flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
+  else
+    flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
+  if (flags != flags2) {
+    ret = fcntl(fd, F_SETFD, flags2);
+    if (ret == -1) {
+      rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
+    }
+  }
+#endif
+}
+
+int
+rb_cloexec_fcntl_dupfd(int fd, int minfd)
+{
+    int ret;
+
+#if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC)
+    static int try_dupfd_cloexec = 1;
+    if (try_dupfd_cloexec) {
+      ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
+      if (ret != -1) {
+	if (ret <= 2)
+	  rb_maygvl_fd_fix_cloexec(ret);
+	return ret;
+      }
+      /* F_DUPFD_CLOEXEC is available since Linux 2.6.24.  Linux 2.6.18 fails with EINVAL */
+      if (errno == EINVAL) {
+	ret = fcntl(fd, F_DUPFD, minfd);
+	if (ret != -1) {
+	  try_dupfd_cloexec = 0;
+	}
+      }
+    }
+    else {
+      ret = fcntl(fd, F_DUPFD, minfd);
+    }
+#else
+    ret = fcntl(fd, F_DUPFD, minfd);
+#endif
+    if (ret == -1) return -1;
+    rb_maygvl_fd_fix_cloexec(ret);
+    return ret;
+}
+
 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
 #define ARGF argf_of(argf)
 
@@ -7927,61 +7983,204 @@
     return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
 }
 
-struct io_cntl_arg {
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+ typedef unsigned long ioctl_req_t;
+ #define NUM2IOCTLREQ(num) NUM2ULONG(num)
+#else
+ typedef int ioctl_req_t;
+ #define NUM2IOCTLREQ(num) NUM2INT(num)
+#endif
+
+struct ioctl_arg {
     int		fd;
-    int		cmd;
+    ioctl_req_t	cmd;
     long	narg;
-    int		io_p;
 };
 
-static VALUE nogvl_io_cntl(void *ptr)
+static VALUE nogvl_ioctl(void *ptr)
 {
-    struct io_cntl_arg *arg = ptr;
+    struct ioctl_arg *arg = ptr;
 
-    if (arg->io_p)
-	return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
-    else
-	return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
+    return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
 }
 
 static int
-io_cntl(int fd, int cmd, long narg, int io_p)
+do_ioctl(int fd, ioctl_req_t cmd, long narg)
 {
     int retval;
-    struct io_cntl_arg arg;
+    struct ioctl_arg arg;
 
-#ifndef HAVE_FCNTL
-    if (!io_p) {
-	rb_notimplement();
-    }
-#endif
-
     arg.fd = fd;
     arg.cmd = cmd;
     arg.narg = narg;
-    arg.io_p = io_p;
 
-    retval = (int)rb_thread_io_blocking_region(nogvl_io_cntl, &arg, fd);
-#if defined(F_DUPFD)
-    if (!io_p && retval != -1 && cmd == F_DUPFD) {
-	rb_update_max_fd(retval);
-    }
-#endif
+    retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
 
     return retval;
 }
 
-static VALUE
-rb_io_ctl(VALUE io, VALUE req, VALUE arg, int io_p)
+static long
+ioctl_narg_len(ioctl_req_t cmd)
 {
-    int cmd = NUM2INT(req);
-    rb_io_t *fptr;
-    long len = 0;
+    long len;
+
+#ifdef IOCPARM_MASK
+#ifndef IOCPARM_LEN
+#define IOCPARM_LEN(x)  (((x) >> 16) & IOCPARM_MASK)
+#endif
+#endif
+#ifdef IOCPARM_LEN
+    len = IOCPARM_LEN(cmd);	/* on BSDish systems we're safe */
+#elif defined(_IOC_SIZE)
+    len = _IOC_SIZE(cmd);
+#else
+    len = 256;		/* otherwise guess at what's safe */
+#endif
+
+    return len;
+}
+
+#ifdef HAVE_FCNTL
+#ifdef __linux__
+typedef long fcntl_arg_t;
+#else
+/* posix */
+typedef int fcntl_arg_t;
+#endif
+
+static long
+fcntl_narg_len(int cmd)
+{
+    long len;
+
+    switch (cmd) {
+#ifdef F_DUPFD
+      case F_DUPFD:
+	len = sizeof(fcntl_arg_t);
+	break;
+#endif
+#ifdef F_DUP2FD /* bsd specific */
+      case F_DUP2FD:
+	len = sizeof(int);
+	break;
+#endif
+#ifdef F_DUPFD_CLOEXEC /* linux specific */
+      case F_DUPFD_CLOEXEC:
+	len = sizeof(fcntl_arg_t);
+	break;
+#endif
+#ifdef F_GETFD
+      case F_GETFD:
+	len = 1;
+	break;
+#endif
+#ifdef F_SETFD
+      case F_SETFD:
+	len = sizeof(fcntl_arg_t);
+	break;
+#endif
+#ifdef F_GETFL
+      case F_GETFL:
+	len = 1;
+	break;
+#endif
+#ifdef F_SETFL
+      case F_SETFL:
+	len = sizeof(fcntl_arg_t);
+	break;
+#endif
+#ifdef F_GETOWN
+      case F_GETOWN:
+	len = 1;
+	break;
+#endif
+#ifdef F_SETOWN
+      case F_SETOWN:
+	len = sizeof(fcntl_arg_t);
+	break;
+#endif
+#ifdef F_GETOWN_EX /* linux specific */
+      case F_GETOWN_EX:
+	len = sizeof(struct f_owner_ex);
+	break;
+#endif
+#ifdef F_SETOWN_EX /* linux specific */
+      case F_SETOWN_EX:
+	len = sizeof(struct f_owner_ex);
+	break;
+#endif
+#ifdef F_GETLK
+      case F_GETLK:
+	len = sizeof(struct flock);
+	break;
+#endif
+#ifdef F_SETLK
+      case F_SETLK:
+	len = sizeof(struct flock);
+	break;
+#endif
+#ifdef F_SETLKW
+      case F_SETLKW:
+	len = sizeof(struct flock);
+	break;
+#endif
+#ifdef F_READAHEAD /* bsd specific */
+      case F_READAHEAD:
+	len = sizeof(int);
+	break;
+#endif
+#ifdef F_RDAHEAD /* Darwin specific */
+      case F_RDAHEAD:
+	len = sizeof(int);
+	break;
+#endif
+#ifdef F_GETSIG /* linux specific */
+      case F_GETSIG:
+	len = 1;
+	break;
+#endif
+#ifdef F_SETSIG /* linux specific */
+      case F_SETSIG:
+	len = sizeof(fcntl_arg_t);
+	break;
+#endif
+#ifdef F_GETLEASE /* linux specific */
+      case F_GETLEASE:
+	len = 1;
+	break;
+#endif
+#ifdef F_SETLEASE /* linux specific */
+      case F_SETLEASE:
+	len = sizeof(fcntl_arg_t);
+	break;
+#endif
+#ifdef F_NOTIFY /* linux specific */
+      case F_NOTIFY:
+	len = sizeof(fcntl_arg_t);
+	break;
+#endif
+
+      default:
+	len = 256;
+	break;
+    }
+
+    return len;
+}
+#else /* HAVE_FCNTL */
+static long
+fcntl_narg_len(int cmd)
+{
+    return 0;
+}
+#endif /* HAVE_FCNTL */
+
+static long
+setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
+{
     long narg = 0;
-    int retval;
+    VALUE arg = *argp;
 
-    rb_secure(2);
-
     if (NIL_P(arg) || arg == Qfalse) {
 	narg = 0;
     }
@@ -7998,50 +8197,50 @@
 	    narg = NUM2LONG(arg);
 	}
 	else {
-	    arg = tmp;
-#ifdef IOCPARM_MASK
-#ifndef IOCPARM_LEN
-#define IOCPARM_LEN(x)  (((x) >> 16) & IOCPARM_MASK)
-#endif
-#endif
-#ifdef IOCPARM_LEN
-	    len = IOCPARM_LEN(cmd);	/* on BSDish systems we're safe */
-#else
-	    len = 256;		/* otherwise guess at what's safe */
-#endif
+	    long len;
+
+	    *argp = arg = tmp;
+	    if (io_p)
+		len = ioctl_narg_len(cmd);
+	    else
+		len = fcntl_narg_len((int)cmd);
 	    rb_str_modify(arg);
 
-	    if (len <= RSTRING_LEN(arg)) {
-		len = RSTRING_LEN(arg);
-	    }
-	    if (RSTRING_LEN(arg) < len) {
+	    /* expand for data + sentinel. */
+	    if (RSTRING_LEN(arg) < len+1) {
 		rb_str_resize(arg, len+1);
 	    }
-	    RSTRING_PTR(arg)[len] = 17;	/* a little sanity check here */
+	    /* a little sanity check here */
+	    RSTRING_PTR(arg)[RSTRING_LEN(arg) - 1] = 17;
 	    narg = (long)(SIGNED_VALUE)RSTRING_PTR(arg);
 	}
     }
+        return narg;
+    }
+
+static VALUE
+rb_ioctl(VALUE io, VALUE req, VALUE arg)
+{
+    ioctl_req_t cmd = NUM2IOCTLREQ(req);
+    rb_io_t *fptr;
+    long narg;
+    int retval;
+  
+    rb_secure(2);
+
+    narg = setup_narg(cmd, &arg, 1);
     GetOpenFile(io, fptr);
-    retval = io_cntl(fptr->fd, cmd, narg, io_p);
+    retval = do_ioctl(fptr->fd, cmd, narg);
     if (retval < 0) rb_sys_fail_path(fptr->pathv);
-    if (TYPE(arg) == T_STRING && RSTRING_PTR(arg)[len] != 17) {
-	rb_raise(rb_eArgError, "return value overflowed string");
+    if (RB_TYPE_P(arg, T_STRING)) {
+	if (RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] != 17)
+	    rb_raise(rb_eArgError, "return value overflowed string");
+	RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] = '\0';
     }
 
-    if (!io_p && cmd == F_SETFL) {
-	if (narg & O_NONBLOCK) {
-	    fptr->mode |= FMODE_WSPLIT_INITIALIZED;
-	    fptr->mode &= ~FMODE_WSPLIT;
-	}
-	else {
-	    fptr->mode &= ~(FMODE_WSPLIT_INITIALIZED|FMODE_WSPLIT);
-	}
-    }
-
     return INT2NUM(retval);
 }
 
-
 /*
  *  call-seq:
  *     ios.ioctl(integer_cmd, arg)    -> integer
@@ -8060,10 +8259,80 @@
     VALUE req, arg;
 
     rb_scan_args(argc, argv, "11", &req, &arg);
-    return rb_io_ctl(io, req, arg, 1);
+    return rb_ioctl(io, req, arg);
 }
 
 #ifdef HAVE_FCNTL
+struct fcntl_arg {
+    int		fd;
+    int 	cmd;
+    long	narg;
+};
+
+static VALUE nogvl_fcntl(void *ptr)
+{
+    struct fcntl_arg *arg = ptr;
+
+#if defined(F_DUPFD)
+    if (arg->cmd == F_DUPFD)
+	return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
+#endif
+    return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
+}
+
+static int
+do_fcntl(int fd, int cmd, long narg)
+{
+    int retval;
+    struct fcntl_arg arg;
+
+    arg.fd = fd;
+    arg.cmd = cmd;
+    arg.narg = narg;
+
+    retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
+#if defined(F_DUPFD)
+    if (retval != -1 && cmd == F_DUPFD) {
+	rb_update_max_fd(retval);
+    }
+#endif
+
+    return retval;
+}
+
+static VALUE
+rb_fcntl(VALUE io, VALUE req, VALUE arg)
+{
+    int cmd = NUM2INT(req);
+    rb_io_t *fptr;
+    long narg;
+    int retval;
+
+    rb_secure(2);
+
+    narg = setup_narg(cmd, &arg, 0);
+    GetOpenFile(io, fptr);
+    retval = do_fcntl(fptr->fd, cmd, narg);
+    if (retval < 0) rb_sys_fail_path(fptr->pathv);
+    if (RB_TYPE_P(arg, T_STRING)) {
+	if (RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] != 17)
+	    rb_raise(rb_eArgError, "return value overflowed string");
+	RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] = '\0';
+    }
+
+    if (cmd == F_SETFL) {
+	if (narg & O_NONBLOCK) {
+	    fptr->mode |= FMODE_WSPLIT_INITIALIZED;
+	    fptr->mode &= ~FMODE_WSPLIT;
+	}
+	else {
+	    fptr->mode &= ~(FMODE_WSPLIT_INITIALIZED|FMODE_WSPLIT);
+	}
+    }
+
+    return INT2NUM(retval);
+}
+
 /*
  *  call-seq:
  *     ios.fcntl(integer_cmd, arg)    -> integer
@@ -8083,7 +8352,7 @@
     VALUE req, arg;
 
     rb_scan_args(argc, argv, "11", &req, &arg);
-    return rb_io_ctl(io, req, arg, 0);
+    return rb_fcntl(io, req, arg);
 }
 #else
 #define rb_io_fcntl rb_f_notimplement

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]