Class: IO
- Inherits:
-
Object
- Object
- IO
- Defined in:
- (unknown)
Constant Summary collapse
- DIRECTIO_OFF =
Applications get the default system behavior when accessing file data.
0
- DIRECTIO_ON =
File data is not cached in the system’s memory pages.
1
- DIRECT =
direct disk access (in Linux)
040000
- IOV_MAX =
LONG2NUM(IOV_MAX)
- EXTRA_VERSION =
The version of this library. This a string.
1.2.8
Class Method Summary collapse
-
.closefrom(lowfd) ⇒ Object
Close all open file descriptors (associated with the current process) that are greater than or equal to
lowfd
. -
.fdwalk(lowfd) {|fh| ... } ⇒ Object
Iterates over each open file descriptor and yields back a File object.
-
.pread(fd, nbyte, offset) ⇒ Object
IO.pread(fd, length, offset).
-
.pread_ptr(v_fd, v_nbyte, v_offset) ⇒ Object
IO.pread_ptr(fd, length, offset).
-
.pwrite(fd, buf, offset) ⇒ Object
IO.pwrite(fd, buf, offset).
-
.writev(fd, ary) ⇒ Object
IO.writev(fd, %w(hello world)).
Instance Method Summary collapse
-
#directio=(advice) ⇒ Object
Sets the advice for the current file descriptor using directio().
-
#directio? ⇒ Boolean
Returns true or false, based on whether directio has been set for the current handle.
-
#ttyname ⇒ Object
io.ttyname.
Class Method Details
.closefrom(lowfd) ⇒ Object
Close all open file descriptors (associated with the current process) that are greater than or equal to lowfd
.
This method uses your system’s builtin closefrom() function, if supported. Otherwise, it uses a manual, and (probably) less efficient approach.
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'ext/io/extra.c', line 149
static VALUE io_closefrom(VALUE klass, VALUE v_low_fd){
#if defined(HAVE_CLOSEFROM) && !defined(HAVE_RB_RESERVED_FD_P)
/* we can't safely use closefrom() if the RubyVM reserves FDs */
closefrom(NUM2INT(v_low_fd));
#else
int i, lowfd;
int maxfd = open_max();
lowfd = NUM2INT(v_low_fd);
for(i = lowfd; i < maxfd; i++) {
if(!RB_RESERVED_FD_P(i))
close(i);
}
#endif
return klass;
}
|
.fdwalk(lowfd) {|fh| ... } ⇒ Object
Iterates over each open file descriptor and yields back a File object.
Not supported on all platforms.
244 245 246 247 248 249 250 251 252 253 254 |
# File 'ext/io/extra.c', line 244
static VALUE io_fdwalk(int argc, VALUE* argv, VALUE klass){
VALUE v_low_fd, v_block;
int lowfd;
rb_scan_args(argc, argv, "1&", &v_low_fd, &v_block);
lowfd = NUM2INT(v_low_fd);
fdwalk(close_func, &lowfd);
return klass;
}
|
.pread(fd, nbyte, offset) ⇒ Object
IO.pread(fd, length, offset)
This is similar to the IO.read method, except that it reads from a given position in the file without changing the file pointer. And unlike IO.read, the fd
, length
and offset
arguments are all mandatory.
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
# File 'ext/io/extra.c', line 373
static VALUE s_io_pread(VALUE klass, VALUE fd, VALUE nbyte, VALUE offset){
struct pread_args args;
VALUE str;
ssize_t nread;
args.fd = NUM2INT(fd);
args.nbyte = NUM2ULONG(nbyte);
args.offset = NUM2OFFT(offset);
str = rb_str_new(NULL, args.nbyte);
args.buf = RSTRING_PTR(str);
#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
nread = (ssize_t)rb_thread_call_without_gvl((void*)nogvl_pread, &args, RUBY_UBF_IO, 0);
#else
nread = (ssize_t)rb_thread_blocking_region(nogvl_pread, &args, RUBY_UBF_IO, 0);
#endif
if (nread == -1)
rb_sys_fail("pread");
if ((size_t)nread != args.nbyte)
rb_str_set_len(str, nread);
return str;
}
|
.pread_ptr(v_fd, v_nbyte, v_offset) ⇒ Object
IO.pread_ptr(fd, length, offset)
This is identical to IO.pread, except that it returns the pointer address of the string, instead of the actual buffer.
408 409 410 411 412 413 414 415 416 417 418 419 420 |
# File 'ext/io/extra.c', line 408
static VALUE s_io_pread_ptr(VALUE klass, VALUE v_fd, VALUE v_nbyte, VALUE v_offset){
int fd = NUM2INT(v_fd);
size_t nbyte = NUM2ULONG(v_nbyte);
off_t offset = NUM2OFFT(v_offset);
uintptr_t* vector = malloc(nbyte + 1);
if(pread(fd, vector, nbyte, offset) == -1){
free(vector);
rb_sys_fail("pread");
}
return ULL2NUM(vector[0]);
}
|
.pwrite(fd, buf, offset) ⇒ Object
IO.pwrite(fd, buf, offset)
This method writes the buf
, starting at offset
, to the given fd
, which must be opened with write permissions.
This is similar to a seek & write in standard Ruby but the difference, beyond being a singleton method, is that the file pointer is never moved.
Returns the number of bytes written.
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 |
# File 'ext/io/extra.c', line 449
static VALUE s_io_pwrite(VALUE klass, VALUE fd, VALUE buf, VALUE offset){
ssize_t result;
struct pwrite_args args;
args.fd = NUM2INT(fd);
args.buf = RSTRING_PTR(buf);
args.nbyte = RSTRING_LEN(buf);
args.offset = NUM2OFFT(offset);
#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
result = (ssize_t)rb_thread_call_without_gvl((void*)nogvl_pwrite, &args, RUBY_UBF_IO, 0);
#else
result = (ssize_t)rb_thread_blocking_region(nogvl_pwrite, &args, RUBY_UBF_IO, 0);
#endif
if(result == -1)
rb_sys_fail("pwrite");
return ULL2NUM(result);
}
|
.writev(fd, ary) ⇒ Object
IO.writev(fd, %w(hello world))
This method writes the contents of an array of strings to the given fd
. It can be useful to avoid generating a temporary string via Array#join when writing out large arrays of strings.
The given array should have fewer elements than the IO::IOV_MAX constant.
Returns the number of bytes written.
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 |
# File 'ext/io/extra.c', line 520
static VALUE s_io_writev(VALUE klass, VALUE fd, VALUE ary) {
ssize_t result = 0;
ssize_t left;
struct writev_args args;
args.fd = NUM2INT(fd);
ARY2IOVEC(args.iov, args.iovcnt, left, ary);
for(;;) {
#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
ssize_t w = (ssize_t)rb_thread_call_without_gvl(
(void*)nogvl_writev, &args, RUBY_UBF_IO, 0
);
#else
ssize_t w = (ssize_t)rb_thread_blocking_region(
nogvl_writev, &args, RUBY_UBF_IO, 0
);
#endif
if(w == -1) {
if (rb_io_wait_writable(args.fd)) {
continue;
} else {
if (result > 0) {
/*
* unlikely to hit this case, return the already written bytes,
* we'll let the next write (or close) fail instead
*/
break;
}
rb_sys_fail("writev");
}
}
result += w;
if(w == left) {
break;
} else { /* partial write, this can get tricky */
int i;
struct iovec *new_iov = args.iov;
left -= w;
/* skip over iovecs we've already written completely */
for (i = 0; i < args.iovcnt; i++, new_iov++) {
if (w == 0)
break;
/*
* partially written iov,
* modify and retry with current iovec in front
*/
if (new_iov->iov_len > (size_t)w) {
VALUE base = (VALUE)new_iov->iov_base;
new_iov->iov_len -= w;
new_iov->iov_base = (void *)(base + w);
break;
}
w -= new_iov->iov_len;
}
/* retry without the already-written iovecs */
args.iovcnt -= i;
args.iov = new_iov;
}
}
return LONG2NUM(result);
}
|
Instance Method Details
#directio=(advice) ⇒ Object
Sets the advice for the current file descriptor using directio(). Valid values are IO::DIRECTIO_ON and IO::DIRECTIO_OFF. See the directio(3c) man page for more information.
All file descriptors start at DIRECTIO_OFF, unless your filesystem has been mounted using ‘forcedirectio’ (and supports that option).
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
# File 'ext/io/extra.c', line 295
static VALUE io_set_directio(VALUE self, VALUE v_advice){
int fd;
int advice = NUM2INT(v_advice);
/* Only two possible valid values */
if( (advice != DIRECTIO_OFF) && (advice != DIRECTIO_ON) )
rb_raise(rb_eStandardError, "Invalid value passed to IO#directio=");
/* Retrieve the current file descriptor in order to pass it to directio() */
fd = NUM2INT(rb_funcall(self, rb_intern("fileno"), 0, 0));
#if defined(HAVE_DIRECTIO)
if(directio(fd, advice) < 0)
rb_raise(rb_eStandardError, "The directio() call failed");
if(advice == DIRECTIO_ON)
rb_iv_set(self, "@directio", Qtrue);
else
rb_iv_set(self, "@directio", Qfalse);
#else
{
#if defined(O_DIRECT)
int flags = fcntl(fd, F_GETFL);
if(flags < 0)
rb_sys_fail("fcntl");
if(advice == DIRECTIO_OFF){
if(flags & O_DIRECT){
if(fcntl(fd, F_SETFL, flags & ~O_DIRECT) < 0)
rb_sys_fail("fcntl");
}
} else { /* DIRECTIO_ON */
if(!(flags & O_DIRECT)){
if(fcntl(fd, F_SETFL, flags | O_DIRECT) < 0)
rb_sys_fail("fcntl");
}
}
#elif defined(F_NOCACHE)
if(advice == DIRECTIO_OFF){
if(fcntl(fd, F_NOCACHE, 0) < 0)
rb_sys_fail("fcntl");
rb_iv_set(self, "@directio", Qfalse);
} else { /* DIRECTIO_ON*/
if(fcntl(fd, F_NOCACHE, 1) < 0)
rb_sys_fail("fcntl");
rb_iv_set(self, "@directio", Qtrue);
}
#endif
}
#endif
return self;
}
|
#directio? ⇒ Boolean
Returns true or false, based on whether directio has been set for the current handle. The default is false.
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'ext/io/extra.c', line 265
static VALUE io_get_directio(VALUE self){
#if defined(HAVE_DIRECTIO) || defined(F_NOCACHE)
VALUE v_advice = rb_iv_get(self, "@directio");
if(NIL_P(v_advice))
v_advice = Qfalse;
return v_advice;
#elif defined(O_DIRECT)
int fd = NUM2INT(rb_funcall(self, rb_intern("fileno"), 0, 0));
int flags = fcntl(fd, F_GETFL);
if(flags < 0)
rb_sys_fail("fcntl");
return (flags & O_DIRECT) ? Qtrue : Qfalse;
#endif /* O_DIRECT */
}
|
#ttyname ⇒ Object
io.ttyname
Returns the ttyname associated with the IO object, or nil if the IO object isn’t associated with a tty.
Example:
STDOUT.ttyname # => '/dev/ttyp1'
604 605 606 607 608 609 610 611 612 613 |
# File 'ext/io/extra.c', line 604
static VALUE io_get_ttyname(VALUE self){
VALUE v_return = Qnil;
int fd = NUM2INT(rb_funcall(self, rb_intern("fileno"), 0, 0));
if(isatty(fd))
v_return = rb_str_new2(ttyname(fd));
return v_return;
}
|