/* mktemp - create temporary file or directory */
/*
Copyright (C) 2019 Free Software Foundation, Inc.
This file is part of GNU Bash.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see .
*/
#include
#if defined (HAVE_UNISTD_H)
# include
#endif
#include
#include "bashansi.h"
#include "loadables.h"
#define DEFAULT_PREFIX "shtmp"
int
mktemp_builtin (list)
WORD_LIST *list;
{
WORD_LIST *l;
int rval, opt, fd, mflags, base_mflags;
int dflag, qflag, tflag, uflag, onetime;
char *prefix, *varname, *filename, *template;
SHELL_VAR *v;
dflag = qflag = uflag = tflag = onetime = 0;
prefix = varname = 0;
rval = EXECUTION_SUCCESS;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "dqut:v:")) != -1)
{
switch (opt)
{
case 'd':
dflag = 1;
break;
case 'q':
qflag = 1;
break;
case 't':
tflag = 1;
prefix = list_optarg;
break;
case 'u':
uflag = 1;
break;
case 'v':
varname = list_optarg;
break;
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (varname) /* check for validity, not readonly */
{
if (legal_identifier (varname) == 0)
{
if (qflag == 0)
sh_invalidid (varname);
return (EXECUTION_FAILURE);
}
v = find_variable (varname);
if (v && readonly_p (v))
{
if (qflag == 0)
sh_readonly (varname);
return (EXECUTION_FAILURE);
}
}
onetime = (list == 0); /* once through the loop, $TMPDIR/prefix.XXXXXX */
if (prefix == 0)
prefix = DEFAULT_PREFIX;
base_mflags = MT_USETMPDIR|MT_USERANDOM; /* USERANDOM not strictly needed */
while (list || onetime)
{
mflags = base_mflags;
onetime = 0;
#if defined (USE_MKTEMP) && defined (USE_MKSTEMP)
if (list)
{
template = list->word->word;
mflags |= MT_TEMPLATE;
}
#else
/* This is sub-optimal. */
if (list)
{
/* Treat the basename as a prefix */
template = strrchr (list->word->word, '/');
if (template)
template++;
else
template = list->word->word;
}
#endif
else
template = prefix;
if (dflag)
{
filename = sh_mktmpdir (template, mflags);
if (filename == 0)
{
if (qflag == 0)
builtin_error ("%s: cannot create directory", template);
rval = EXECUTION_FAILURE;
}
else
{
if (uflag)
rmdir (filename);
printf ("%s\n", filename);
}
}
else /* filename */
{
fd = sh_mktmpfd (template, mflags, &filename);
if (fd < 0)
{
if (qflag == 0)
builtin_error ("%s: cannot create file", template);
rval = EXECUTION_FAILURE;
}
else
{
close (fd);
if (uflag)
unlink (filename);
printf ("%s\n", filename);
}
}
/* Assign variable if requested */
if (filename && varname)
{
v = builtin_bind_variable (varname, filename, 0);
if (v == 0 || readonly_p (v) || noassign_p (v))
{
builtin_error ("%s: cannot set variable", varname);
rval = EXECUTION_FAILURE;
}
}
FREE (filename);
if (list)
list = list->next;
}
return (rval);
}
char *mktemp_doc[] = {
"Make unique temporary file name",
"",
"Take each supplied filename template and overwrite a portion of it",
"to create a filename, which is unique and may be used by the calling",
"script. TEMPLATE is a string ending in some number of 'X's. If",
"TEMPLATE is not supplied, shtmp.XXXXXX is used and $TMPDIR is used as",
"the name of the containing directory. Files are created u+rw; directories",
"are created u+rwx.",
"",
"Options, if supplied, have the following meanings:",
"",
" -d Create a directory instead of a file",
" -q Do not print error messages about file creation failure",
" -t PREFIX Use PREFIX as the directory in which to create files",
" -u Do not create anything; simply print a name",
" -v VAR Store the generated name into shell variable VAR",
"",
"Any PREFIX supplied with -t is ignored if TEMPLATE is supplied.",
"",
"The return status is true if the file or directory was created successfully;",
"false if an error occurs or VAR is invalid or readonly.",
(char *)NULL
};
struct builtin mktemp_struct = {
"mktemp", /* builtin name */
mktemp_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
mktemp_doc, /* array of long documentation strings. */
"mktemp [-d] [-q] [-t prefix] [-u] [-v varname] [template] ...",
0 /* reserved for internal use */
};