1*cf5a6c84SAndroid Build Coastguard Worker /* mktemp.c - Create a temporary file or directory.
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2012 Elie De Brauwer <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker *
5*cf5a6c84SAndroid Build Coastguard Worker * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/mktemp.html
6*cf5a6c84SAndroid Build Coastguard Worker
7*cf5a6c84SAndroid Build Coastguard Worker USE_MKTEMP(NEWTOY(mktemp, ">1(tmpdir);:uqd(directory)p:t", TOYFLAG_BIN))
8*cf5a6c84SAndroid Build Coastguard Worker
9*cf5a6c84SAndroid Build Coastguard Worker config MKTEMP
10*cf5a6c84SAndroid Build Coastguard Worker bool "mktemp"
11*cf5a6c84SAndroid Build Coastguard Worker default y
12*cf5a6c84SAndroid Build Coastguard Worker help
13*cf5a6c84SAndroid Build Coastguard Worker usage: mktemp [-dqtu] [-p DIR] [TEMPLATE]
14*cf5a6c84SAndroid Build Coastguard Worker
15*cf5a6c84SAndroid Build Coastguard Worker Safely create a new file "DIR/TEMPLATE" and print its name.
16*cf5a6c84SAndroid Build Coastguard Worker
17*cf5a6c84SAndroid Build Coastguard Worker -d Create directory instead of file (--directory)
18*cf5a6c84SAndroid Build Coastguard Worker -p Put new file in DIR (--tmpdir)
19*cf5a6c84SAndroid Build Coastguard Worker -q Quiet, no error messages
20*cf5a6c84SAndroid Build Coastguard Worker -t Prefer $TMPDIR > DIR > /tmp (default DIR > $TMPDIR > /tmp)
21*cf5a6c84SAndroid Build Coastguard Worker -u Don't create anything, just print what would be created
22*cf5a6c84SAndroid Build Coastguard Worker
23*cf5a6c84SAndroid Build Coastguard Worker Each X in TEMPLATE is replaced with a random printable character. The
24*cf5a6c84SAndroid Build Coastguard Worker default TEMPLATE is tmp.XXXXXXXXXX.
25*cf5a6c84SAndroid Build Coastguard Worker */
26*cf5a6c84SAndroid Build Coastguard Worker
27*cf5a6c84SAndroid Build Coastguard Worker #define FOR_mktemp
28*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
29*cf5a6c84SAndroid Build Coastguard Worker
30*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
31*cf5a6c84SAndroid Build Coastguard Worker char *p, *tmpdir;
32*cf5a6c84SAndroid Build Coastguard Worker )
33*cf5a6c84SAndroid Build Coastguard Worker
mktemp_main(void)34*cf5a6c84SAndroid Build Coastguard Worker void mktemp_main(void)
35*cf5a6c84SAndroid Build Coastguard Worker {
36*cf5a6c84SAndroid Build Coastguard Worker char *template = *toys.optargs, *dir, *te = getenv("TMPDIR");
37*cf5a6c84SAndroid Build Coastguard Worker int len;
38*cf5a6c84SAndroid Build Coastguard Worker
39*cf5a6c84SAndroid Build Coastguard Worker // --tmpdir's argument is optional's but -p is mandatory, so can't combine
40*cf5a6c84SAndroid Build Coastguard Worker if (!TT.p && FLAG(tmpdir)) {
41*cf5a6c84SAndroid Build Coastguard Worker TT.p = TT.tmpdir ? TT.tmpdir : "";
42*cf5a6c84SAndroid Build Coastguard Worker toys.optflags |= FLAG_p;
43*cf5a6c84SAndroid Build Coastguard Worker }
44*cf5a6c84SAndroid Build Coastguard Worker dir = TT.p;
45*cf5a6c84SAndroid Build Coastguard Worker // if template, no prefix unless -pt. if !template, always prefix
46*cf5a6c84SAndroid Build Coastguard Worker if (!dir || !*dir || (FLAG(t) && te && *te)) dir = te;
47*cf5a6c84SAndroid Build Coastguard Worker if (!dir || !*dir) dir = "/tmp";
48*cf5a6c84SAndroid Build Coastguard Worker if (!template) template = "tmp.XXXXXXXXXX";
49*cf5a6c84SAndroid Build Coastguard Worker else {
50*cf5a6c84SAndroid Build Coastguard Worker if (*template == '/' && TT.p && *TT.p) perror_exit("-p + /template");
51*cf5a6c84SAndroid Build Coastguard Worker if (!FLAG(p) && !FLAG(t)) dir = 0;
52*cf5a6c84SAndroid Build Coastguard Worker }
53*cf5a6c84SAndroid Build Coastguard Worker
54*cf5a6c84SAndroid Build Coastguard Worker // TODO: coreutils cleans paths, so -p /t/// would result in /t/xxx...
55*cf5a6c84SAndroid Build Coastguard Worker template = dir ? xmprintf("%s/%s", dir, template) : xstrdup(template);
56*cf5a6c84SAndroid Build Coastguard Worker len = strlen(template);
57*cf5a6c84SAndroid Build Coastguard Worker if (len<3 || strcmp(template+len-3, "XXX")) perror_exit("need XXX");
58*cf5a6c84SAndroid Build Coastguard Worker
59*cf5a6c84SAndroid Build Coastguard Worker // In theory you just xputs(mktemp(template)) for -u, in practice there's
60*cf5a6c84SAndroid Build Coastguard Worker // link-time deprecation warnings if you do that. So we fake up our own:
61*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(u)) {
62*cf5a6c84SAndroid Build Coastguard Worker long long rr;
63*cf5a6c84SAndroid Build Coastguard Worker char *s = template+len;
64*cf5a6c84SAndroid Build Coastguard Worker
65*cf5a6c84SAndroid Build Coastguard Worker // Replace X with 64 chars from posix portable character set (all but "_").
66*cf5a6c84SAndroid Build Coastguard Worker xgetrandom(&rr, sizeof(rr));
67*cf5a6c84SAndroid Build Coastguard Worker while (--s>template) {
68*cf5a6c84SAndroid Build Coastguard Worker if (*s != 'X') break;
69*cf5a6c84SAndroid Build Coastguard Worker *s = '-'+(rr&63);
70*cf5a6c84SAndroid Build Coastguard Worker if (*s>'.') ++*s;
71*cf5a6c84SAndroid Build Coastguard Worker if (*s>'9') (*s) += 7;
72*cf5a6c84SAndroid Build Coastguard Worker if (*s>'Z') (*s) += 6;
73*cf5a6c84SAndroid Build Coastguard Worker rr>>=6;
74*cf5a6c84SAndroid Build Coastguard Worker }
75*cf5a6c84SAndroid Build Coastguard Worker } else if (FLAG(d) ? !mkdtemp(template) : mkstemp(template) == -1) {
76*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(q)) {
77*cf5a6c84SAndroid Build Coastguard Worker toys.exitval = 1;
78*cf5a6c84SAndroid Build Coastguard Worker return;
79*cf5a6c84SAndroid Build Coastguard Worker } else perror_exit("Failed to create %s %s",
80*cf5a6c84SAndroid Build Coastguard Worker FLAG(d) ? "directory" : "file", template);
81*cf5a6c84SAndroid Build Coastguard Worker }
82*cf5a6c84SAndroid Build Coastguard Worker
83*cf5a6c84SAndroid Build Coastguard Worker xputs(template);
84*cf5a6c84SAndroid Build Coastguard Worker if (CFG_TOYBOX_FREE) free(template);
85*cf5a6c84SAndroid Build Coastguard Worker }
86