]> git.wincent.com - mkdtemp.git/blob - ext/mkdtemp.c
Switch to BSD license
[mkdtemp.git] / ext / mkdtemp.c
1 /*
2   Copyright 2007-2010 Wincent Colaiuta. All rights reserved.
3
4   Redistribution and use in source and binary forms, with or without
5   modification, are permitted provided that the following conditions are met:
6
7   1. Redistributions of source code must retain the above copyright notice,
8      this list of conditions and the following disclaimer.
9   2. Redistributions in binary form must reproduce the above copyright notice,
10      this list of conditions and the following disclaimer in the documentation
11      and/or other materials provided with the distribution.
12
13   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
17   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23   POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include <ruby.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include "ruby_compat.h"
30
31 /*
32
33 call-seq:
34     Dir.mkdtemp([string])   -> String or nil
35
36 This method securely creates temporary directories. It is a wrapper for the
37 mkdtemp() function in the standard C library. It takes an optional String
38 parameter as a template describing the desired form of the directory name and
39 overwriting the template in-place; if no template is supplied then
40 "/tmp/temp.XXXXXX" is used as a default.
41
42 Note that the exact implementation of mkdtemp() may vary depending on the
43 target system. For example, on Mac OS X at the time of writing, the man page
44 states that the template may contain "some number" of "Xs" on the end of the
45 string, whereas on Red Hat Enterprise Linux it states that the template suffix
46 "must be XXXXXX".
47
48 */
49 static VALUE dir_mkdtemp_m(int argc, VALUE *argv, VALUE self)
50 {
51     VALUE template;
52     char *c_template;
53     char *path;
54
55     /* process argument */
56     if (rb_scan_args(argc, argv, "01", &template) == 0) /* check for 0 mandatory arguments, 1 optional argument */
57         template = Qnil;                                /* default to nil if no argument passed */
58     if (NIL_P(template))
59         template = rb_str_new2("/tmp/temp.XXXXXX");     /* fallback to this template if passed nil */
60     SafeStringValue(template);                          /* raises if template is tainted and SAFE level > 0 */
61     template = StringValue(template);                   /* duck typing support */
62
63     /* create temporary storage */
64     c_template = malloc(RSTRING_LEN(template) + 1);
65     if (!c_template)
66         rb_raise(rb_eNoMemError, "failed to allocate %ld bytes of template storage", RSTRING_LEN(template) + 1);
67     strncpy(c_template, RSTRING_PTR(template), RSTRING_LEN(template));
68     c_template[RSTRING_LEN(template)] = 0;              /* NUL-terminate */
69
70     /* fill out template */
71     path = mkdtemp(c_template);
72     if (path)
73         template = rb_str_new2(path);
74     free(c_template);
75     if (path == NULL)
76         rb_raise(rb_eSystemCallError, "mkdtemp failed (error #%d: %s)", errno, strerror(errno));
77     return template;
78 }
79
80 void Init_mkdtemp()
81 {
82     rb_define_module_function(rb_cDir, "mkdtemp", dir_mkdtemp_m, -1);
83 }