io-extra 1.2.8 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +1 -0
- data/CHANGES +11 -0
- data/MANIFEST +2 -1
- data/README +11 -7
- data/ext/extconf.rb +0 -4
- data/ext/io/extra.c +144 -225
- data/lib/io-extra.rb +1 -0
- data/test/test_io_extra.rb +2 -1
- metadata +44 -22
- metadata.gz.sig +0 -0
- data/.gemtest +0 -0
- data/Rakefile +0 -98
- data/doc/io_extra.txt +0 -85
- data/examples/example_io_extra.rb +0 -42
- data/examples/example_pread.rb +0 -24
- data/io-extra.gemspec +0 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e110a14a9b41e4ae67f06a04338ebba468ae3731b1ed8d940606cfc50f56fa11
|
4
|
+
data.tar.gz: 90bc28cf009765f3cdefdeb4fa6028b4269a2b58067ceb9272f58fdfd75e5352
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6dbb68585d84b9e0fde2b4e508749500eb86993157aeff7ce830e7b86676ac96027ef6ba18bac8ec1258f16f5b1331a97d5187de90237858828361928c888bc2
|
7
|
+
data.tar.gz: 66beb1736b6ca2d846aa0eeca812dcf317b90463b260a18f439197090df1de51d4117c9ae233ddcc9c687e84967af30446a270ec8e8ffd229636f9413ae70d6f
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data.tar.gz.sig
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
���$��d�/�56?�����I�π�T2�F������v3��wscmk
|
data/CHANGES
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
== 1.3.0 - 19-Oct-2018
|
2
|
+
* Now assumes Ruby 2.1 or later. This has no effect on the external API, but
|
3
|
+
it does allow for lots of internal cleanup.
|
4
|
+
* License changed to Apache-2.0.
|
5
|
+
* The EXTRA_VERSION constant is now frozen.
|
6
|
+
* Added the io-extra.rb file for convenience.
|
7
|
+
* Updates to the gemspec, including the addition of metadata.
|
8
|
+
* The Rakefile now assumes Rubygems 2.0 or later.
|
9
|
+
* Added a cert.
|
10
|
+
* Removed the .gemtest file.
|
11
|
+
|
1
12
|
== 1.2.8 - 29-Dec-2014
|
2
13
|
* Updated for compatibility with Ruby 2.2.x.
|
3
14
|
|
data/MANIFEST
CHANGED
data/README
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
gem install io-extra
|
12
12
|
|
13
13
|
= Synopsis
|
14
|
-
require 'io/extra'
|
14
|
+
require 'io/extra' # or 'io-extra'
|
15
15
|
|
16
16
|
# Close all file descriptors from 3 up.
|
17
17
|
IO.closefrom(3)
|
@@ -45,9 +45,9 @@
|
|
45
45
|
of IO.fdwalk and a pure Ruby version that looks something like this:
|
46
46
|
|
47
47
|
def IO.fdwalk(n)
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
ObjectSpace.each_object(File){ |f|
|
49
|
+
yield f if f.fileno >= n
|
50
|
+
}
|
51
51
|
end
|
52
52
|
|
53
53
|
The primary difference is that this only closes Ruby file objects, not
|
@@ -67,21 +67,25 @@
|
|
67
67
|
The IO.writev tests fail on Solaris. Short test scripts seem to work,
|
68
68
|
however. We're not sure what the issue is yet. Help wanted.
|
69
69
|
|
70
|
+
Update: As of 2018 Solaris is basically dead, so I'm not going to worry
|
71
|
+
about supporting Solaris unless there's an outcry.
|
72
|
+
|
70
73
|
Please file any bug reports on the project page at
|
71
74
|
https://github.com/djberg96/io-extra
|
72
75
|
|
73
76
|
= Future Plans
|
74
|
-
* Switch from C extension to FFI.
|
77
|
+
* Switch from C extension to FFI (maybe).
|
78
|
+
* Add the IO.pselect method.
|
75
79
|
|
76
80
|
= Acknowledgements
|
77
81
|
Eric Wong for some great work on Linux compatibility and other fixes, as
|
78
82
|
well as the code for the IO.writev method.
|
79
83
|
|
80
84
|
= License
|
81
|
-
|
85
|
+
Apache-2.0
|
82
86
|
|
83
87
|
= Copyright
|
84
|
-
(C) 2003-
|
88
|
+
(C) 2003-2018 Daniel J. Berger
|
85
89
|
All Rights Reserved
|
86
90
|
|
87
91
|
= Warranty
|
data/ext/extconf.rb
CHANGED
@@ -13,11 +13,7 @@ have_func('directio')
|
|
13
13
|
have_func('pread')
|
14
14
|
have_func('pwrite')
|
15
15
|
have_func('writev')
|
16
|
-
have_func('rb_str_set_len', 'ruby.h')
|
17
|
-
have_func('rb_thread_blocking_region')
|
18
16
|
have_func('ttyname')
|
19
|
-
have_func('rb_reserved_fd_p')
|
20
|
-
have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
|
21
17
|
|
22
18
|
case RbConfig::CONFIG['host_os']
|
23
19
|
when /darwin/i
|
data/ext/io/extra.c
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
/* Extra methods for the IO class */
|
2
2
|
#include "ruby.h"
|
3
|
-
#ifdef HAVE_RUBY_IO_H
|
4
3
|
#include "ruby/io.h"
|
5
|
-
#
|
6
|
-
#include "rubyio.h"
|
7
|
-
#endif
|
4
|
+
#include "ruby/thread.h"
|
8
5
|
|
9
6
|
#include <unistd.h>
|
10
7
|
#include <stdlib.h>
|
@@ -26,69 +23,11 @@
|
|
26
23
|
#if defined(_SC_IOV_MAX)
|
27
24
|
#define IOV_MAX (sysconf(_SC_IOV_MAX))
|
28
25
|
#else
|
29
|
-
|
26
|
+
// Assume infinity, or let the syscall return with error
|
30
27
|
#define IOV_MAX INT_MAX
|
31
28
|
#endif
|
32
29
|
#endif
|
33
30
|
|
34
|
-
#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
|
35
|
-
#include <ruby/thread.h>
|
36
|
-
#endif
|
37
|
-
|
38
|
-
#if ! defined(HAVE_RB_THREAD_BLOCKING_REGION) && \
|
39
|
-
! defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
40
|
-
/*
|
41
|
-
* Partial emulation of the 1.9 rb_thread_blocking_region under 1.8,
|
42
|
-
* this is enough to ensure signals are processed safely when doing I/O
|
43
|
-
* to a slow device, but doesn't actually ensure threads can be
|
44
|
-
* scheduled fairly in 1.8.
|
45
|
-
*/
|
46
|
-
#include <rubysig.h>
|
47
|
-
#define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
|
48
|
-
typedef void rb_unblock_function_t(void *);
|
49
|
-
typedef VALUE rb_blocking_function_t(void *);
|
50
|
-
static VALUE
|
51
|
-
rb_thread_blocking_region(
|
52
|
-
rb_blocking_function_t *fn, void *data1,
|
53
|
-
rb_unblock_function_t *ubf, void *data2)
|
54
|
-
{
|
55
|
-
VALUE rv;
|
56
|
-
|
57
|
-
TRAP_BEG;
|
58
|
-
rv = fn(data1);
|
59
|
-
TRAP_END;
|
60
|
-
|
61
|
-
return rv;
|
62
|
-
}
|
63
|
-
#endif
|
64
|
-
|
65
|
-
#ifndef RSTRING_PTR
|
66
|
-
#define RSTRING_PTR(v) (RSTRING(v)->ptr)
|
67
|
-
#define RSTRING_LEN(v) (RSTRING(v)->len)
|
68
|
-
#endif
|
69
|
-
|
70
|
-
#ifndef HAVE_RB_STR_SET_LEN
|
71
|
-
/* this is taken from Ruby 1.8.7, 1.8.6 may not have it */
|
72
|
-
static void rb_18_str_set_len(VALUE str, long len)
|
73
|
-
{
|
74
|
-
RSTRING(str)->len = len;
|
75
|
-
RSTRING(str)->ptr[len] = '\0';
|
76
|
-
}
|
77
|
-
#define rb_str_set_len(str,len) rb_18_str_set_len(str,len)
|
78
|
-
#endif
|
79
|
-
|
80
|
-
/*
|
81
|
-
* Matz Ruby 1.9.3 has rb_reserved_fd_p() because it uses an internal
|
82
|
-
* timer thread + pipe to communicate signal wakeups (1.9.0 - 1.9.2
|
83
|
-
* wokeup every 10ms to check for signals). Accidentally closing this
|
84
|
-
* pipe breaks the VM completely, so we use this function to avoid it.
|
85
|
-
* This can be safely made a no-op for Ruby implementations that do
|
86
|
-
* not have this function (since it implies the VM does not reserve FDs)
|
87
|
-
*/
|
88
|
-
#ifndef RB_RESERVED_FD_P
|
89
|
-
#define RB_RESERVED_FD_P(fd) (0)
|
90
|
-
#endif
|
91
|
-
|
92
31
|
#ifdef PROC_SELF_FD_DIR
|
93
32
|
#include <dirent.h>
|
94
33
|
#endif
|
@@ -147,20 +86,16 @@ static int open_max(void){
|
|
147
86
|
* The manual approach was copied from the closefrom() man page on Solaris 9.
|
148
87
|
*/
|
149
88
|
static VALUE io_closefrom(VALUE klass, VALUE v_low_fd){
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
#else
|
154
|
-
int i, lowfd;
|
155
|
-
int maxfd = open_max();
|
156
|
-
lowfd = NUM2INT(v_low_fd);
|
89
|
+
int i, lowfd;
|
90
|
+
int maxfd = open_max();
|
91
|
+
lowfd = NUM2INT(v_low_fd);
|
157
92
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
93
|
+
for(i = lowfd; i < maxfd; i++) {
|
94
|
+
if(!RB_RESERVED_FD_P(i))
|
95
|
+
close(i);
|
96
|
+
}
|
97
|
+
|
98
|
+
return klass;
|
164
99
|
}
|
165
100
|
|
166
101
|
#ifndef HAVE_FDWALK
|
@@ -226,6 +161,7 @@ static int close_func(void* lowfd, int fd){
|
|
226
161
|
if(fd >= *(int*)lowfd){
|
227
162
|
if (RB_RESERVED_FD_P(fd))
|
228
163
|
return 0;
|
164
|
+
|
229
165
|
v_args[0] = UINT2NUM(fd);
|
230
166
|
rb_yield(rb_class_new_instance(1, v_args, rb_cFile));
|
231
167
|
}
|
@@ -242,15 +178,15 @@ static int close_func(void* lowfd, int fd){
|
|
242
178
|
* Not supported on all platforms.
|
243
179
|
*/
|
244
180
|
static VALUE io_fdwalk(int argc, VALUE* argv, VALUE klass){
|
245
|
-
|
246
|
-
|
181
|
+
VALUE v_low_fd, v_block;
|
182
|
+
int lowfd;
|
247
183
|
|
248
|
-
|
249
|
-
|
184
|
+
rb_scan_args(argc, argv, "1&", &v_low_fd, &v_block);
|
185
|
+
lowfd = NUM2INT(v_low_fd);
|
250
186
|
|
251
|
-
|
187
|
+
fdwalk(close_func, &lowfd);
|
252
188
|
|
253
|
-
|
189
|
+
return klass;
|
254
190
|
}
|
255
191
|
#endif
|
256
192
|
|
@@ -264,20 +200,20 @@ static VALUE io_fdwalk(int argc, VALUE* argv, VALUE klass){
|
|
264
200
|
*/
|
265
201
|
static VALUE io_get_directio(VALUE self){
|
266
202
|
#if defined(HAVE_DIRECTIO) || defined(F_NOCACHE)
|
267
|
-
|
203
|
+
VALUE v_advice = rb_iv_get(self, "@directio");
|
268
204
|
|
269
|
-
|
270
|
-
|
205
|
+
if(NIL_P(v_advice))
|
206
|
+
v_advice = Qfalse;
|
271
207
|
|
272
|
-
|
208
|
+
return v_advice;
|
273
209
|
#elif defined(O_DIRECT)
|
274
|
-
|
275
|
-
|
210
|
+
int fd = NUM2INT(rb_funcall(self, rb_intern("fileno"), 0, 0));
|
211
|
+
int flags = fcntl(fd, F_GETFL);
|
276
212
|
|
277
|
-
|
278
|
-
|
213
|
+
if(flags < 0)
|
214
|
+
rb_sys_fail("fcntl");
|
279
215
|
|
280
|
-
|
216
|
+
return (flags & O_DIRECT) ? Qtrue : Qfalse;
|
281
217
|
#endif /* O_DIRECT */
|
282
218
|
}
|
283
219
|
|
@@ -350,17 +286,16 @@ static VALUE io_set_directio(VALUE self, VALUE v_advice){
|
|
350
286
|
|
351
287
|
#ifdef HAVE_PREAD
|
352
288
|
struct pread_args {
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
289
|
+
int fd;
|
290
|
+
void *buf;
|
291
|
+
size_t nbyte;
|
292
|
+
off_t offset;
|
357
293
|
};
|
358
294
|
|
359
295
|
static VALUE nogvl_pread(void *ptr)
|
360
296
|
{
|
361
|
-
|
362
|
-
|
363
|
-
return (VALUE)pread(args->fd, args->buf, args->nbyte, args->offset);
|
297
|
+
struct pread_args *args = ptr;
|
298
|
+
return (VALUE)pread(args->fd, args->buf, args->nbyte, args->offset);
|
364
299
|
}
|
365
300
|
|
366
301
|
/*
|
@@ -371,28 +306,25 @@ static VALUE nogvl_pread(void *ptr)
|
|
371
306
|
* the +fd+, +length+ and +offset+ arguments are all mandatory.
|
372
307
|
*/
|
373
308
|
static VALUE s_io_pread(VALUE klass, VALUE fd, VALUE nbyte, VALUE offset){
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
#endif
|
309
|
+
struct pread_args args;
|
310
|
+
VALUE str;
|
311
|
+
ssize_t nread;
|
312
|
+
|
313
|
+
args.fd = NUM2INT(fd);
|
314
|
+
args.nbyte = NUM2ULONG(nbyte);
|
315
|
+
args.offset = NUM2OFFT(offset);
|
316
|
+
str = rb_str_new(NULL, args.nbyte);
|
317
|
+
args.buf = RSTRING_PTR(str);
|
318
|
+
|
319
|
+
nread = (ssize_t)rb_thread_call_without_gvl((void*)nogvl_pread, &args, RUBY_UBF_IO, 0);
|
320
|
+
|
321
|
+
if(nread == -1)
|
322
|
+
rb_sys_fail("pread");
|
389
323
|
|
390
|
-
|
391
|
-
|
392
|
-
if ((size_t)nread != args.nbyte)
|
393
|
-
rb_str_set_len(str, nread);
|
324
|
+
if((size_t)nread != args.nbyte)
|
325
|
+
rb_str_set_len(str, nread);
|
394
326
|
|
395
|
-
|
327
|
+
return str;
|
396
328
|
}
|
397
329
|
|
398
330
|
/*
|
@@ -422,17 +354,16 @@ static VALUE s_io_pread_ptr(VALUE klass, VALUE v_fd, VALUE v_nbyte, VALUE v_offs
|
|
422
354
|
|
423
355
|
#ifdef HAVE_PWRITE
|
424
356
|
struct pwrite_args {
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
357
|
+
int fd;
|
358
|
+
const void *buf;
|
359
|
+
size_t nbyte;
|
360
|
+
off_t offset;
|
429
361
|
};
|
430
362
|
|
431
363
|
static VALUE nogvl_pwrite(void *ptr)
|
432
364
|
{
|
433
|
-
|
434
|
-
|
435
|
-
return (VALUE)pwrite(args->fd, args->buf, args->nbyte, args->offset);
|
365
|
+
struct pwrite_args *args = ptr;
|
366
|
+
return (VALUE)pwrite(args->fd, args->buf, args->nbyte, args->offset);
|
436
367
|
}
|
437
368
|
|
438
369
|
/*
|
@@ -447,24 +378,20 @@ static VALUE nogvl_pwrite(void *ptr)
|
|
447
378
|
* Returns the number of bytes written.
|
448
379
|
*/
|
449
380
|
static VALUE s_io_pwrite(VALUE klass, VALUE fd, VALUE buf, VALUE offset){
|
450
|
-
|
451
|
-
|
381
|
+
ssize_t result;
|
382
|
+
struct pwrite_args args;
|
452
383
|
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
384
|
+
args.fd = NUM2INT(fd);
|
385
|
+
args.buf = RSTRING_PTR(buf);
|
386
|
+
args.nbyte = RSTRING_LEN(buf);
|
387
|
+
args.offset = NUM2OFFT(offset);
|
457
388
|
|
458
|
-
|
459
|
-
result = (ssize_t)rb_thread_call_without_gvl((void*)nogvl_pwrite, &args, RUBY_UBF_IO, 0);
|
460
|
-
#else
|
461
|
-
result = (ssize_t)rb_thread_blocking_region(nogvl_pwrite, &args, RUBY_UBF_IO, 0);
|
462
|
-
#endif
|
389
|
+
result = (ssize_t)rb_thread_call_without_gvl((void*)nogvl_pwrite, &args, RUBY_UBF_IO, 0);
|
463
390
|
|
464
|
-
|
465
|
-
|
391
|
+
if(result == -1)
|
392
|
+
rb_sys_fail("pwrite");
|
466
393
|
|
467
|
-
|
394
|
+
return ULL2NUM(result);
|
468
395
|
}
|
469
396
|
#endif
|
470
397
|
|
@@ -494,16 +421,15 @@ static VALUE s_io_pwrite(VALUE klass, VALUE fd, VALUE buf, VALUE offset){
|
|
494
421
|
|
495
422
|
#if defined(HAVE_WRITEV)
|
496
423
|
struct writev_args {
|
497
|
-
|
498
|
-
|
499
|
-
|
424
|
+
int fd;
|
425
|
+
struct iovec *iov;
|
426
|
+
int iovcnt;
|
500
427
|
};
|
501
428
|
|
502
429
|
static VALUE nogvl_writev(void *ptr)
|
503
430
|
{
|
504
|
-
|
505
|
-
|
506
|
-
return (VALUE)writev(args->fd, args->iov, args->iovcnt);
|
431
|
+
struct writev_args *args = ptr;
|
432
|
+
return (VALUE)writev(args->fd, args->iov, args->iovcnt);
|
507
433
|
}
|
508
434
|
|
509
435
|
/*
|
@@ -518,75 +444,68 @@ static VALUE nogvl_writev(void *ptr)
|
|
518
444
|
* Returns the number of bytes written.
|
519
445
|
*/
|
520
446
|
static VALUE s_io_writev(VALUE klass, VALUE fd, VALUE ary) {
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
args.fd = NUM2INT(fd);
|
526
|
-
ARY2IOVEC(args.iov, args.iovcnt, left, ary);
|
527
|
-
|
528
|
-
for(;;) {
|
529
|
-
#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
|
530
|
-
ssize_t w = (ssize_t)rb_thread_call_without_gvl(
|
531
|
-
(void*)nogvl_writev, &args, RUBY_UBF_IO, 0
|
532
|
-
);
|
533
|
-
#else
|
534
|
-
ssize_t w = (ssize_t)rb_thread_blocking_region(
|
535
|
-
nogvl_writev, &args, RUBY_UBF_IO, 0
|
536
|
-
);
|
537
|
-
#endif
|
447
|
+
ssize_t result = 0;
|
448
|
+
ssize_t left;
|
449
|
+
struct writev_args args;
|
538
450
|
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
451
|
+
args.fd = NUM2INT(fd);
|
452
|
+
ARY2IOVEC(args.iov, args.iovcnt, left, ary);
|
453
|
+
|
454
|
+
for(;;) {
|
455
|
+
ssize_t w = (ssize_t)rb_thread_call_without_gvl(
|
456
|
+
(void*)nogvl_writev, &args, RUBY_UBF_IO, 0
|
457
|
+
);
|
458
|
+
|
459
|
+
if(w == -1){
|
460
|
+
if(rb_io_wait_writable(args.fd)){
|
461
|
+
continue;
|
462
|
+
}
|
463
|
+
else{
|
464
|
+
if(result > 0){
|
465
|
+
/* unlikely to hit this case, return the already written bytes,
|
466
|
+
* we'll let the next write (or close) fail instead */
|
467
|
+
break;
|
468
|
+
}
|
469
|
+
rb_sys_fail("writev");
|
552
470
|
}
|
471
|
+
}
|
553
472
|
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
/* skip over iovecs we've already written completely */
|
564
|
-
for (i = 0; i < args.iovcnt; i++, new_iov++) {
|
565
|
-
if (w == 0)
|
566
|
-
break;
|
567
|
-
|
568
|
-
/*
|
569
|
-
* partially written iov,
|
570
|
-
* modify and retry with current iovec in front
|
571
|
-
*/
|
572
|
-
if (new_iov->iov_len > (size_t)w) {
|
573
|
-
VALUE base = (VALUE)new_iov->iov_base;
|
574
|
-
|
575
|
-
new_iov->iov_len -= w;
|
576
|
-
new_iov->iov_base = (void *)(base + w);
|
577
|
-
break;
|
578
|
-
}
|
579
|
-
|
580
|
-
w -= new_iov->iov_len;
|
581
|
-
}
|
473
|
+
result += w;
|
474
|
+
|
475
|
+
if(w == left){
|
476
|
+
break;
|
477
|
+
}
|
478
|
+
else{
|
479
|
+
// Partial write, this can get tricky
|
480
|
+
int i;
|
481
|
+
struct iovec *new_iov = args.iov;
|
582
482
|
|
583
|
-
|
584
|
-
|
585
|
-
|
483
|
+
left -= w;
|
484
|
+
|
485
|
+
// Skip over iovecs we've already written completely
|
486
|
+
for(i = 0; i < args.iovcnt; i++, new_iov++){
|
487
|
+
if (w == 0)
|
488
|
+
break;
|
489
|
+
|
490
|
+
// Partially written iov, modify and retry with current iovec in front
|
491
|
+
if(new_iov->iov_len > (size_t)w){
|
492
|
+
VALUE base = (VALUE)new_iov->iov_base;
|
493
|
+
|
494
|
+
new_iov->iov_len -= w;
|
495
|
+
new_iov->iov_base = (void *)(base + w);
|
496
|
+
break;
|
497
|
+
}
|
498
|
+
|
499
|
+
w -= new_iov->iov_len;
|
586
500
|
}
|
587
|
-
}
|
588
501
|
|
589
|
-
|
502
|
+
// Retry without the already-written iovecs
|
503
|
+
args.iovcnt -= i;
|
504
|
+
args.iov = new_iov;
|
505
|
+
}
|
506
|
+
}
|
507
|
+
|
508
|
+
return LONG2NUM(result);
|
590
509
|
}
|
591
510
|
#endif
|
592
511
|
|
@@ -617,47 +536,47 @@ static VALUE io_get_ttyname(VALUE self){
|
|
617
536
|
* and IO#directio? instance methods (if supported on your platform).
|
618
537
|
*/
|
619
538
|
void Init_extra(){
|
620
|
-
|
539
|
+
rb_define_singleton_method(rb_cIO, "closefrom", io_closefrom, 1);
|
621
540
|
|
622
541
|
#ifdef HAVE_FDWALK
|
623
|
-
|
542
|
+
rb_define_singleton_method(rb_cIO, "fdwalk", io_fdwalk, -1);
|
624
543
|
#endif
|
625
544
|
|
626
545
|
#if defined(HAVE_DIRECTIO) || defined(O_DIRECT) || defined(F_NOCACHE)
|
627
|
-
|
628
|
-
|
546
|
+
rb_define_method(rb_cIO, "directio?", io_get_directio, 0);
|
547
|
+
rb_define_method(rb_cIO, "directio=", io_set_directio, 1);
|
629
548
|
|
630
|
-
|
631
|
-
|
549
|
+
/* 0: Applications get the default system behavior when accessing file data. */
|
550
|
+
rb_define_const(rb_cIO, "DIRECTIO_OFF", UINT2NUM(DIRECTIO_OFF));
|
632
551
|
|
633
|
-
|
634
|
-
|
552
|
+
/* 1: File data is not cached in the system's memory pages. */
|
553
|
+
rb_define_const(rb_cIO, "DIRECTIO_ON", UINT2NUM(DIRECTIO_ON));
|
635
554
|
#endif
|
636
555
|
|
637
556
|
#ifdef O_DIRECT
|
638
|
-
|
639
|
-
|
557
|
+
/* 040000: direct disk access (in Linux) */
|
558
|
+
rb_define_const(rb_cIO, "DIRECT", UINT2NUM(O_DIRECT));
|
640
559
|
#endif
|
641
560
|
|
642
|
-
|
561
|
+
rb_define_const(rb_cIO, "IOV_MAX", LONG2NUM(IOV_MAX));
|
643
562
|
|
644
563
|
#ifdef HAVE_PREAD
|
645
|
-
|
646
|
-
|
564
|
+
rb_define_singleton_method(rb_cIO, "pread", s_io_pread, 3);
|
565
|
+
rb_define_singleton_method(rb_cIO, "pread_ptr", s_io_pread_ptr, 3);
|
647
566
|
#endif
|
648
567
|
|
649
568
|
#ifdef HAVE_PWRITE
|
650
|
-
|
569
|
+
rb_define_singleton_method(rb_cIO, "pwrite", s_io_pwrite, 3);
|
651
570
|
#endif
|
652
571
|
|
653
572
|
#ifdef HAVE_WRITEV
|
654
|
-
|
573
|
+
rb_define_singleton_method(rb_cIO, "writev", s_io_writev, 2);
|
655
574
|
#endif
|
656
575
|
|
657
576
|
#ifdef HAVE_TTYNAME
|
658
577
|
rb_define_method(rb_cIO, "ttyname", io_get_ttyname, 0);
|
659
578
|
#endif
|
660
579
|
|
661
|
-
|
662
|
-
|
580
|
+
/* 1.3.0: The version of this library. */
|
581
|
+
rb_define_const(rb_cIO, "EXTRA_VERSION", rb_str_freeze(rb_str_new2("1.3.0")));
|
663
582
|
}
|
data/lib/io-extra.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'io/extra'
|
data/test/test_io_extra.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io-extra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel J. Berger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
|
-
cert_chain:
|
11
|
-
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MREwDwYDVQQDDAhkamJl
|
14
|
+
cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
|
15
|
+
MB4XDTE4MDMxODE1MjIwN1oXDTI4MDMxNTE1MjIwN1owPzERMA8GA1UEAwwIZGpi
|
16
|
+
ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
|
17
|
+
bTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALgfaroVM6CI06cxr0/h
|
18
|
+
A+j+pc8fgpRgBVmHFaFunq28GPC3IvW7Nvc3Y8SnAW7pP1EQIbhlwRIaQzJ93/yj
|
19
|
+
u95KpkP7tA9erypnV7dpzBkzNlX14ACaFD/6pHoXoe2ltBxk3CCyyzx70mTqJpph
|
20
|
+
75IB03ni9a8yqn8pmse+s83bFJOAqddSj009sGPcQO+QOWiNxqYv1n5EHcvj2ebO
|
21
|
+
6hN7YTmhx7aSia4qL/quc4DlIaGMWoAhvML7u1fmo53CYxkKskfN8MOecq2vfEmL
|
22
|
+
iLu+SsVVEAufMDDFMXMJlvDsviolUSGMSNRTujkyCcJoXKYYxZSNtIiyd9etI0X3
|
23
|
+
ctu0uhrFyrMZXCedutvXNjUolD5r9KGBFSWH1R9u2I3n3SAyFF2yzv/7idQHLJJq
|
24
|
+
74BMnx0FIq6fCpu5slAipvxZ3ZkZpEXZFr3cIBtO1gFvQWW7E/Y3ijliWJS1GQFq
|
25
|
+
058qERadHGu1yu1dojmFRo6W2KZvY9al2yIlbkpDrD5MYQIDAQABo3cwdTAJBgNV
|
26
|
+
HRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUFZsMapgzJimzsbaBG2Tm8j5e
|
27
|
+
AzgwHQYDVR0RBBYwFIESZGpiZXJnOTZAZ21haWwuY29tMB0GA1UdEgQWMBSBEmRq
|
28
|
+
YmVyZzk2QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAW2tnYixXQtKxgGXq
|
29
|
+
/3iSWG2bLwvxS4go3srO+aRXZHrFUMlJ5W0mCxl03aazxxKTsVVpZD8QZxvK91OQ
|
30
|
+
h9zr9JBYqCLcCVbr8SkmYCi/laxIZxsNE5YI8cC8vvlLI7AMgSfPSnn/Epq1GjGY
|
31
|
+
6L1iRcEDtanGCIvjqlCXO9+BmsnCfEVehqZkQHeYczA03tpOWb6pon2wzvMKSsKH
|
32
|
+
ks0ApVdstSLz1kzzAqem/uHdG9FyXdbTAwH1G4ZPv69sQAFAOCgAqYmdnzedsQtE
|
33
|
+
1LQfaQrx0twO+CZJPcRLEESjq8ScQxWRRkfuh2VeR7cEU7L7KqT10mtUwrvw7APf
|
34
|
+
DYoeCY9KyjIBjQXfbj2ke5u1hZj94Fsq9FfbEQg8ygCgwThnmkTrrKEiMSs3alYR
|
35
|
+
ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
|
36
|
+
WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
|
37
|
+
-----END CERTIFICATE-----
|
38
|
+
date: 2018-10-19 00:00:00.000000000 Z
|
12
39
|
dependencies:
|
13
40
|
- !ruby/object:Gem::Dependency
|
14
41
|
name: test-unit
|
@@ -38,22 +65,17 @@ extra_rdoc_files:
|
|
38
65
|
- MANIFEST
|
39
66
|
- ext/io/extra.c
|
40
67
|
files:
|
41
|
-
-
|
42
|
-
-
|
43
|
-
- MANIFEST
|
44
|
-
- README
|
45
|
-
- Rakefile
|
46
|
-
- doc/io_extra.txt
|
47
|
-
- examples/example_io_extra.rb
|
48
|
-
- examples/example_pread.rb
|
49
|
-
- ext/extconf.rb
|
50
|
-
- ext/io/extra.c
|
51
|
-
- io-extra.gemspec
|
52
|
-
- test/test_io_extra.rb
|
53
|
-
homepage: http://www.rubyforge.org/projects/shards
|
68
|
+
- lib/io-extra.rb
|
69
|
+
homepage: https://github.com/djberg96/io-extra
|
54
70
|
licenses:
|
55
|
-
-
|
56
|
-
metadata:
|
71
|
+
- Apache-2.0
|
72
|
+
metadata:
|
73
|
+
homepage_uri: https://github.com/djberg96/io-extra
|
74
|
+
bug_tracker_uri: https://github.com/djberg96/io-extra/issues
|
75
|
+
changelog_uri: https://github.com/djberg96/io-extra/blob/master/CHANGES
|
76
|
+
documentation_uri: https://github.com/djberg96/io-extra/wiki
|
77
|
+
source_code_uri: https://github.com/djberg96/io-extra
|
78
|
+
wiki_uri: https://github.com/djberg96/io-extra/wiki
|
57
79
|
post_install_message:
|
58
80
|
rdoc_options: []
|
59
81
|
require_paths:
|
@@ -62,17 +84,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
62
84
|
requirements:
|
63
85
|
- - ">="
|
64
86
|
- !ruby/object:Gem::Version
|
65
|
-
version: 1.
|
87
|
+
version: 2.1.0
|
66
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
89
|
requirements:
|
68
90
|
- - ">="
|
69
91
|
- !ruby/object:Gem::Version
|
70
92
|
version: '0'
|
71
93
|
requirements: []
|
72
|
-
rubyforge_project:
|
73
|
-
rubygems_version: 2.
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 2.7.6
|
74
96
|
signing_key:
|
75
97
|
specification_version: 4
|
76
|
-
summary: Adds extra methods to the IO class
|
98
|
+
summary: Adds extra methods to the IO class
|
77
99
|
test_files:
|
78
100
|
- test/test_io_extra.rb
|
metadata.gz.sig
ADDED
Binary file
|
data/.gemtest
DELETED
File without changes
|
data/Rakefile
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
require 'rake'
|
2
|
-
require 'rake/clean'
|
3
|
-
require 'rake/testtask'
|
4
|
-
require 'rbconfig'
|
5
|
-
include RbConfig
|
6
|
-
|
7
|
-
CLEAN.include(
|
8
|
-
'**/*.gem', # Gem files
|
9
|
-
'**/*.rbc', # Rubinius
|
10
|
-
'**/*.o', # C object file
|
11
|
-
'**/*.log', # Ruby extension build log
|
12
|
-
'**/Makefile', # C Makefile
|
13
|
-
'**/conftest.dSYM', # OS X build directory
|
14
|
-
"**/*.#{CONFIG['DLEXT']}" # C shared object
|
15
|
-
)
|
16
|
-
|
17
|
-
if File::ALT_SEPARATOR
|
18
|
-
STDERR.puts 'Not supported on this platform. Exiting.'
|
19
|
-
exit(-1)
|
20
|
-
end
|
21
|
-
|
22
|
-
desc "Build the io-extra library (but don't install it)"
|
23
|
-
task :build => [:clean] do
|
24
|
-
Dir.chdir('ext') do
|
25
|
-
ruby 'extconf.rb'
|
26
|
-
sh 'make'
|
27
|
-
build_file = File.join(Dir.pwd, 'extra.' + CONFIG['DLEXT'])
|
28
|
-
Dir.mkdir('io') unless File.exists?('io')
|
29
|
-
FileUtils.cp(build_file, 'io')
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
namespace :gem do
|
34
|
-
desc 'Create the io-extra gem'
|
35
|
-
task :create => [:clean] do
|
36
|
-
spec = eval(IO.read('io-extra.gemspec'))
|
37
|
-
if Gem::VERSION.to_f >= 2.0
|
38
|
-
require 'rubygems/package'
|
39
|
-
Gem::Package.build(spec)
|
40
|
-
else
|
41
|
-
Gem::Builder.new(spec).build
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
desc "Install the io-extra library as a gem"
|
46
|
-
task :install => [:create] do
|
47
|
-
file = Dir["io-extra*.gem"].last
|
48
|
-
sh "gem install -l #{file}"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
namespace :archive do
|
53
|
-
spec = eval(IO.read('io-extra.gemspec'))
|
54
|
-
file = "io-extra-#{spec.version}"
|
55
|
-
|
56
|
-
desc 'Create an io-extra tarball.'
|
57
|
-
task :tar do
|
58
|
-
file = file + ".tar"
|
59
|
-
cmd = "git archive --format=tar --prefix=#{file}/ -o #{file} HEAD"
|
60
|
-
sh cmd
|
61
|
-
end
|
62
|
-
|
63
|
-
desc 'Create a gzipped tarball for io-extra'
|
64
|
-
task :gz => [:tar] do
|
65
|
-
sh "gzip #{file}"
|
66
|
-
end
|
67
|
-
|
68
|
-
desc 'Create a bzip2 tarball for io-extra'
|
69
|
-
task :bz2 => [:tar] do
|
70
|
-
sh "bzip2 #{file}"
|
71
|
-
end
|
72
|
-
|
73
|
-
desc 'Create a zipped tarball for io-extra'
|
74
|
-
task :zip do
|
75
|
-
sh "git archive --format=zip --prefix=#{file}/ -o #{file}.zip HEAD"
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
desc "Run the example io-extra program"
|
80
|
-
task :example => [:build] do
|
81
|
-
ruby '-Iext examples/example_io_extra.rb'
|
82
|
-
end
|
83
|
-
|
84
|
-
namespace :example do
|
85
|
-
desc "Run the IO.pread example program."
|
86
|
-
task :pread do
|
87
|
-
ruby '-Iext examples/example_io_extra.rb'
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
Rake::TestTask.new do |t|
|
92
|
-
task :test => :build
|
93
|
-
t.libs << 'ext'
|
94
|
-
t.verbose = true
|
95
|
-
t.warning = true
|
96
|
-
end
|
97
|
-
|
98
|
-
task :default => :test
|
data/doc/io_extra.txt
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
= Description
|
2
|
-
The io-extra library provides a few extra IO methods that you may find
|
3
|
-
handy.
|
4
|
-
|
5
|
-
= Supported Platforms
|
6
|
-
Works on most Unix platforms.
|
7
|
-
|
8
|
-
Not supported on MS Windows or OS X.
|
9
|
-
|
10
|
-
= Synopsis
|
11
|
-
require "io/extra"
|
12
|
-
|
13
|
-
# Print the fileno of each file handle and then close it
|
14
|
-
IO.fdwalk(0){ |fh|
|
15
|
-
p fh.fileno
|
16
|
-
fh.close
|
17
|
-
}
|
18
|
-
|
19
|
-
# Close all file handles with a fileno greater than or equal to 2.
|
20
|
-
IO.closefrom(2)
|
21
|
-
|
22
|
-
= Class Methods
|
23
|
-
IO.closefrom(low_fd)
|
24
|
-
Closes all open file descriptors greater than or equal to 'low_fd'.
|
25
|
-
|
26
|
-
This uses your systems native closefrom() function, if supported. If not,
|
27
|
-
this method uses a slightly less efficient manual approach that uses
|
28
|
-
getrlimit() behind the scenes.
|
29
|
-
|
30
|
-
IO.fdwalk(low_fd){ |fh| ... }
|
31
|
-
Iterates over each open file descriptor and yields back a File object.
|
32
|
-
Note that it is up to you to close file handles, if desired, when this
|
33
|
-
method is used.
|
34
|
-
|
35
|
-
Not supported on all platforms.
|
36
|
-
|
37
|
-
IO.pread(fd, length, offset)
|
38
|
-
Reads +length+ bytes of data from the given +fd+, starting at +offset.
|
39
|
-
The primary advantage of this method over Ruby's IO#read method is that
|
40
|
-
it performs the read without changing the file pointer.
|
41
|
-
|
42
|
-
Not supported on all platforms.
|
43
|
-
|
44
|
-
IO.pwrite(fd, buf, offset)
|
45
|
-
Writes +buf+ to the given +fd+, starting at +offset. The primary advantage
|
46
|
-
of this method over a standard seek & write approach is that it performs
|
47
|
-
the write without changing the file pointer.
|
48
|
-
|
49
|
-
Not supported on all platforms.
|
50
|
-
|
51
|
-
= Instance methods
|
52
|
-
IO#directio?
|
53
|
-
Returns true or false, based on whether directio has been set for the
|
54
|
-
current handle. The default is false.
|
55
|
-
|
56
|
-
Note supported on all platforms.
|
57
|
-
|
58
|
-
IO#directio=(io_const)
|
59
|
-
Sets the advice for the current file descriptor using directio(). Valid
|
60
|
-
values are IO::DIRECTIO_ON and IO::DIRECTIO_OFF.
|
61
|
-
|
62
|
-
All file descriptors start at DIRECTIO_OFF, unless your filesystem has
|
63
|
-
been mounted using 'forcedirectio' (and supports that option).
|
64
|
-
|
65
|
-
Not supported on all platforms
|
66
|
-
|
67
|
-
= Constants
|
68
|
-
IO::DIRECTIO_ON
|
69
|
-
This value can be passed to IO#directio= in order to turn directio on for
|
70
|
-
the given file handle.
|
71
|
-
|
72
|
-
This value is only defined if your platform supports the directio()
|
73
|
-
function.
|
74
|
-
IO::DIRECTIO_OFF
|
75
|
-
This value can be passed to IO#directio= in order to turn directio off for
|
76
|
-
the given file handle.
|
77
|
-
|
78
|
-
This value is only defined if your platform supports the directio()
|
79
|
-
function.
|
80
|
-
|
81
|
-
IO::EXTRA_VERSION
|
82
|
-
Returns the current version number of this library as a String.
|
83
|
-
|
84
|
-
= Other documentation
|
85
|
-
See the README for more documentation.
|
@@ -1,42 +0,0 @@
|
|
1
|
-
##############################################################################
|
2
|
-
# test.rb
|
3
|
-
#
|
4
|
-
# This is a small test program for the io-extra library. Modify as you see
|
5
|
-
# fit. You can run this via the 'rake example' task.
|
6
|
-
##############################################################################
|
7
|
-
require "io/extra"
|
8
|
-
p IO::EXTRA_VERSION
|
9
|
-
|
10
|
-
fh = File.open("foo.txt","w+")
|
11
|
-
|
12
|
-
=begin
|
13
|
-
p fh.directio?
|
14
|
-
|
15
|
-
fh.directio = IO::DIRECTIO_ON
|
16
|
-
p fh.directio?
|
17
|
-
|
18
|
-
fh.close
|
19
|
-
=end
|
20
|
-
|
21
|
-
IO.fdwalk(0){ |handle|
|
22
|
-
p handle
|
23
|
-
p handle.fileno
|
24
|
-
puts
|
25
|
-
}
|
26
|
-
|
27
|
-
=begin
|
28
|
-
STDIN.close
|
29
|
-
|
30
|
-
# Should print "Hello" 2 times
|
31
|
-
IO.fdwalk(0){ |fd|
|
32
|
-
puts "Hello #{fd}"
|
33
|
-
}
|
34
|
-
|
35
|
-
|
36
|
-
IO.closefrom(0)
|
37
|
-
|
38
|
-
puts "Done" # Shouldn't see this
|
39
|
-
=end
|
40
|
-
|
41
|
-
fh.close
|
42
|
-
File.delete("foo.txt") if File.exists?("foo.txt")
|
data/examples/example_pread.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
########################################################################
|
2
|
-
# example_pread.rb
|
3
|
-
#
|
4
|
-
# Example program demonstrating the use of IO.pread.
|
5
|
-
########################################################################
|
6
|
-
require 'io/extra'
|
7
|
-
require 'tmpdir'
|
8
|
-
|
9
|
-
# Create a temporary file with a little data in it.
|
10
|
-
file = File.join(Dir.tmpdir, 'pread_test.txt')
|
11
|
-
File.open(file, 'w'){ |fh| 100.times{ |n| fh.puts "Hello: #{n}" } }
|
12
|
-
|
13
|
-
# Read from the file using pread.
|
14
|
-
begin
|
15
|
-
fh = File.open(file)
|
16
|
-
|
17
|
-
puts "Handle position before read: #{fh.pos}"
|
18
|
-
puts IO.pread(fh.fileno, 18, 0)
|
19
|
-
|
20
|
-
puts "Handle position after read: #{fh.pos}"
|
21
|
-
puts IO.pread(fh.fileno, 18, 0)
|
22
|
-
ensure
|
23
|
-
fh.close
|
24
|
-
end
|
data/io-extra.gemspec
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'rbconfig'
|
3
|
-
|
4
|
-
Gem::Specification.new do |spec|
|
5
|
-
if File::ALT_SEPARATOR
|
6
|
-
STDERR.puts 'Not supported on this platform. Exiting.'
|
7
|
-
exit(-1)
|
8
|
-
end
|
9
|
-
|
10
|
-
spec.name = 'io-extra'
|
11
|
-
spec.version = '1.2.8'
|
12
|
-
spec.author = 'Daniel J. Berger'
|
13
|
-
spec.license = 'Artistic 2.0'
|
14
|
-
spec.email = 'djberg96@gmail.com'
|
15
|
-
spec.homepage = 'http://www.rubyforge.org/projects/shards'
|
16
|
-
spec.summary = 'Adds extra methods to the IO class.'
|
17
|
-
spec.test_file = 'test/test_io_extra.rb'
|
18
|
-
spec.extensions = ['ext/extconf.rb']
|
19
|
-
spec.files = Dir['**/*'] << '.gemtest'
|
20
|
-
|
21
|
-
spec.extra_rdoc_files = [
|
22
|
-
'CHANGES',
|
23
|
-
'README',
|
24
|
-
'MANIFEST',
|
25
|
-
'ext/io/extra.c'
|
26
|
-
]
|
27
|
-
|
28
|
-
spec.rubyforge_project = 'shards'
|
29
|
-
spec.required_ruby_version = '>= 1.8.6'
|
30
|
-
|
31
|
-
spec.add_development_dependency('test-unit', '>= 2.5.0')
|
32
|
-
|
33
|
-
spec.description = <<-EOF
|
34
|
-
Adds the IO.closefrom, IO.fdwalk, IO.pread, IO.pread_ptr, IO.pwrite, and
|
35
|
-
IO.writev singleton methods as well as the IO#directio, IO#directio? and
|
36
|
-
IO#ttyname instance methods (for those platforms that support them).
|
37
|
-
EOF
|
38
|
-
end
|