Project

General

Profile

Backport #6127 ยป ruby-io-c.patch

dlampa (Donovan Lampa), 10/10/2012 11:20 PM

View differences:

/Users/dlampa/carrier-build-root/local_build/carrier-ruby-1.9.3p194-2/src/ruby-build/ruby-source/io.c 2012-10-10 09:02:34.000000000 -0500
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)
......
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;
#ifndef HAVE_FCNTL
if (!io_p) {
rb_notimplement();
}
#endif
struct ioctl_arg arg;
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 narg = 0;
int retval;
long len;
rb_secure(2);
#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;
VALUE arg = *argp;
if (NIL_P(arg) || arg == Qfalse) {
narg = 0;
......
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);
}
}
GetOpenFile(io, fptr);
retval = io_cntl(fptr->fd, cmd, narg, io_p);
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");
return narg;
}
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);
}
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 = do_ioctl(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';
}
return INT2NUM(retval);
}
/*
* call-seq:
* ios.ioctl(integer_cmd, arg) -> integer
......
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
......
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
    (1-1/1)