io-extra 1.1.1 → 1.2.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.
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
@@ -4,7 +4,7 @@
4
4
  * Rakefile
5
5
  * io-extra.gemspec
6
6
  * doc/io_extra.txt
7
- * examples/test.rb
7
+ * examples/example_io_extra.rb
8
8
  * ext/extconf.rb
9
9
  * ext/io/extra.c
10
10
  * test/test_io_extra.rb
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 or OS X.
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 reports on the project page
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
- Ruby's
70
+ Artistic 2.0
62
71
 
63
72
  = Copyright
64
- (C) 2003-2008 Daniel J. Berger
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
- if Config::CONFIG['host_os'] =~ /darwin/i
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
- #ifndef HAVE_CLOSEFROM
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
- #ifdef HAVE_DIRECTIO
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
- struct rlimit limits;
40
- getrlimit(RLIMIT_NOFILE, &limits);
95
+ int maxfd = open_max();
41
96
  lowfd = NUM2INT(v_low_fd);
42
97
 
43
- for(i = lowfd; i < limits.rlim_max; 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
- #ifdef HAVE_DIRECTIO
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
- char* buf = malloc(nbyte + 1);
285
+ VALUE str = rb_str_new(NULL, nbyte);
286
+ ssize_t nread = pread(fd, RSTRING_PTR(str), nbyte, offset);
148
287
 
149
- if(pread(fd, buf, nbyte, offset) == -1)
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 rb_str_new2(buf);
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
- RSTRING(v_buf)->ptr,
196
- RSTRING(v_buf)->len,
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
- #ifdef HAVE_DIRECTIO
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.1.1: The version of this package. This a string. */
238
- rb_define_const(rb_cIO, "EXTRA_VERSION", rb_str_new2("1.1.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
@@ -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.1.1', IO::EXTRA_VERSION)
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
- def test_directio_set
28
- assert_respond_to(@fh, :directio=)
29
- assert_raises(StandardError){ @fh.directio = 99 }
30
- assert_nothing_raised{ @fh.directio = IO::DIRECTIO_ON }
31
- end
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
- def test_constants
34
- assert_not_nil(IO::DIRECTIO_ON)
35
- assert_not_nil(IO::DIRECTIO_OFF)
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
- def test_fdwalk
39
- assert_respond_to(IO, :fdwalk)
40
- assert_nothing_raised{ IO.fdwalk(0){ } }
41
- end
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(Fixnum, IO.pread_ptr(@fh.fileno, 5, 4))
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.1.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: 2008-09-08 00:00:00 -06:00
12
+ date: 2009-07-28 00:00:00 -06:00
13
13
  default_executable:
14
- dependencies: []
15
-
16
- description: Adds the IO.closefrom, IO.fdwalk, IO.pread, IO.pread_ptr, and IO.pwrite class methods as well as the IO#directio and IO#directio? instance methods (for those platforms that support them).
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
- - test/test_io_extra.rb
39
+ - examples/example_io_extra.rb
40
+ - ext/extconf.rb
29
41
  - ext/io/extra.c
30
- - CHANGES
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.2.0
71
+ rubygems_version: 1.3.5
56
72
  signing_key:
57
- specification_version: 2
58
- summary: Adds the IO.closefrom, IO.fdwalk, IO.pread, IO.pread_ptr, and IO.pwrite class methods as well as the IO#directio and IO#directio? instance methods (for those platforms that support them).
73
+ specification_version: 3
74
+ summary: Adds extra methods to the IO class.
59
75
  test_files:
60
76
  - test/test_io_extra.rb