1 /* vi: set sw=4 ts=4: */
2 /*
3 * Mini mktemp implementation for busybox
4 *
5 * Copyright (C) 2000 by Daniel Jacobowitz
6 * Written by Daniel Jacobowitz <dan@debian.org>
7 *
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */
10 /* Coreutils 6.12 man page says:
11 * mktemp [OPTION]... [TEMPLATE]
12 * Create a temporary file or directory, safely, and print its name. If
13 * TEMPLATE is not specified, use tmp.XXXXXXXXXX.
14 * -d, --directory
15 * create a directory, not a file
16 * -q, --quiet
17 * suppress diagnostics about file/dir-creation failure
18 * -u, --dry-run
19 * do not create anything; merely print a name (unsafe)
20 * --tmpdir[=DIR]
21 * interpret TEMPLATE relative to DIR. If DIR is not specified,
22 * use $TMPDIR if set, else /tmp. With this option, TEMPLATE must
23 * not be an absolute name. Unlike with -t, TEMPLATE may contain
24 * slashes, but even here, mktemp still creates only the final com-
25 * ponent.
26 * -p DIR use DIR as a prefix; implies -t [deprecated]
27 * -t interpret TEMPLATE as a single file name component, relative to
28 * a directory: $TMPDIR, if set; else the directory specified via
29 * -p; else /tmp [deprecated]
30 */
31 //config:config MKTEMP
32 //config: bool "mktemp (4.2 kb)"
33 //config: default y
34 //config: help
35 //config: mktemp is used to create unique temporary files
36
37 //applet:IF_MKTEMP(APPLET_NOEXEC(mktemp, mktemp, BB_DIR_BIN, BB_SUID_DROP, mktemp))
38
39 //kbuild:lib-$(CONFIG_MKTEMP) += mktemp.o
40
41 //usage:#define mktemp_trivial_usage
42 //usage: "[-dt] [-p DIR] [TEMPLATE]"
43 //usage:#define mktemp_full_usage "\n\n"
44 //usage: "Create a temporary file with name based on TEMPLATE and print its name.\n"
45 //usage: "TEMPLATE must end with XXXXXX (e.g. [/dir/]nameXXXXXX).\n"
46 //usage: "Without TEMPLATE, -t tmp.XXXXXX is assumed.\n"
47 //usage: "\n -d Make directory, not file"
48 //usage: "\n -q Fail silently on errors"
49 //usage: "\n -t Prepend base directory name to TEMPLATE"
50 //usage: "\n -p DIR Use DIR as a base directory (implies -t)"
51 //usage: "\n -u Do not create anything; print a name"
52 //usage: "\n"
53 //usage: "\nBase directory is: -p DIR, else $TMPDIR, else /tmp"
54 //usage:
55 //usage:#define mktemp_example_usage
56 //usage: "$ mktemp /tmp/temp.XXXXXX\n"
57 //usage: "/tmp/temp.mWiLjM\n"
58 //usage: "$ ls -la /tmp/temp.mWiLjM\n"
59 //usage: "-rw------- 1 andersen andersen 0 Apr 25 17:10 /tmp/temp.mWiLjM\n"
60
61 #include "libbb.h"
62
63 int mktemp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
mktemp_main(int argc UNUSED_PARAM,char ** argv)64 int mktemp_main(int argc UNUSED_PARAM, char **argv)
65 {
66 const char *path;
67 char *chp;
68 unsigned opts;
69 enum {
70 OPT_d = 1 << 0,
71 OPT_q = 1 << 1,
72 OPT_t = 1 << 2,
73 OPT_p = 1 << 3,
74 OPT_u = 1 << 4,
75 OPT_tmpdir = (1 << 5) * ENABLE_LONG_OPTS,
76 };
77
78 path = getenv("TMPDIR");
79 if (!path || path[0] == '\0')
80 path = "/tmp";
81
82 #if ENABLE_LONG_OPTS
83 opts = getopt32long(argv, "^"
84 "dqtp:u"
85 "\0"
86 "?1" /* 1 arg max */,
87 "directory\0" No_argument "d"
88 "quiet\0" No_argument "q"
89 "dry-run\0" No_argument "u"
90 "tmpdir\0" Optional_argument "\xff"
91 , &path, &path
92 );
93 #else
94 opts = getopt32(argv, "^" "dqtp:u" "\0" "?1"/*1 arg max*/, &path);
95 #endif
96
97 chp = argv[optind];
98 if (!chp) {
99 /* GNU coreutils 8.4:
100 * bare "mktemp" -> "mktemp -t tmp.XXXXXX"
101 */
102 chp = xstrdup("tmp.XXXXXX");
103 opts |= OPT_t;
104 }
105 #if 0
106 /* Don't allow directory separator in template */
107 if ((opts & OPT_t) && bb_basename(chp) != chp) {
108 errno = EINVAL;
109 goto error;
110 }
111 #endif
112 if (opts & (OPT_t|OPT_p|OPT_tmpdir))
113 chp = concat_path_file(path, chp);
114
115 if (opts & OPT_u) {
116 chp = mktemp(chp);
117 if (chp[0] == '\0')
118 goto error;
119 } else if (opts & OPT_d) {
120 if (mkdtemp(chp) == NULL)
121 goto error;
122 } else {
123 if (mkstemp(chp) < 0)
124 goto error;
125 }
126 puts(chp);
127 return EXIT_SUCCESS;
128 error:
129 if (opts & OPT_q)
130 return EXIT_FAILURE;
131 /* don't use chp as it gets mangled in case of error */
132 bb_perror_nomsg_and_die();
133 }
134