]> git.wincent.com - mkdtemp.git/blob - ext/mkdtemp.c
Silence warning compiling against Ruby 1.9
[mkdtemp.git] / ext / mkdtemp.c
1 /*
2 Copyright 2007-2009 Wincent Colaiuta
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include <ruby.h>
18 #include <errno.h>
19 #include <unistd.h>
20
21 /*
22
23 call-seq:
24     Dir.mkdtemp([string])   -> String or nil
25
26 This method securely creates temporary directories. It is a wrapper for the mkdtemp() function in the standard C library. It takes
27 an optional String parameter as a template describing the desired form of the directory name and overwriting the template in-place;
28 if no template is supplied then "/tmp/temp.XXXXXX" is used as a default.
29
30 Note that the exact implementation of mkdtemp() may vary depending on the target system. For example, on Mac OS X at the time of
31 writing, the man page states that the template may contain "some number" of "Xs" on the end of the string, whereas on Red Hat
32 Enterprise Linux it states that the template suffix "must be XXXXXX".
33
34 */
35 static VALUE dir_mkdtemp_m(int argc, VALUE *argv, VALUE self)
36 {
37     VALUE template;
38     char *c_template;
39     char *path;
40
41     /* process argument */
42     if (rb_scan_args(argc, argv, "01", &template) == 0) /* check for 0 mandatory arguments, 1 optional argument */
43         template = Qnil;                                /* default to nil if no argument passed */
44     if (NIL_P(template))
45         template = rb_str_new2("/tmp/temp.XXXXXX");     /* fallback to this template if passed nil */
46     SafeStringValue(template);                          /* raises if template is tainted and SAFE level > 0 */
47     template = StringValue(template);                   /* duck typing support */
48
49     /* create temporary storage */
50     c_template = malloc(RSTRING_LEN(template) + 1);
51     if (!c_template)
52         rb_raise(rb_eNoMemError, "failed to allocate %ld bytes of template storage", RSTRING_LEN(template) + 1);
53     strncpy(c_template, RSTRING_PTR(template), RSTRING_LEN(template));
54     c_template[RSTRING_LEN(template)] = 0;              /* NUL-terminate */
55
56     /* fill out template */
57     path = mkdtemp(c_template);
58     if (path)
59         template = rb_str_new2(path);
60     free(c_template);
61     if (path == NULL)
62         rb_raise(rb_eSystemCallError, "mkdtemp failed (error #%d: %s)", errno, strerror(errno));
63     return template;
64 }
65
66 void Init_mkdtemp()
67 {
68     rb_define_module_function(rb_cDir, "mkdtemp", dir_mkdtemp_m, -1);
69 }