ruby-stemp 1.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.
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
+