io-extra 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +10 -0
- data/README +39 -0
- data/doc/io_extra.txt +89 -0
- data/extconf.rb +10 -0
- data/lib/io/extra.c +147 -0
- data/test/tc_ioextra.rb +65 -0
- metadata +51 -0
data/CHANGES
ADDED
data/README
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
= Description
|
2
|
+
The io-extra package provides a few extra IO methods that you may find
|
3
|
+
handy. They are IO.closefrom, IO.fdwalk, IO#directio? and IO#directio=.
|
4
|
+
|
5
|
+
Not supported on MS Windows.
|
6
|
+
|
7
|
+
= Installation
|
8
|
+
ruby extconf.rb
|
9
|
+
make
|
10
|
+
ruby test/tc_ioextra.rb (optional)
|
11
|
+
make site-install
|
12
|
+
|
13
|
+
= Developer's Notes
|
14
|
+
== Q) What is the difference between your implementation of IO.closefrom and a
|
15
|
+
pure Ruby version that looks something like this?
|
16
|
+
|
17
|
+
def IO.closefrom(n)
|
18
|
+
0.upto n do |fd|
|
19
|
+
IO.for_fd(fd).close
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
The primary difference is that this walks all file descriptors, rather
|
24
|
+
than only open file descriptors. However, I should note that this only
|
25
|
+
applies if your platform supports the closefrom() function. In that case,
|
26
|
+
the only advantage is speed.
|
27
|
+
|
28
|
+
== Q) What is the difference between your implementation of IO.fdwalk and a
|
29
|
+
pure Ruby version that looks something like this?
|
30
|
+
|
31
|
+
def IO.fdwalk(n)
|
32
|
+
ObjectSpace.each_object(File){ |f|
|
33
|
+
yield f if f.fileno >= n
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
The primary difference is that this only closes Ruby file objects, not
|
38
|
+
necessarily every filehandle opened by the Ruby process. Think system(), for
|
39
|
+
example.
|
data/doc/io_extra.txt
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
= Description
|
2
|
+
The io-extra package provides a few extra IO methods that you may find
|
3
|
+
handy. They are IO.closefrom, IO.fdwalk and IO.directio.
|
4
|
+
|
5
|
+
Not supported on Win32.
|
6
|
+
|
7
|
+
= Synopsis
|
8
|
+
require "io/extra"
|
9
|
+
|
10
|
+
# Print the fileno of each file handle and then close it
|
11
|
+
IO.fdwalk(0){ |fh|
|
12
|
+
p fh.fileno
|
13
|
+
fh.close
|
14
|
+
}
|
15
|
+
|
16
|
+
# Close all file handles with a fileno greater than or equal to 2.
|
17
|
+
IO.closefrom(2)
|
18
|
+
|
19
|
+
= Class Methods
|
20
|
+
IO.closefrom(low_fd)
|
21
|
+
Closes all open file descriptors greater than or equal to 'low_fd'.
|
22
|
+
|
23
|
+
This uses your systems native closefrom() function, if supported. If not,
|
24
|
+
this method uses a slightly less efficient manual approach that uses
|
25
|
+
getrlimit() behind the scenes.
|
26
|
+
|
27
|
+
IO.fdwalk(low_fd){ |fh| ... }
|
28
|
+
Iterates over each open file descriptor and yields back a File object.
|
29
|
+
Note that it is up to you to close file handles, if desired, when this
|
30
|
+
method is used.
|
31
|
+
|
32
|
+
Not supported by all platforms.
|
33
|
+
|
34
|
+
= Instance methods
|
35
|
+
IO#directio?
|
36
|
+
Returns true or false, based on whether directio has been set for the
|
37
|
+
current handle. The default is false.
|
38
|
+
|
39
|
+
Note supported on all platforms.
|
40
|
+
|
41
|
+
IO#directio=(io_const)
|
42
|
+
Sets the advice for the current file descriptor using directio(). Valid
|
43
|
+
values are IO::DIRECTIO_ON and IO::DIRECTIO_OFF.
|
44
|
+
|
45
|
+
All file descriptors start at DIRECTIO_OFF, unless your filesystem has
|
46
|
+
been mounted using 'forcedirectio' (and supports that option).
|
47
|
+
|
48
|
+
Not supported on all platforms
|
49
|
+
|
50
|
+
= Constants
|
51
|
+
IO::DIRECTIO_ON
|
52
|
+
This value can be passed to IO#directio= in order to turn directio on for
|
53
|
+
the given file handle.
|
54
|
+
|
55
|
+
This value is only defined if your platform supports the directio()
|
56
|
+
function.
|
57
|
+
IO::DIRECTIO_OFF
|
58
|
+
This value can be passed to IO#directio= in order to turn directio off for
|
59
|
+
the given file handle.
|
60
|
+
|
61
|
+
This value is only defined if your platform supports the directio()
|
62
|
+
function.
|
63
|
+
|
64
|
+
IO::EXTRA_VERSION
|
65
|
+
Returns the current version number of this package as a String.
|
66
|
+
|
67
|
+
= Known Bugs
|
68
|
+
You may receive a warning about implicit declaration during the build
|
69
|
+
process. You can ignore this.
|
70
|
+
|
71
|
+
= Future Plans
|
72
|
+
Eliminate warnings that occur during the build process.
|
73
|
+
|
74
|
+
= License
|
75
|
+
Ruby's
|
76
|
+
|
77
|
+
= Copyright
|
78
|
+
(C) 2003-2005 Daniel J. Berger
|
79
|
+
All Rights Reserved
|
80
|
+
|
81
|
+
= Warranty
|
82
|
+
This package is provided "as is" and without any express or
|
83
|
+
implied warranties, including, without limitation, the implied
|
84
|
+
warranties of merchantability and fitness for a particular purpose.
|
85
|
+
|
86
|
+
= Author
|
87
|
+
Daniel J. Berger
|
88
|
+
djberg96 at gmail dot com
|
89
|
+
imperator on IRC (irc.freenode.net)
|
data/extconf.rb
ADDED
data/lib/io/extra.c
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
/* Extra methods for the IO class */
|
2
|
+
#include "ruby.h"
|
3
|
+
#include "rubyio.h"
|
4
|
+
#include <unistd.h>
|
5
|
+
#include <stdlib.h>
|
6
|
+
|
7
|
+
#ifndef HAVE_CLOSEFROM
|
8
|
+
#include <sys/resource.h>
|
9
|
+
#endif
|
10
|
+
|
11
|
+
#ifdef HAVE_DIRECTIO
|
12
|
+
#include <sys/types.h>
|
13
|
+
#include <sys/fcntl.h>
|
14
|
+
#endif
|
15
|
+
|
16
|
+
/*
|
17
|
+
* call-seq:
|
18
|
+
* IO.closefrom(lowfd)
|
19
|
+
*
|
20
|
+
* Close all open file descriptors (associated with the current process) that
|
21
|
+
* are greater than or equal to +lowfd+.
|
22
|
+
*
|
23
|
+
* This method uses your system's builtin closefrom() function, if supported.
|
24
|
+
* Otherwise, it uses a manual, and (probably) less efficient approach.
|
25
|
+
*
|
26
|
+
*--
|
27
|
+
* The manual approach was copied from the closefrom() man page on Solaris 9.
|
28
|
+
*/
|
29
|
+
static VALUE io_closefrom(VALUE klass, VALUE v_low_fd){
|
30
|
+
#ifdef HAVE_CLOSEFROM
|
31
|
+
closefrom(NUM2INT(v_low_fd));
|
32
|
+
#else
|
33
|
+
int i, lowfd;
|
34
|
+
struct rlimit limits;
|
35
|
+
getrlimit(RLIMIT_NOFILE, &limits);
|
36
|
+
lowfd = NUM2INT(v_low_fd);
|
37
|
+
|
38
|
+
for(i = lowfd; i < limits.rlim_max; i++){
|
39
|
+
close(i);
|
40
|
+
}
|
41
|
+
#endif
|
42
|
+
return klass;
|
43
|
+
}
|
44
|
+
|
45
|
+
/*
|
46
|
+
* Used by io_fdwalk. Yields a File object back to the block.
|
47
|
+
* It's up to the user to close it.
|
48
|
+
*/
|
49
|
+
static int close_func(void* lowfd, int fd){
|
50
|
+
VALUE v_args[1];
|
51
|
+
|
52
|
+
v_args[0] = UINT2NUM(fd);
|
53
|
+
rb_yield(rb_class_new_instance(1, v_args, rb_cFile));
|
54
|
+
return 0;
|
55
|
+
}
|
56
|
+
|
57
|
+
#ifdef HAVE_FDWALK
|
58
|
+
/*
|
59
|
+
* call-seq:
|
60
|
+
* IO.fdwalk(lowfd){ |fh| ... }
|
61
|
+
*
|
62
|
+
* Iterates over each open file descriptor and yields back a File object.
|
63
|
+
*
|
64
|
+
* Not supported on all platforms.
|
65
|
+
*/
|
66
|
+
static VALUE io_fdwalk(int argc, VALUE* argv, VALUE klass){
|
67
|
+
VALUE v_low_fd, v_block;
|
68
|
+
int lowfd;
|
69
|
+
|
70
|
+
rb_scan_args(argc, argv, "1&", &v_low_fd, &v_block);
|
71
|
+
lowfd = NUM2INT(v_low_fd);
|
72
|
+
|
73
|
+
fdwalk(close_func, &lowfd);
|
74
|
+
|
75
|
+
return klass;
|
76
|
+
}
|
77
|
+
#endif
|
78
|
+
|
79
|
+
#ifdef HAVE_DIRECTIO
|
80
|
+
/*
|
81
|
+
* call-seq:
|
82
|
+
* IO#directio?
|
83
|
+
*
|
84
|
+
* Returns true or false, based on whether directio has been set for the
|
85
|
+
* current handle. The default is false.
|
86
|
+
*/
|
87
|
+
static VALUE io_get_directio(VALUE self){
|
88
|
+
VALUE v_advice = rb_iv_get(self, "directio");
|
89
|
+
|
90
|
+
if(NIL_P(v_advice))
|
91
|
+
v_advice = Qfalse;
|
92
|
+
|
93
|
+
return v_advice;
|
94
|
+
}
|
95
|
+
|
96
|
+
/*
|
97
|
+
* call-seq:
|
98
|
+
* IO#directio=(advice)
|
99
|
+
*
|
100
|
+
* Sets the advice for the current file descriptor using directio(). Valid
|
101
|
+
* values are IO::DIRECTIO_ON and IO::DIRECTIO_OFF.
|
102
|
+
*
|
103
|
+
* All file descriptors start at DIRECTIO_OFF, unless your filesystem has
|
104
|
+
* been mounted using 'forcedirectio' (and supports that option).
|
105
|
+
*/
|
106
|
+
static VALUE io_set_directio(VALUE self, VALUE v_advice){
|
107
|
+
int fd, rv;
|
108
|
+
int advice = NUM2INT(v_advice);
|
109
|
+
|
110
|
+
/* Only two possible valid values */
|
111
|
+
if( (advice != DIRECTIO_OFF) && (advice != DIRECTIO_ON) )
|
112
|
+
rb_raise(rb_eStandardError, "Invalid value passed to IO#directio=");
|
113
|
+
|
114
|
+
/* Retrieve the current file descriptor in order to pass it to directio() */
|
115
|
+
fd = NUM2INT(rb_funcall(self, rb_intern("fileno"), 0, 0));
|
116
|
+
|
117
|
+
rv = directio(fd, advice);
|
118
|
+
|
119
|
+
if(-1 == rv)
|
120
|
+
rb_raise(rb_eStandardError, "The directio() call failed");
|
121
|
+
|
122
|
+
if(advice == DIRECTIO_ON)
|
123
|
+
rb_iv_set(self, "directio", Qtrue);
|
124
|
+
|
125
|
+
return self;
|
126
|
+
}
|
127
|
+
#endif
|
128
|
+
|
129
|
+
/* Adds the IO.closefrom, IO.fdwalk class methods, as well as the IO#directio
|
130
|
+
* and IO#directio? instance methods (if supported on your platform).
|
131
|
+
*/
|
132
|
+
void Init_extra(){
|
133
|
+
rb_define_singleton_method(rb_cIO, "closefrom", io_closefrom, 1);
|
134
|
+
|
135
|
+
#ifdef HAVE_FDWALK
|
136
|
+
rb_define_singleton_method(rb_cIO, "fdwalk", io_fdwalk, -1);
|
137
|
+
#endif
|
138
|
+
|
139
|
+
#ifdef HAVE_DIRECTIO
|
140
|
+
rb_define_method(rb_cIO, "directio?", io_get_directio, 0);
|
141
|
+
rb_define_method(rb_cIO, "directio=", io_set_directio, 1);
|
142
|
+
rb_define_const(rb_cIO, "DIRECTIO_OFF", UINT2NUM(DIRECTIO_OFF));
|
143
|
+
rb_define_const(rb_cIO, "DIRECTIO_ON", UINT2NUM(DIRECTIO_ON));
|
144
|
+
#endif
|
145
|
+
|
146
|
+
rb_define_const(rb_cIO, "EXTRA_VERSION", rb_str_new2("1.0.1"));
|
147
|
+
}
|
data/test/tc_ioextra.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
#################################################
|
2
|
+
# tc_ioextra.rb
|
3
|
+
#
|
4
|
+
# Test suite for the io-extra package.
|
5
|
+
#################################################
|
6
|
+
base = File.basename(Dir.pwd)
|
7
|
+
|
8
|
+
if base == "test" || base =~ /io-extra/
|
9
|
+
require "ftools"
|
10
|
+
Dir.chdir("..") if base == "test"
|
11
|
+
Dir.mkdir("io") rescue nil
|
12
|
+
File.copy("extra.so","io")
|
13
|
+
$LOAD_PATH.unshift(Dir.pwd)
|
14
|
+
Dir.chdir("test") rescue nil
|
15
|
+
end
|
16
|
+
|
17
|
+
require "test/unit"
|
18
|
+
require "io/extra"
|
19
|
+
|
20
|
+
class TC_IO_Extra < Test::Unit::TestCase
|
21
|
+
def setup
|
22
|
+
@file = "delete_this.txt"
|
23
|
+
@fh = File.open(@file,"w+")
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_version
|
27
|
+
assert_equal("1.0.1", IO::EXTRA_VERSION)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_directio
|
31
|
+
assert_respond_to(@fh,:directio?)
|
32
|
+
assert_nothing_raised{ @fh.directio? }
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_directio_set
|
36
|
+
assert_respond_to(@fh,:directio=)
|
37
|
+
assert_raises(StandardError){ @fh.directio = 99 }
|
38
|
+
assert_nothing_raised{ @fh.directio = IO::DIRECTIO_ON }
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_closefrom
|
42
|
+
assert_respond_to(IO,:closefrom)
|
43
|
+
assert_nothing_raised{ IO.closefrom(3) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_fdwalk
|
47
|
+
assert_respond_to(IO,:fdwalk)
|
48
|
+
assert_nothing_raised{ IO.fdwalk(0){ } }
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_constants
|
52
|
+
assert_not_nil(IO::DIRECTIO_ON)
|
53
|
+
assert_not_nil(IO::DIRECTIO_OFF)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Ignore EBADF, since some of the tests will close @fh
|
57
|
+
def teardown
|
58
|
+
begin
|
59
|
+
@fh.close
|
60
|
+
rescue Errno::EBADF
|
61
|
+
end
|
62
|
+
@fh = nil
|
63
|
+
File.delete(@file) if File.exists?(@file)
|
64
|
+
end
|
65
|
+
end
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: io-extra
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.1
|
7
|
+
date: 2006-07-07 00:00:00 -06:00
|
8
|
+
summary: Adds the IO.closefrom and IO.fdwalk class methods as well as the IO#directio and IO#directio? instance methods (for those platforms that support them).
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: djberg96@gmail.com
|
12
|
+
homepage: http://www.rubyforge.org/projects/shards
|
13
|
+
rubyforge_project: shards
|
14
|
+
description: Adds the IO.closefrom and IO.fdwalk class methods as well as the IO#directio and IO#directio? instance methods (for those platforms that support them).
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.8.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Daniel J. Berger
|
31
|
+
files:
|
32
|
+
- doc/io_extra.txt
|
33
|
+
- test/tc_ioextra.rb
|
34
|
+
- lib/io/extra.c
|
35
|
+
- CHANGES
|
36
|
+
- README
|
37
|
+
test_files:
|
38
|
+
- test/tc_ioextra.rb
|
39
|
+
rdoc_options: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- CHANGES
|
43
|
+
- README
|
44
|
+
executables: []
|
45
|
+
|
46
|
+
extensions:
|
47
|
+
- extconf.rb
|
48
|
+
requirements: []
|
49
|
+
|
50
|
+
dependencies: []
|
51
|
+
|