io-extra 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +10 -0
- data/MANIFEST +1 -1
- data/README +15 -6
- data/Rakefile +61 -0
- data/examples/example_io_extra.rb +42 -0
- data/ext/extconf.rb +19 -1
- data/ext/io/extra.c +170 -24
- data/io-extra.gemspec +42 -0
- data/test/test_io_extra.rb +59 -26
- metadata +27 -11
data/CHANGES
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
== 1.2.0 - 28-Jul-2009
|
2
|
+
* Several Linux compatibility fixes, all provided by Eric Wong.
|
3
|
+
* Now compatible with 1.9.x thanks to Eric Wong.
|
4
|
+
* Bug fix for IO.pread - memory leak and null byte behavior spotted and
|
5
|
+
fixed by Eric Wong.
|
6
|
+
* Changed license to Artistic 2.0.
|
7
|
+
* Added test-unit 2.x as a development dependency.
|
8
|
+
* Several tests were updated to use features from test-unit 2.x.
|
9
|
+
* Fixed the 'example' rake task.
|
10
|
+
|
1
11
|
== 1.1.1 - 8-Sep-2008
|
2
12
|
* Added the IO.pread_ptr method. This returns the buffer address
|
3
13
|
rather than the buffer itself.
|
data/MANIFEST
CHANGED
data/README
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
The io-extra library provides a few extra IO methods that you may find
|
3
3
|
handy. They are IO.closefrom, IO.fdwalk, IO#directio? and IO#directio=.
|
4
4
|
|
5
|
-
Not supported on MS Windows
|
5
|
+
Not supported on MS Windows.
|
6
|
+
|
7
|
+
Limited support for OS X.
|
6
8
|
|
7
9
|
= Installation
|
8
10
|
== Standard Installation
|
@@ -10,6 +12,9 @@ Not supported on MS Windows or OS X.
|
|
10
12
|
rake install
|
11
13
|
|
12
14
|
== Gem Installation
|
15
|
+
=== Remote
|
16
|
+
gem install io-extra
|
17
|
+
=== Local
|
13
18
|
rake test (optional)
|
14
19
|
rake install_gem
|
15
20
|
|
@@ -51,17 +56,21 @@ For further documentation, see the io_extra.txt file or the inline
|
|
51
56
|
documentation that was generated by RDoc (if you did a gem install).
|
52
57
|
|
53
58
|
= Known Issues
|
54
|
-
None that I'm aware of. Please file any bug
|
55
|
-
at http://www.rubyforge.org/projects/shards.
|
59
|
+
None that I'm aware of (beyond those documented above). Please file any bug
|
60
|
+
reports on the project page at http://www.rubyforge.org/projects/shards.
|
56
61
|
|
57
62
|
= Future Plans
|
58
|
-
I may add the File::O_DIRECT open constant on platforms that support it.
|
63
|
+
* I may add the File::O_DIRECT open constant on platforms that support it.
|
64
|
+
* Switch from C extension to FFI.
|
65
|
+
|
66
|
+
= Acknowledgements
|
67
|
+
Eric Wong for some great work on Linux compatibility and other fixes.
|
59
68
|
|
60
69
|
= License
|
61
|
-
|
70
|
+
Artistic 2.0
|
62
71
|
|
63
72
|
= Copyright
|
64
|
-
(C) 2003-
|
73
|
+
(C) 2003-2009 Daniel J. Berger
|
65
74
|
All Rights Reserved
|
66
75
|
|
67
76
|
= Warranty
|
data/Rakefile
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/clean'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rbconfig'
|
5
|
+
include Config
|
6
|
+
|
7
|
+
case RUBY_PLATFORM
|
8
|
+
when /mswin/i
|
9
|
+
STDERR.puts 'Not supported on this platform. Exiting.'
|
10
|
+
exit(-1)
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Clean the build files for the io-extra source"
|
14
|
+
task :clean do
|
15
|
+
FileUtils.rm_rf('io') if File.exists?('io')
|
16
|
+
Dir.chdir('ext') do
|
17
|
+
sh 'make distclean' if File.exists?('extra.o')
|
18
|
+
|
19
|
+
FileUtils.rm_rf('extra/extra.c') if File.exists?('extra.c')
|
20
|
+
|
21
|
+
build_file = File.join(Dir.pwd, 'io', 'extra.' + Config::CONFIG['DLEXT'])
|
22
|
+
File.delete(build_file) if File.exists?(build_file)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Build the io-extra library (but don't install it)"
|
27
|
+
task :build => [:clean] do
|
28
|
+
Dir.chdir('ext') do
|
29
|
+
ruby 'extconf.rb'
|
30
|
+
sh 'make'
|
31
|
+
build_file = File.join(Dir.pwd, 'extra.' + Config::CONFIG['DLEXT'])
|
32
|
+
Dir.mkdir('io') unless File.exists?('io')
|
33
|
+
FileUtils.cp(build_file, 'io')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Install the io-extra package (non-gem)"
|
38
|
+
task :install => [:build] do
|
39
|
+
Dir.chdir('ext') do
|
40
|
+
sh 'make install'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "Install the io-extra package as a gem"
|
45
|
+
task :install_gem do
|
46
|
+
ruby 'io-extra.gemspec'
|
47
|
+
file = Dir["io-extra*.gem"].last
|
48
|
+
sh "gem install #{file}"
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Run the example io-extra program"
|
52
|
+
task :example => [:build] do
|
53
|
+
ruby '-Iext examples/example_io_extra.rb'
|
54
|
+
end
|
55
|
+
|
56
|
+
Rake::TestTask.new do |t|
|
57
|
+
task :test => :build
|
58
|
+
t.libs << 'ext'
|
59
|
+
t.verbose = true
|
60
|
+
t.warning = true
|
61
|
+
end
|
@@ -0,0 +1,42 @@
|
|
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/ext/extconf.rb
CHANGED
@@ -4,14 +4,32 @@ require 'rbconfig'
|
|
4
4
|
|
5
5
|
dir_config('io')
|
6
6
|
|
7
|
+
have_header('stdint.h')
|
8
|
+
have_header('sys/resource.h')
|
7
9
|
have_func('closefrom')
|
8
10
|
have_func('fdwalk')
|
9
11
|
have_func('directio')
|
10
12
|
have_func('pread')
|
11
13
|
have_func('pwrite')
|
14
|
+
have_func('rb_str_set_len', 'ruby.h')
|
12
15
|
|
13
|
-
|
16
|
+
case Config::CONFIG['host_os']
|
17
|
+
when /darwin/i
|
14
18
|
$CPPFLAGS += " -D_MACOS"
|
19
|
+
when /linux/i
|
20
|
+
# this may be needed for other platforms as well
|
21
|
+
$CPPFLAGS += " -D_XOPEN_SOURCE=500"
|
22
|
+
|
23
|
+
# for O_DIRECT
|
24
|
+
$CPPFLAGS += " -D_GNU_SOURCE=1"
|
25
|
+
|
26
|
+
# we know Linux is always capable of this, but /proc/ may not be mounted
|
27
|
+
# at build time
|
28
|
+
$CPPFLAGS += %{ '-DPROC_SELF_FD_DIR="/proc/self/fd"'}
|
29
|
+
end
|
30
|
+
|
31
|
+
if have_macro("O_DIRECT", %w(sys/types.h fcntl.h))
|
32
|
+
$CPPFLAGS += " -DHAVE_O_DIRECT_MACRO"
|
15
33
|
end
|
16
34
|
|
17
35
|
create_makefile('io/extra', 'io')
|
data/ext/io/extra.c
CHANGED
@@ -1,16 +1,77 @@
|
|
1
1
|
/* Extra methods for the IO class */
|
2
2
|
#include "ruby.h"
|
3
|
+
#ifdef HAVE_RUBY_IO_H
|
4
|
+
#include "ruby/io.h"
|
5
|
+
#else
|
3
6
|
#include "rubyio.h"
|
7
|
+
#endif
|
8
|
+
|
4
9
|
#include <unistd.h>
|
5
10
|
#include <stdlib.h>
|
11
|
+
#include <errno.h>
|
12
|
+
|
13
|
+
#ifdef HAVE_STDINT_H
|
14
|
+
#include <stdint.h>
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#ifndef RSTRING_PTR
|
18
|
+
#define RSTRING_PTR(v) (RSTRING(v)->ptr)
|
19
|
+
#define RSTRING_LEN(v) (RSTRING(v)->len)
|
20
|
+
#endif
|
21
|
+
|
22
|
+
#ifndef HAVE_RB_STR_SET_LEN
|
23
|
+
/* this is taken from Ruby 1.8.7, 1.8.6 may not have it */
|
24
|
+
static void rb_18_str_set_len(VALUE str, long len)
|
25
|
+
{
|
26
|
+
RSTRING(str)->len = len;
|
27
|
+
RSTRING(str)->ptr[len] = '\0';
|
28
|
+
}
|
29
|
+
#define rb_str_set_len(str,len) rb_18_str_set_len(str,len)
|
30
|
+
#endif
|
31
|
+
|
6
32
|
|
7
|
-
#
|
33
|
+
#ifdef PROC_SELF_FD_DIR
|
34
|
+
#include <dirent.h>
|
35
|
+
#endif
|
36
|
+
|
37
|
+
#if !defined(HAVE_CLOSEFROM) || !defined(HAVE_FDWALK)
|
38
|
+
#ifdef HAVE_SYS_RESOURCE_H
|
8
39
|
#include <sys/resource.h>
|
9
40
|
#endif
|
41
|
+
static int open_max(void){
|
42
|
+
#ifdef HAVE_SYS_RESOURCE_H
|
43
|
+
struct rlimit limits;
|
44
|
+
|
45
|
+
if(!getrlimit(RLIMIT_NOFILE, &limits) &&
|
46
|
+
limits.rlim_max != RLIM_INFINITY &&
|
47
|
+
limits.rlim_max > 0 &&
|
48
|
+
limits.rlim_max <= INT_MAX)
|
49
|
+
return (int)limits.rlim_max;
|
50
|
+
#endif
|
51
|
+
#ifdef _SC_OPEN_MAX
|
52
|
+
{
|
53
|
+
long tmp;
|
54
|
+
|
55
|
+
if ((tmp = sysconf(_SC_OPEN_MAX)) && tmp > 0 && tmp <= INT_MAX)
|
56
|
+
return (int)tmp;
|
57
|
+
}
|
58
|
+
#endif
|
59
|
+
#ifdef OPEN_MAX
|
60
|
+
return OPEN_MAX;
|
61
|
+
#else
|
62
|
+
return 1024; /* a common limit */
|
63
|
+
#endif
|
64
|
+
}
|
65
|
+
#endif
|
10
66
|
|
11
|
-
#
|
67
|
+
#if defined(HAVE_DIRECTIO) || defined(HAVE_O_DIRECT_MACRO)
|
12
68
|
#include <sys/types.h>
|
69
|
+
#endif
|
13
70
|
#include <fcntl.h>
|
71
|
+
|
72
|
+
#ifndef DIRECTIO_OFF
|
73
|
+
#define DIRECTIO_OFF 0
|
74
|
+
#define DIRECTIO_ON 1
|
14
75
|
#endif
|
15
76
|
|
16
77
|
/*
|
@@ -22,30 +83,76 @@
|
|
22
83
|
*
|
23
84
|
* This method uses your system's builtin closefrom() function, if supported.
|
24
85
|
* Otherwise, it uses a manual, and (probably) less efficient approach.
|
25
|
-
*
|
86
|
+
*
|
26
87
|
*--
|
27
88
|
* The manual approach was copied from the closefrom() man page on Solaris 9.
|
28
|
-
* Not implemented on OS X because the getrlimit function is busted.
|
29
89
|
*/
|
30
90
|
static VALUE io_closefrom(VALUE klass, VALUE v_low_fd){
|
31
|
-
#ifdef _MACOS
|
32
|
-
rb_raise(rb_eNotImpError, "IO.closefrom is not implemented on this platform");
|
33
|
-
#endif
|
34
|
-
|
35
91
|
#ifdef HAVE_CLOSEFROM
|
36
92
|
closefrom(NUM2INT(v_low_fd));
|
37
93
|
#else
|
38
94
|
int i, lowfd;
|
39
|
-
|
40
|
-
getrlimit(RLIMIT_NOFILE, &limits);
|
95
|
+
int maxfd = open_max();
|
41
96
|
lowfd = NUM2INT(v_low_fd);
|
42
97
|
|
43
|
-
for(i = lowfd; i <
|
98
|
+
for(i = lowfd; i < maxfd; i++)
|
44
99
|
close(i);
|
45
100
|
#endif
|
46
101
|
return klass;
|
47
102
|
}
|
48
103
|
|
104
|
+
#ifndef HAVE_FDWALK
|
105
|
+
static int fdwalk(int (*func)(void *data, int fd), void *data){
|
106
|
+
int rv = 0;
|
107
|
+
int fd;
|
108
|
+
|
109
|
+
#ifdef PROC_SELF_FD_DIR
|
110
|
+
DIR *dir = opendir(PROC_SELF_FD_DIR);
|
111
|
+
|
112
|
+
if(dir){ /* procfs may not be mounted... */
|
113
|
+
struct dirent *ent;
|
114
|
+
int saved_errno;
|
115
|
+
int dir_fd = dirfd(dir);
|
116
|
+
|
117
|
+
while((ent = readdir(dir))){
|
118
|
+
char *err = NULL;
|
119
|
+
|
120
|
+
if(ent->d_name[0] == '.')
|
121
|
+
continue;
|
122
|
+
|
123
|
+
errno = 0;
|
124
|
+
fd = (int)strtol(ent->d_name, &err, 10);
|
125
|
+
|
126
|
+
if (errno || ! err || *err || fd == dir_fd)
|
127
|
+
continue;
|
128
|
+
|
129
|
+
if ((rv = func(data, fd)))
|
130
|
+
break;
|
131
|
+
}
|
132
|
+
saved_errno = errno;
|
133
|
+
closedir(dir);
|
134
|
+
errno = saved_errno;
|
135
|
+
} else
|
136
|
+
#endif /* PROC_SELF_FD_DIR */
|
137
|
+
{
|
138
|
+
int maxfd = open_max();
|
139
|
+
|
140
|
+
for(fd = 0; fd < maxfd; fd++){
|
141
|
+
/* use fcntl to detect whether fd is a valid file descriptor */
|
142
|
+
errno = 0;
|
143
|
+
if(fcntl(fd, F_GETFD) < 0)
|
144
|
+
continue;
|
145
|
+
|
146
|
+
errno = 0;
|
147
|
+
if ((rv = func(data, fd)))
|
148
|
+
break;
|
149
|
+
}
|
150
|
+
}
|
151
|
+
return rv;
|
152
|
+
}
|
153
|
+
#define HAVE_FDWALK
|
154
|
+
#endif
|
155
|
+
|
49
156
|
#ifdef HAVE_FDWALK
|
50
157
|
/*
|
51
158
|
* Used by io_fdwalk. Yields a File object back to the block.
|
@@ -53,7 +160,7 @@ static VALUE io_closefrom(VALUE klass, VALUE v_low_fd){
|
|
53
160
|
*/
|
54
161
|
static int close_func(void* lowfd, int fd){
|
55
162
|
VALUE v_args[1];
|
56
|
-
|
163
|
+
|
57
164
|
v_args[0] = UINT2NUM(fd);
|
58
165
|
rb_yield(rb_class_new_instance(1, v_args, rb_cFile));
|
59
166
|
return 0;
|
@@ -75,12 +182,12 @@ static VALUE io_fdwalk(int argc, VALUE* argv, VALUE klass){
|
|
75
182
|
lowfd = NUM2INT(v_low_fd);
|
76
183
|
|
77
184
|
fdwalk(close_func, &lowfd);
|
78
|
-
|
185
|
+
|
79
186
|
return klass;
|
80
187
|
}
|
81
188
|
#endif
|
82
189
|
|
83
|
-
#
|
190
|
+
#if defined(HAVE_DIRECTIO) || defined(O_DIRECT)
|
84
191
|
/*
|
85
192
|
* call-seq:
|
86
193
|
* IO#directio?
|
@@ -89,6 +196,7 @@ static VALUE io_fdwalk(int argc, VALUE* argv, VALUE klass){
|
|
89
196
|
* current handle. The default is false.
|
90
197
|
*/
|
91
198
|
static VALUE io_get_directio(VALUE self){
|
199
|
+
#if defined(HAVE_DIRECTIO)
|
92
200
|
VALUE v_advice = Qnil;
|
93
201
|
|
94
202
|
if(rb_ivar_defined(rb_cIO, rb_intern("@directio")))
|
@@ -98,6 +206,15 @@ static VALUE io_get_directio(VALUE self){
|
|
98
206
|
v_advice = Qfalse;
|
99
207
|
|
100
208
|
return v_advice;
|
209
|
+
#elif defined(O_DIRECT)
|
210
|
+
int fd = NUM2INT(rb_funcall(self, rb_intern("fileno"), 0, 0));
|
211
|
+
int flags = fcntl(fd, F_GETFL);
|
212
|
+
|
213
|
+
if(flags < 0)
|
214
|
+
rb_sys_fail("fcntl");
|
215
|
+
|
216
|
+
return (flags & O_DIRECT) ? Qtrue : Qfalse;
|
217
|
+
#endif /* O_DIRECT */
|
101
218
|
}
|
102
219
|
|
103
220
|
/*
|
@@ -122,11 +239,32 @@ static VALUE io_set_directio(VALUE self, VALUE v_advice){
|
|
122
239
|
/* Retrieve the current file descriptor in order to pass it to directio() */
|
123
240
|
fd = NUM2INT(rb_funcall(self, rb_intern("fileno"), 0, 0));
|
124
241
|
|
242
|
+
#if defined(HAVE_DIRECTIO)
|
125
243
|
if(directio(fd, advice) < 0)
|
126
244
|
rb_raise(rb_eStandardError, "The directio() call failed");
|
127
245
|
|
128
246
|
if(advice == DIRECTIO_ON)
|
129
247
|
rb_iv_set(self, "directio", Qtrue);
|
248
|
+
#else
|
249
|
+
{
|
250
|
+
int flags = fcntl(fd, F_GETFL);
|
251
|
+
|
252
|
+
if(flags < 0)
|
253
|
+
rb_sys_fail("fcntl");
|
254
|
+
|
255
|
+
if(advice == DIRECTIO_OFF){
|
256
|
+
if(flags & O_DIRECT){
|
257
|
+
if(fcntl(fd, F_SETFL, flags & ~O_DIRECT) < 0)
|
258
|
+
rb_sys_fail("fcntl");
|
259
|
+
}
|
260
|
+
} else { /* DIRECTIO_ON */
|
261
|
+
if(!(flags & O_DIRECT)){
|
262
|
+
if(fcntl(fd, F_SETFL, flags | O_DIRECT) < 0)
|
263
|
+
rb_sys_fail("fcntl");
|
264
|
+
}
|
265
|
+
}
|
266
|
+
}
|
267
|
+
#endif
|
130
268
|
|
131
269
|
return self;
|
132
270
|
}
|
@@ -144,12 +282,15 @@ static VALUE s_io_pread(VALUE klass, VALUE v_fd, VALUE v_nbyte, VALUE v_offset){
|
|
144
282
|
int fd = NUM2INT(v_fd);
|
145
283
|
size_t nbyte = NUM2ULONG(v_nbyte);
|
146
284
|
off_t offset = NUM2ULONG(v_offset);
|
147
|
-
|
285
|
+
VALUE str = rb_str_new(NULL, nbyte);
|
286
|
+
ssize_t nread = pread(fd, RSTRING_PTR(str), nbyte, offset);
|
148
287
|
|
149
|
-
if(
|
288
|
+
if (nread < 0)
|
150
289
|
rb_sys_fail("pread");
|
290
|
+
if (nread != nbyte)
|
291
|
+
rb_str_set_len(str, nread);
|
151
292
|
|
152
|
-
return
|
293
|
+
return str;
|
153
294
|
}
|
154
295
|
|
155
296
|
/*
|
@@ -192,8 +333,8 @@ static VALUE s_io_pwrite(VALUE klass, VALUE v_fd, VALUE v_buf, VALUE v_offset){
|
|
192
333
|
|
193
334
|
result = pwrite(
|
194
335
|
NUM2INT(v_fd),
|
195
|
-
|
196
|
-
|
336
|
+
RSTRING_PTR(v_buf),
|
337
|
+
RSTRING_LEN(v_buf),
|
197
338
|
NUM2INT(v_offset)
|
198
339
|
);
|
199
340
|
|
@@ -214,17 +355,22 @@ void Init_extra(){
|
|
214
355
|
rb_define_singleton_method(rb_cIO, "fdwalk", io_fdwalk, -1);
|
215
356
|
#endif
|
216
357
|
|
217
|
-
#
|
358
|
+
#if defined(HAVE_DIRECTIO) || defined(O_DIRECT)
|
218
359
|
rb_define_method(rb_cIO, "directio?", io_get_directio, 0);
|
219
360
|
rb_define_method(rb_cIO, "directio=", io_set_directio, 1);
|
220
|
-
|
361
|
+
|
221
362
|
/* 0: Applications get the default system behavior when accessing file data. */
|
222
363
|
rb_define_const(rb_cIO, "DIRECTIO_OFF", UINT2NUM(DIRECTIO_OFF));
|
223
|
-
|
364
|
+
|
224
365
|
/* 1: File data is not cached in the system's memory pages. */
|
225
366
|
rb_define_const(rb_cIO, "DIRECTIO_ON", UINT2NUM(DIRECTIO_ON));
|
226
367
|
#endif
|
227
368
|
|
369
|
+
#ifdef O_DIRECT
|
370
|
+
/* 040000: direct disk access (in Linux) */
|
371
|
+
rb_define_const(rb_cIO, "DIRECT", UINT2NUM(O_DIRECT));
|
372
|
+
#endif
|
373
|
+
|
228
374
|
#ifdef HAVE_PREAD
|
229
375
|
rb_define_singleton_method(rb_cIO, "pread", s_io_pread, 3);
|
230
376
|
rb_define_singleton_method(rb_cIO, "pread_ptr", s_io_pread_ptr, 3);
|
@@ -234,6 +380,6 @@ void Init_extra(){
|
|
234
380
|
rb_define_singleton_method(rb_cIO, "pwrite", s_io_pwrite, 3);
|
235
381
|
#endif
|
236
382
|
|
237
|
-
/* 1.
|
238
|
-
rb_define_const(rb_cIO, "EXTRA_VERSION", rb_str_new2("1.
|
383
|
+
/* 1.2.0: The version of this library. This a string. */
|
384
|
+
rb_define_const(rb_cIO, "EXTRA_VERSION", rb_str_new2("1.2.0"));
|
239
385
|
}
|
data/io-extra.gemspec
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rbconfig'
|
3
|
+
|
4
|
+
spec = Gem::Specification.new do |gem|
|
5
|
+
if Config::CONFIG['host_os'] =~ /mswin|dos|win32/i
|
6
|
+
STDERR.puts 'Not supported on this platform. Exiting.'
|
7
|
+
exit(-1)
|
8
|
+
end
|
9
|
+
|
10
|
+
gem.name = 'io-extra'
|
11
|
+
gem.version = '1.2.0'
|
12
|
+
gem.author = 'Daniel J. Berger'
|
13
|
+
gem.license = 'Artistic 2.0'
|
14
|
+
gem.email = 'djberg96@gmail.com'
|
15
|
+
gem.homepage = 'http://www.rubyforge.org/projects/shards'
|
16
|
+
gem.platform = Gem::Platform::RUBY
|
17
|
+
gem.summary = 'Adds extra methods to the IO class.'
|
18
|
+
gem.test_file = 'test/test_io_extra.rb'
|
19
|
+
gem.extensions = ['ext/extconf.rb']
|
20
|
+
gem.files = Dir['**/*'].reject{ |f| f.include?('CVS') }
|
21
|
+
|
22
|
+
gem.extra_rdoc_files = [
|
23
|
+
'CHANGES',
|
24
|
+
'README',
|
25
|
+
'MANIFEST',
|
26
|
+
'ext/io/extra.c'
|
27
|
+
]
|
28
|
+
|
29
|
+
gem.rubyforge_project = 'shards'
|
30
|
+
gem.required_ruby_version = '>= 1.8.0'
|
31
|
+
|
32
|
+
gem.add_development_dependency('test-unit', '>= 2.0.3')
|
33
|
+
|
34
|
+
gem.description = <<-EOF
|
35
|
+
Adds the IO.closefrom, IO.fdwalk, IO.pread, IO.pread_ptr, and IO.pwrite
|
36
|
+
class methods as well as the IO#directio and IO#directio? instance
|
37
|
+
methods (for those platforms that support them).
|
38
|
+
EOF
|
39
|
+
end
|
40
|
+
|
41
|
+
Gem.manage_gems if Gem::RubyGemsVersion.to_f < 1.0
|
42
|
+
Gem::Builder.new(spec).build
|
data/test/test_io_extra.rb
CHANGED
@@ -4,7 +4,11 @@
|
|
4
4
|
# Test suite for the io-extra library. This test should be run via the
|
5
5
|
# 'rake test' task.
|
6
6
|
###########################################################################
|
7
|
+
require 'rubygems'
|
8
|
+
gem 'test-unit'
|
9
|
+
|
7
10
|
require 'test/unit'
|
11
|
+
require 'rbconfig'
|
8
12
|
require 'io/extra'
|
9
13
|
|
10
14
|
class TC_IO_Extra < Test::Unit::TestCase
|
@@ -15,40 +19,51 @@ class TC_IO_Extra < Test::Unit::TestCase
|
|
15
19
|
end
|
16
20
|
|
17
21
|
def test_version
|
18
|
-
assert_equal('1.
|
22
|
+
assert_equal('1.2.0', IO::EXTRA_VERSION)
|
19
23
|
end
|
20
|
-
|
21
|
-
unless Config::CONFIG['host_os'] =~ /darwin/i
|
22
|
-
def test_directio
|
23
|
-
assert_respond_to(@fh, :directio?)
|
24
|
-
assert_nothing_raised{ @fh.directio? }
|
25
|
-
end
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
def test_direct_constant
|
26
|
+
omit_unless(Config::CONFIG['host_os'] =~ /linux/i, 'Linux-only')
|
27
|
+
assert_equal(040000, IO::DIRECT)
|
28
|
+
assert_equal(040000, File::DIRECT)
|
29
|
+
end
|
32
30
|
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
def test_open_direct
|
32
|
+
omit_unless(Config::CONFIG['host_os'] =~ /linux/i, 'Linux-only')
|
33
|
+
assert_nothing_raised do
|
34
|
+
fh = File.open(@fh.path, IO::RDWR|IO::DIRECT)
|
35
|
+
fh.close
|
36
36
|
end
|
37
|
+
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
def test_directio
|
40
|
+
omit_if(Config::CONFIG['host_os'] =~ /darwin/i, 'unsupported')
|
41
|
+
assert_respond_to(@fh, :directio?)
|
42
|
+
assert_nothing_raised{ @fh.directio? }
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_directio_set
|
46
|
+
omit_if(Config::CONFIG['host_os'] =~ /darwin/i, 'unsupported')
|
47
|
+
assert_respond_to(@fh, :directio=)
|
48
|
+
assert_raises(StandardError){ @fh.directio = 99 }
|
49
|
+
assert_nothing_raised{ @fh.directio = IO::DIRECTIO_ON }
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_constants
|
53
|
+
omit_if(Config::CONFIG['host_os'] =~ /darwin/i, 'unsupported')
|
54
|
+
assert_not_nil(IO::DIRECTIO_ON)
|
55
|
+
assert_not_nil(IO::DIRECTIO_OFF)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_fdwalk
|
59
|
+
omit_if(Config::CONFIG['host_os'] =~ /darwin/i, 'unsupported')
|
60
|
+
assert_respond_to(IO, :fdwalk)
|
61
|
+
assert_nothing_raised{ IO.fdwalk(0){ } }
|
42
62
|
end
|
43
63
|
|
44
64
|
def test_closefrom
|
45
65
|
assert_respond_to(IO, :closefrom)
|
46
|
-
|
47
|
-
if Config::CONFIG['host_os'] =~ /darwin/i
|
48
|
-
assert_raise(NotImplementedError){ IO.closefrom(3) }
|
49
|
-
else
|
50
|
-
assert_nothing_raised{ IO.closefrom(3) }
|
51
|
-
end
|
66
|
+
assert_nothing_raised{ IO.closefrom(3) }
|
52
67
|
end
|
53
68
|
|
54
69
|
def test_pread
|
@@ -58,11 +73,29 @@ class TC_IO_Extra < Test::Unit::TestCase
|
|
58
73
|
assert_equal("quick", IO.pread(@fh.fileno, 5, 4))
|
59
74
|
end
|
60
75
|
|
76
|
+
def test_pread_binary
|
77
|
+
@fh.close rescue nil
|
78
|
+
@fh = File.open(@file, "ab")
|
79
|
+
@fh.binmode
|
80
|
+
size = @fh.stat.size
|
81
|
+
assert_nothing_raised { @fh.syswrite("FOO\0HELLO") }
|
82
|
+
@fh.close rescue nil
|
83
|
+
@fh = File.open(@file)
|
84
|
+
assert_equal("O\0H", IO.pread(@fh.fileno, 3, size + 2))
|
85
|
+
end
|
86
|
+
|
61
87
|
def test_pread_ptr
|
62
88
|
@fh.close rescue nil
|
63
89
|
@fh = File.open(@file)
|
64
90
|
assert_respond_to(IO, :pread_ptr)
|
65
|
-
assert_kind_of(
|
91
|
+
assert_kind_of(Integer, IO.pread_ptr(@fh.fileno, 5, 4))
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_pread_last
|
95
|
+
@fh.close rescue nil
|
96
|
+
@fh = File.open(@file)
|
97
|
+
size = @fh.stat.size
|
98
|
+
assert_equal("ck\n", IO.pread(@fh.fileno, 5, size - 3))
|
66
99
|
end
|
67
100
|
|
68
101
|
def test_pwrite
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io-extra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel J. Berger
|
@@ -9,11 +9,20 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-07-28 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: test-unit
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.0.3
|
24
|
+
version:
|
25
|
+
description: " Adds the IO.closefrom, IO.fdwalk, IO.pread, IO.pread_ptr, and IO.pwrite\n class methods as well as the IO#directio and IO#directio? instance\n methods (for those platforms that support them).\n"
|
17
26
|
email: djberg96@gmail.com
|
18
27
|
executables: []
|
19
28
|
|
@@ -23,15 +32,22 @@ extra_rdoc_files:
|
|
23
32
|
- CHANGES
|
24
33
|
- README
|
25
34
|
- MANIFEST
|
35
|
+
- ext/io/extra.c
|
26
36
|
files:
|
37
|
+
- CHANGES
|
27
38
|
- doc/io_extra.txt
|
28
|
-
-
|
39
|
+
- examples/example_io_extra.rb
|
40
|
+
- ext/extconf.rb
|
29
41
|
- ext/io/extra.c
|
30
|
-
-
|
31
|
-
- README
|
42
|
+
- io-extra.gemspec
|
32
43
|
- MANIFEST
|
44
|
+
- Rakefile
|
45
|
+
- README
|
46
|
+
- test/test_io_extra.rb
|
33
47
|
has_rdoc: true
|
34
48
|
homepage: http://www.rubyforge.org/projects/shards
|
49
|
+
licenses:
|
50
|
+
- Artistic 2.0
|
35
51
|
post_install_message:
|
36
52
|
rdoc_options: []
|
37
53
|
|
@@ -52,9 +68,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
52
68
|
requirements: []
|
53
69
|
|
54
70
|
rubyforge_project: shards
|
55
|
-
rubygems_version: 1.
|
71
|
+
rubygems_version: 1.3.5
|
56
72
|
signing_key:
|
57
|
-
specification_version:
|
58
|
-
summary: Adds
|
73
|
+
specification_version: 3
|
74
|
+
summary: Adds extra methods to the IO class.
|
59
75
|
test_files:
|
60
76
|
- test/test_io_extra.rb
|