/* * call-seq: * #write_unblocked(string) -> integer * * Writes the given string to <em>ios</em> using * the write(2) system call. It assumes that O_NONBLOCK * is already set for the underlying file descriptor. * * Over ~100,000 calls it is about 0.043 seconds faster. * * It returns the number of bytes written. */ static VALUE rb_yaram_mbox_write_unblocked(VALUE self, VALUE io, VALUE str) { rb_io_t *fptr; long n; rb_secure(4); if (TYPE(str) != T_STRING) str = rb_obj_as_string(str); io = rb_io_get_write_io(io); GetOpenFile(io, fptr); rb_io_check_writable(fptr); if (io_fflush(fptr) < 0) rb_sys_fail(0); n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str)); if (n == -1) { if (errno == EWOULDBLOCK || errno == EAGAIN) rb_mod_sys_fail(rb_mWaitWritable, "write would block"); rb_sys_fail_path(fptr->pathv); } return LONG2FIX(n); }
VALUE rb_readlink(VALUE path) { ssize_t len; WCHAR *wpath, wbuf[MAX_PATH]; rb_encoding *enc; UINT cp, path_cp; FilePathValue(path); enc = rb_enc_get(path); cp = path_cp = code_page(enc); if (cp == INVALID_CODE_PAGE) { path = fix_string_encoding(path, enc); cp = CP_UTF8; } wpath = mbstr_to_wstr(cp, RSTRING_PTR(path), RSTRING_LEN(path)+rb_enc_mbminlen(enc), NULL); if (!wpath) rb_memerror(); len = rb_w32_wreadlink(wpath, wbuf, numberof(wbuf)); free(wpath); if (len < 0) rb_sys_fail_path(path); enc = rb_filesystem_encoding(); cp = path_cp = code_page(enc); if (cp == INVALID_CODE_PAGE) cp = CP_UTF8; return append_wstr(rb_enc_str_new(0, 0, enc), wbuf, len, cp, path_cp, enc); }
/* * Document-method: setsockopt * call-seq: * setsockopt(level, optname, optval) * setsockopt(socketoption) * * Sets a socket option. These are protocol and system specific, see your * local system documentation for details. * * === Parameters * * +level+ is an integer, usually one of the SOL_ constants such as * Socket::SOL_SOCKET, or a protocol level. * A string or symbol of the name, possibly without prefix, is also * accepted. * * +optname+ is an integer, usually one of the SO_ constants, such * as Socket::SO_REUSEADDR. * A string or symbol of the name, possibly without prefix, is also * accepted. * * +optval+ is the value of the option, it is passed to the underlying * setsockopt() as a pointer to a certain number of bytes. How this is * done depends on the type: * - Fixnum: value is assigned to an int, and a pointer to the int is * passed, with length of sizeof(int). * - true or false: 1 or 0 (respectively) is assigned to an int, and the * int is passed as for a Fixnum. Note that +false+ must be passed, * not +nil+. * - String: the string's data and length is passed to the socket. * * +socketoption+ is an instance of Socket::Option * * === Examples * * Some socket options are integers with boolean values, in this case * #setsockopt could be called like this: * sock.setsockopt(:SOCKET, :REUSEADDR, true) * sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true) * sock.setsockopt(Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true)) * * Some socket options are integers with numeric values, in this case * #setsockopt could be called like this: * sock.setsockopt(:IP, :TTL, 255) * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255) * sock.setsockopt(Socket::Option.int(:INET, :IP, :TTL, 255)) * * Option values may be structs. Passing them can be complex as it involves * examining your system headers to determine the correct definition. An * example is an +ip_mreq+, which may be defined in your system headers as: * struct ip_mreq { * struct in_addr imr_multiaddr; * struct in_addr imr_interface; * }; * * In this case #setsockopt could be called like this: * optval = IPAddr.new("224.0.0.251").hton + * IPAddr.new(Socket::INADDR_ANY, Socket::AF_INET).hton * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval) * */ static VALUE bsock_setsockopt(int argc, VALUE *argv, VALUE sock) { UNRUBBY_SOCKET_HACK; VALUE lev, optname, val; int family, level, option; rb_io_t *fptr; int i; char *v; int vlen; if (argc == 1) { lev = rb_funcall(argv[0], rb_intern("level"), 0); optname = rb_funcall(argv[0], rb_intern("optname"), 0); val = rb_funcall(argv[0], rb_intern("data"), 0); } else { rb_scan_args(argc, argv, "30", &lev, &optname, &val); } rb_secure(2); GetOpenFile(sock, fptr); family = rsock_getfamily(fptr->fd); level = rsock_level_arg(family, lev); option = rsock_optname_arg(family, level, optname); switch (TYPE(val)) { case T_FIXNUM: i = FIX2INT(val); goto numval; case T_FALSE: i = 0; goto numval; case T_TRUE: i = 1; numval: v = (char*)&i; vlen = (int)sizeof(i); break; default: StringValue(val); v = RSTRING_PTR(val); vlen = RSTRING_LENINT(val); break; } #define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path)) rb_io_check_closed(fptr); if (setsockopt(fptr->fd, level, option, v, vlen) < 0) rb_sys_fail_path(fptr->pathv); return INT2FIX(0); }
/* * Document-method: getsockopt * call-seq: * getsockopt(level, optname) => socketoption * * Gets a socket option. These are protocol and system specific, see your * local system documentation for details. The option is returned as * a Socket::Option object. * * === Parameters * * +level+ is an integer, usually one of the SOL_ constants such as * Socket::SOL_SOCKET, or a protocol level. * A string or symbol of the name, possibly without prefix, is also * accepted. * * +optname+ is an integer, usually one of the SO_ constants, such * as Socket::SO_REUSEADDR. * A string or symbol of the name, possibly without prefix, is also * accepted. * * === Examples * * Some socket options are integers with boolean values, in this case * #getsockopt could be called like this: * * reuseaddr = sock.getsockopt(:SOCKET, :REUSEADDR).bool * * optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR) * optval = optval.unpack "i" * reuseaddr = optval[0] == 0 ? false : true * * Some socket options are integers with numeric values, in this case * #getsockopt could be called like this: * * ipttl = sock.getsockopt(:IP, :TTL).int * * optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL) * ipttl = optval.unpack("i")[0] * * Option values may be structs. Decoding them can be complex as it involves * examining your system headers to determine the correct definition. An * example is a +struct linger+, which may be defined in your system headers * as: * struct linger { * int l_onoff; * int l_linger; * }; * * In this case #getsockopt could be called like this: * * # Socket::Option knows linger structure. * onoff, linger = sock.getsockopt(:SOCKET, :LINGER).linger * * optval = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER) * onoff, linger = optval.unpack "ii" * onoff = onoff == 0 ? false : true */ static VALUE bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname) { int level, option; socklen_t len; char *buf; rb_io_t *fptr; int family; GetOpenFile(sock, fptr); family = rsock_getfamily(fptr->fd); level = rsock_level_arg(family, lev); option = rsock_optname_arg(family, level, optname); len = 256; buf = ALLOCA_N(char,len); rb_io_check_closed(fptr); if (getsockopt(fptr->fd, level, option, buf, &len) < 0) rb_sys_fail_path(fptr->pathv); return rsock_sockopt_new(family, level, option, rb_str_new(buf, len)); }
static VALUE rb_writev(VALUE io, VALUE list) { rb_io_t * fptr; struct iovec * iov; long i; ssize_t written; VALUE tmp; Check_Type(list, T_ARRAY); #ifdef IOV_MAX if(RARRAY_LEN(list) > IOV_MAX) #else if(RARRAY_LEN(list) > NUM2INT(rb_IOV_MAX)) #endif rb_raise(rb_eArgError, "list is too long"); tmp = rb_io_check_io(io); GetOpenFile(tmp, fptr); rb_io_check_writable(fptr); iov = xcalloc(RARRAY_LEN(list), sizeof(struct iovec)); for(i = 0; i < RARRAY_LEN(list); i++) { VALUE string = rb_ary_entry(list, i); iov[i].iov_base = StringValuePtr(string); iov[i].iov_len = RSTRING_LEN(string); } written = writev(fptr->fd, iov, (int)RARRAY_LEN(list)); xfree(iov); if (written == -1) rb_sys_fail_path(fptr->pathv); return LONG2FIX(written); }