ruby-stemp 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README +36 -0
  2. data/ext/extconf.rb +23 -0
  3. data/ext/stemp.c +170 -0
  4. data/test/ts_stemp.rb +91 -0
  5. metadata +49 -0
data/README ADDED
@@ -0,0 +1,36 @@
1
+ STemp - Secure tempfile extension for Ruby
2
+
3
+ Pure Ruby tempfile implementations appear to suffer from well-known race
4
+ conditions. The 'mkstemp' family of functions now popular on Linux & *BSD
5
+ attempt to work around these issues. This module makes them available to
6
+ Ruby programmers on platforms where they are present.
7
+
8
+ Note that you should set your +umask+ appropriately when using this library:
9
+ not all implementations of these functions use a reasonable file creation mask
10
+ by default.
11
+
12
+ Author:: Cian Synnott <cian@gmail.com>
13
+ Copyright:: Copyright (c) 2006 Cian Synnott
14
+ License:: MIT License
15
+
16
+ Copyright (c) 2006 Cian Synnott
17
+
18
+ Permission is hereby granted, free of charge, to any person obtaining a copy
19
+ of this software and associated documentation files (the "Software"), to
20
+ deal in the Software without restriction, including without limitation the
21
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
22
+ sell copies of the Software, and to permit persons to whom the Software is
23
+ furnished to do so, subject to the following conditions:
24
+
25
+ The above copyright notice and this permission notice shall be included in
26
+ all copies or substantial portions of the Software.
27
+
28
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
34
+ IN THE SOFTWARE.
35
+
36
+ $Id: README 5 2006-11-15 00:15:44Z cian $
data/ext/extconf.rb ADDED
@@ -0,0 +1,23 @@
1
+ #
2
+ # Ruby extension configuration for STemp
3
+ #
4
+ # STemp - Secure tempfile extension for Ruby
5
+ #
6
+ # Author:: Cian Synnott <cian@gmail.com>
7
+ # Copyright:: Copyright (c) 2006 Cian Synnott
8
+ # License:: MIT License
9
+ #
10
+ # For license info, see the README file bundled with this package.
11
+ #
12
+ # $Id: extconf.rb 5 2006-11-15 00:15:44Z cian $
13
+ #
14
+
15
+ require 'mkmf'
16
+
17
+ if have_func('mkdtemp') and have_func('mkstemp') and have_func('tmpfile')
18
+ then
19
+ create_makefile('stemp')
20
+ else
21
+ puts "One or more of 'mkdtemp', 'mkstemp' and 'tmpfile' is not available"
22
+ end
23
+
data/ext/stemp.c ADDED
@@ -0,0 +1,170 @@
1
+ /* STemp - Secure tempfile extension for Ruby
2
+ *
3
+ * Pure Ruby tempfile implementations appear to suffer from well-known race
4
+ * conditions. The 'mkstemp' family of functions now popular on Linux & *BSD
5
+ * attempt to work around these issues. This module makes them available to
6
+ * Ruby programmers on platforms where they are present.
7
+ *
8
+ * Author:: Cian Synnott <cian@gmail.com>
9
+ * Copyright:: Copyright (c) 2006 Cian Synnott
10
+ * License:: MIT License
11
+ *
12
+ * Copyright (c) 2006 Cian Synnott
13
+ *
14
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ * of this software and associated documentation files (the "Software"), to
16
+ * deal in the Software without restriction, including without limitation the
17
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18
+ * sell copies of the Software, and to permit persons to whom the Software is
19
+ * furnished to do so, subject to the following conditions:
20
+ *
21
+ * The above copyright notice and this permission notice shall be included in
22
+ * all copies or substantial portions of the Software.
23
+ *
24
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30
+ * IN THE SOFTWARE.
31
+ *
32
+ * $Id: stemp.c 5 2006-11-15 00:15:44Z cian $
33
+ */
34
+
35
+ #include "ruby.h"
36
+
37
+ #include <unistd.h>
38
+ #include <errno.h>
39
+
40
+ VALUE mSTemp;
41
+
42
+ static void raise_systemcallerror(int, char *);
43
+
44
+ /* call-seq:
45
+ * STemp.mkdtemp(template) -> String
46
+ *
47
+ * Wraps <tt>mkdtemp(3)</tt> for Ruby. See <tt>man mkdtemp</tt> on your system
48
+ * for exact semantics.
49
+ *
50
+ * Notes:
51
+ * - <tt>template</tt> is overwritten with the eventual directory name.
52
+ * - raises a <tt>SystemCallError</tt> if any of the syscalls involved fail.
53
+ *
54
+ */
55
+ static VALUE stemp_mkdtemp(VALUE self, VALUE template) {
56
+ VALUE duckstr;
57
+ char *ret;
58
+
59
+ SafeStringValue(template);
60
+
61
+ duckstr = StringValue(template);
62
+
63
+ ret = mkdtemp(RSTRING(duckstr)->ptr);
64
+
65
+ if (NULL == ret) raise_systemcallerror(errno, "in mkdtemp");
66
+
67
+ return duckstr;
68
+ }
69
+
70
+ /* call-seq:
71
+ * STemp.mkstemp(template) -> File
72
+ *
73
+ * Wraps <tt>mkstemp(3)</tt> for Ruby. See <tt>man mkstemp</tt> on your system
74
+ * for exact semantics.
75
+ *
76
+ * Notes:
77
+ * - returns a File object rather than a simple file descriptor.
78
+ * - <tt>template</tt> is overwritten with the eventual directory name.
79
+ * - raises a <tt>SystemCallError</tt> if any of the syscalls involved fail.
80
+ * - the Debian manpage for <tt>mkstemp</tt> suggests you shouldn't use it, but
81
+ * rather stick with <tt>tmpfile</tt>. However, I think it's better all
82
+ * round to have the choice; there are times when you want to know the
83
+ * tempfile name.
84
+ */
85
+ static VALUE stemp_mkstemp(VALUE self, VALUE template) {
86
+ VALUE duckstr, filedesc, file;
87
+ int fd;
88
+
89
+ SafeStringValue(template);
90
+
91
+ duckstr = StringValue(template);
92
+
93
+ fd = mkstemp(RSTRING(duckstr)->ptr);
94
+
95
+ if (-1 == fd) raise_systemcallerror(errno, "in mkstemp");
96
+
97
+ filedesc = INT2FIX(fd);
98
+
99
+ file = rb_class_new_instance(1, &filedesc,
100
+ rb_const_get(rb_cObject, rb_intern("File")));
101
+
102
+ return file;
103
+ }
104
+
105
+ /* call-seq:
106
+ * STemp.tmpfile -> File
107
+ *
108
+ * Wraps <tt>tmpfile(3)</tt> for Ruby. See <tt>man tmpfile</tt> on your system
109
+ * for exact semantics.
110
+ *
111
+ * Notes:
112
+ * - raises a <tt>SystemCallError</tt> if any of the syscalls involved fail.
113
+ */
114
+ static VALUE stemp_tmpfile(VALUE self) {
115
+ VALUE filedesc, file;
116
+ FILE *fp;
117
+
118
+ fp = tmpfile();
119
+
120
+ if (NULL == fp) raise_systemcallerror(errno, "in tmpfile");
121
+
122
+ /* A shame to have to move back to fileno from the FILE *, but there doesn't
123
+ * seem to be a clean way to do this in Ruby's C bindings otherwise.
124
+ * Note that fileno() is not ANSI C, but should be present wherever mkstemp
125
+ * and company are. */
126
+ filedesc = INT2FIX(fileno(fp));
127
+
128
+ file = rb_class_new_instance(1, &filedesc,
129
+ rb_const_get(rb_cObject, rb_intern("File")));
130
+
131
+ return file;
132
+ }
133
+
134
+ /* raise_systemcallerror - Raise a SystemCallError
135
+ *
136
+ * A utility routine for the actual methods defined here.
137
+ *
138
+ * Args:
139
+ * - num: the system error number, probably errno
140
+ * - msg: a message to attach
141
+ */
142
+ static void raise_systemcallerror(int num, char *msg) {
143
+ VALUE excobj, excno, *params;
144
+
145
+ /* Construct argument list */
146
+ excno = INT2FIX(num);
147
+ params = &excno;
148
+
149
+ excobj = rb_class_new_instance(1, params,
150
+ rb_const_get(rb_cObject, rb_intern("SystemCallError")));
151
+
152
+ /* I go about this in a somewhat strange way because of the way
153
+ * SystemCallError works. Its 'new' method creates an object of the
154
+ * appropriate subclass of Errno based on the number you give it. However,
155
+ * rb_raise takes a _class_, not an instance. */
156
+ rb_raise(rb_funcall(excobj, rb_intern("class"), 0), msg);
157
+ }
158
+
159
+ /* STemp - secure tempfile extension for Ruby
160
+ *
161
+ * Note that you should set your +umask+ appropriately when using this library:
162
+ * not all implementations of these functions use a reasonable file creation
163
+ * mask by default.
164
+ */
165
+ void Init_stemp() {
166
+ mSTemp = rb_define_module("STemp");
167
+ rb_define_singleton_method(mSTemp, "mkdtemp", stemp_mkdtemp, 1);
168
+ rb_define_singleton_method(mSTemp, "mkstemp", stemp_mkstemp, 1);
169
+ rb_define_singleton_method(mSTemp, "tmpfile", stemp_tmpfile, 0);
170
+ }
data/test/ts_stemp.rb ADDED
@@ -0,0 +1,91 @@
1
+ #
2
+ # Unit tests for STemp
3
+ #
4
+ # STemp - Secure tempfile extension for Ruby
5
+ #
6
+ # Author:: Cian Synnott <cian@gmail.com>
7
+ # Copyright:: Copyright (c) 2006 Cian Synnott
8
+ # License:: MIT License
9
+ #
10
+ # For license info, see the README file bundled with this package.
11
+ #
12
+ # $Id: ts_stemp.rb 5 2006-11-15 00:15:44Z cian $
13
+ #
14
+
15
+ require 'test/unit'
16
+ require 'fileutils'
17
+ require 'tmpdir'
18
+
19
+ require 'rubygems'
20
+ require 'stemp'
21
+
22
+ # Tests for STemp
23
+ class TestSTemp < Test::Unit::TestCase
24
+ WRITE = "#{Dir.tmpdir}/test-stemp-write"
25
+ NOWRITE = "#{Dir.tmpdir}/test-stemp-nowrite"
26
+
27
+ def setup
28
+ # Create writeable and unwriteable directory 'fixtures'
29
+ FileUtils.mkdir(WRITE, :mode => 0700)
30
+ FileUtils.mkdir(NOWRITE, :mode => 0500)
31
+ end
32
+
33
+ # Tests for +mkdtemp+.
34
+ def test_mkdtemp
35
+ # If we're getting the correct EACCES exceptions here, the exception
36
+ # handling in mkdtemp is working. Don't bother if we're root. :op
37
+ unless Process.euid == 0
38
+ dirname = "#{NOWRITE}/dir-XXXXXX"
39
+ assert_raise(Errno::EACCES) { STemp.mkdtemp(dirname) }
40
+ end
41
+
42
+ # Normal behaviour. Remember to check side-effect.
43
+ dirname = "#{WRITE}/dir-XXXXXX"
44
+ newname = STemp.mkdtemp(dirname)
45
+ assert_equal(newname, dirname)
46
+ assert_not_equal(dirname, "#{WRITE}/dir-XXXXXX")
47
+ assert(File.directory?(dirname))
48
+ end
49
+
50
+ # Tests for +mkstemp+.
51
+ def test_mkstemp
52
+ # See comments above on first assertion.
53
+ unless Process.euid == 0
54
+ filename = "#{NOWRITE}/file-XXXXXX"
55
+ assert_raise(Errno::EACCES) { STemp.mkstemp(filename) }
56
+ end
57
+
58
+ # Test creating a file, writing to it etc. and that it exists at the end.
59
+ filename = "#{WRITE}/file-XXXXXX"
60
+ f = STemp.mkstemp(filename)
61
+ assert_not_equal(filename, "#{WRITE}/file-XXXXXX")
62
+ text = nil
63
+ assert_nothing_raised do
64
+ f.puts 'test string'
65
+ f.rewind
66
+ text = f.read
67
+ f.close
68
+ end
69
+ assert_equal(text, "test string\n")
70
+ assert(File.exists?(filename))
71
+ end
72
+
73
+ # Tests for +tmpfile+.
74
+ def test_tmpfile
75
+ # Test creating a file, writing to it etc.
76
+ f = STemp.tmpfile
77
+ text = nil
78
+ assert_nothing_raised do
79
+ f.puts 'test string'
80
+ f.rewind
81
+ text = f.read
82
+ f.close
83
+ end
84
+ assert_equal(text, "test string\n")
85
+ end
86
+
87
+ def teardown
88
+ FileUtils.rm_rf(WRITE)
89
+ FileUtils.rm_rf(NOWRITE)
90
+ end
91
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: ruby-stemp
5
+ version: !ruby/object:Gem::Version
6
+ version: "1.0"
7
+ date: 2006-11-15 00:00:00 +00:00
8
+ summary: Secure tempfile extension for Ruby
9
+ require_paths:
10
+ - .
11
+ email: cian@gmail.com
12
+ homepage: http://code.google.com/p/ruby-stemp
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: stemp
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: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ authors:
29
+ - Cian Synnott
30
+ files:
31
+ - ext/extconf.rb
32
+ - ext/stemp.c
33
+ - test/ts_stemp.rb
34
+ - README
35
+ test_files:
36
+ - test/ts_stemp.rb
37
+ rdoc_options:
38
+ - --main
39
+ - README
40
+ extra_rdoc_files:
41
+ - README
42
+ executables: []
43
+
44
+ extensions:
45
+ - ext/extconf.rb
46
+ requirements: []
47
+
48
+ dependencies: []
49
+