From: Wayne Davison <wayned@users.sourceforge.net>
To: zsh-workers@sunsite.dk
Subject: [PATCH] Improved temp-file creation
Date: Mon, 18 Oct 2004 22:37:36 -0700 [thread overview]
Message-ID: <20041019053736.GA23313@blorf.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 944 bytes --]
After my recent changes to gettempname() and its callers, I decided that
it would be nice to have a similar function that works like mkstemp()
(and actually uses it, when available). This way callers that are going
to do an immediate open() with O_CREAT|O_EXCL can all use the same code,
which will hopefully make it easier to ensure that callers don't use
mktemp() in an unsafe manner. It also makes things more efficient when
mkstemp() is available because that call can avoid the extra lstat()
calls that mktemp() uses.
The appended patch adds the function gettempfile() that takes the same
(pretty new) parameters as gettempname(), plus an extra one that gets
set to the pointer for the name (since the function returns a file
descriptor). I then sprinkled around the new function into the code.
One caller of gettempname() even got changed to ask for non-heap memory
instead of calling ztrdup() on the returned heap string.
..wayne..
[-- Attachment #2: temp-files.patch --]
[-- Type: text/plain, Size: 4131 bytes --]
--- Src/builtin.c 18 Oct 2004 19:07:50 -0000 1.130
+++ Src/builtin.c 19 Oct 2004 05:32:17 -0000
@@ -1445,10 +1445,8 @@ bin_fc(char *nam, char **argv, Options o
char *fil;
retval = 1;
- fil = gettempname(NULL, 1);
- if (((tempfd = open(fil, O_WRONLY | O_CREAT | O_EXCL | O_NOCTTY, 0600))
- == -1) ||
- ((out = fdopen(tempfd, "w")) == NULL)) {
+ if ((tempfd = gettempfile(NULL, 1, &fil)) < 0
+ || ((out = fdopen(tempfd, "w")) == NULL)) {
unqueue_signals();
zwarnnam("fc", "can't open temp file: %e", NULL, errno);
} else {
@@ -3535,8 +3533,8 @@ bin_print(char *name, char **args, Optio
zwarnnam(name, "open_memstream failed", NULL, 0);
#else
int tempfd;
- char *tmpf = gettempname(NULL, 1);
- if ((tempfd = open(tmpf, O_RDWR|O_CREAT|O_EXCL, 0644)) < 0
+ char *tmpf;
+ if ((tempfd = gettempfile(NULL, 1, &tmpf)) < 0
|| (fout = fdopen(tempfd, "w+")) == NULL)
zwarnnam(name, "can't open temp file: %e", NULL, errno);
unlink(tmpf);
--- Src/exec.c 18 Oct 2004 19:07:55 -0000 1.75
+++ Src/exec.c 19 Oct 2004 05:32:19 -0000
@@ -2801,8 +2801,7 @@ getherestr(struct redir *fn)
untokenize(t);
unmetafy(t, &len);
t[len++] = '\n';
- s = gettempname(NULL, 1);
- if (!s || (fd = open(s, O_CREAT|O_WRONLY|O_EXCL|O_NOCTTY, 0600)) == -1)
+ if ((fd = gettempfile(NULL, 1, &s)) < 0)
return -1;
write(fd, t, len);
close(fd);
@@ -2975,11 +2974,9 @@ getoutputfile(char *cmd)
return NULL;
if (!(prog = parsecmd(cmd)))
return NULL;
- if (!(nam = gettempname(NULL, 1)))
+ if (!(nam = gettempname(NULL, 0)))
return NULL;
- nam = ztrdup(nam);
-
if (!jobtab[thisjob].filelist)
jobtab[thisjob].filelist = znewlinklist();
zaddlinknode(jobtab[thisjob].filelist, nam);
--- Src/hist.c 18 Oct 2004 19:07:30 -0000 1.55
+++ Src/hist.c 19 Oct 2004 05:32:19 -0000
@@ -2137,8 +2137,7 @@ lockhistfile(char *fn, int keep_trying)
lockfile = bicat(unmeta(fn), ".LOCK");
#ifdef HAVE_LINK
- tmpfile = gettempname(fn, 0);
- if ((fd = open(tmpfile, O_WRONLY|O_CREAT|O_EXCL, 0644)) >= 0) {
+ if ((fd = gettempfile(fn, 0, &tmpfile)) >= 0) {
FILE *out = fdopen(fd, "w");
if (out) {
fprintf(out, "%ld %s\n", (long)getpid(), getsparam("HOST"));
@@ -2163,8 +2162,8 @@ lockhistfile(char *fn, int keep_trying)
break;
}
unlink(tmpfile);
+ free(tmpfile);
}
- free(tmpfile);
#else /* not HAVE_LINK */
while ((fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) {
if (errno != EEXIST || !keep_trying)
--- Src/utils.c 18 Oct 2004 19:07:46 -0000 1.68
+++ Src/utils.c 19 Oct 2004 05:32:20 -0000
@@ -1156,6 +1156,47 @@ gettempname(const char *prefix, int use_
return ret;
}
+/**/
+mod_export int
+gettempfile(const char *prefix, int use_heap, char **tempname)
+{
+ char *fn;
+ int fd;
+#if HAVE_MKSTEMP
+ char *suffix = prefix ? ".XXXXXX" : "XXXXXX";
+
+ if (!prefix && !(prefix = getsparam("TMPPREFIX")))
+ prefix = DEFAULT_TMPPREFIX;
+ if (use_heap)
+ fn = dyncat(unmeta(prefix), suffix);
+ else
+ fn = bicat(unmeta(prefix), suffix);
+
+ fd = mkstemp(fn);
+ if (fd < 0) {
+ if (!use_heap)
+ free(fn);
+ fn = NULL;
+ }
+#else
+ int failures = 0;
+
+ do {
+ if (!(fn = gettempname(prefix, use_heap))) {
+ fd = -1;
+ break;
+ }
+ if ((fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0600)) >= 0)
+ break;
+ if (!use_heap)
+ free(fn);
+ fn = NULL;
+ } while (errno == EEXIST && ++failures < 16);
+#endif
+ *tempname = fn;
+ return fd;
+}
+
/* Check if a string contains a token */
/**/
--- Src/Modules/zftp.c 18 Oct 2004 19:07:56 -0000 1.33
+++ Src/Modules/zftp.c 19 Oct 2004 05:32:21 -0000
@@ -1971,8 +1971,7 @@ zftp_open(char *name, char **args, int f
* However, it is closed whenever there are no connections open.
*/
if (zfstatfd == -1) {
- fname = gettempname(NULL, 1);
- zfstatfd = open(fname, O_RDWR|O_CREAT|O_EXCL, 0600);
+ zfstatfd = gettempfile(NULL, 1, &fname);
DPUTS(zfstatfd == -1, "zfstatfd not created");
#if defined(F_SETFD) && defined(FD_CLOEXEC)
/* If the shell execs a program, we don't want this fd left open. */
next reply other threads:[~2004-10-19 5:38 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-10-19 5:37 Wayne Davison [this message]
2004-10-29 7:01 ` Geoff Wing
2004-10-29 16:07 ` Wayne Davison
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20041019053736.GA23313@blorf.net \
--to=wayned@users.sourceforge.net \
--cc=zsh-workers@sunsite.dk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).