xref: /aosp_15_r20/external/toybox/toys/lsb/mktemp.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
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