summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/fileutils.h6
-rw-r--r--lib/fileutils.c12
-rw-r--r--login-utils/setpwnam.c3
-rw-r--r--login-utils/vipw.c3
-rw-r--r--term-utils/wall.c2
5 files changed, 17 insertions, 9 deletions
diff --git a/include/fileutils.h b/include/fileutils.h
index 33aba0a0d..cf29e1b83 100644
--- a/include/fileutils.h
+++ b/include/fileutils.h
@@ -1,13 +1,13 @@
#ifndef UTIL_LINUX_FILEUTILS
#define UTIL_LINUX_FILEUTILS
-extern int xmkstemp(char **tmpname);
+extern int xmkstemp(char **tmpname, char *dir);
-static inline FILE *xfmkstemp(char **tmpname)
+static inline FILE *xfmkstemp(char **tmpname, char *dir)
{
int fd;
FILE *ret;
- fd = xmkstemp(tmpname);
+ fd = xmkstemp(tmpname, dir);
if (fd == -1) {
return NULL;
}
diff --git a/lib/fileutils.c b/lib/fileutils.c
index 0d4656f11..ff8bb8617 100644
--- a/lib/fileutils.c
+++ b/lib/fileutils.c
@@ -16,14 +16,20 @@
/* Create open temporary file in safe way. Please notice that the
* file permissions are -rw------- by default. */
-int xmkstemp(char **tmpname)
+int xmkstemp(char **tmpname, char *dir)
{
char *localtmp;
char *tmpenv;
mode_t old_mode;
int fd;
- tmpenv = getenv("TMPDIR");
+ /* Some use cases must be capable of being moved atomically
+ * with rename(2), which is the reason why dir is here. */
+ if (dir != NULL)
+ tmpenv = dir;
+ else
+ tmpenv = getenv("TMPDIR");
+
if (tmpenv)
xasprintf(&localtmp, "%s/%s.XXXXXX", tmpenv,
program_invocation_short_name);
@@ -68,7 +74,7 @@ int main(void)
{
FILE *f;
char *tmpname;
- f = xfmkstemp(&tmpname);
+ f = xfmkstemp(&tmpname, NULL);
unlink(tmpname);
free(tmpname);
fclose(f);
diff --git a/login-utils/setpwnam.c b/login-utils/setpwnam.c
index 44dda98e7..23aef532d 100644
--- a/login-utils/setpwnam.c
+++ b/login-utils/setpwnam.c
@@ -81,10 +81,11 @@ int setpwnam(struct passwd *pwd)
int contlen, rc;
char *linebuf = NULL;
char *tmpname = NULL;
+ char *atomic_dir = "/etc";
pw_init();
- if ((fp = xfmkstemp(&tmpname)) == NULL)
+ if ((fp = xfmkstemp(&tmpname, atomic_dir)) == NULL)
return -1;
/* ptmp should be owned by root.root or root.wheel */
diff --git a/login-utils/vipw.c b/login-utils/vipw.c
index 66c682dc0..a5982813b 100644
--- a/login-utils/vipw.c
+++ b/login-utils/vipw.c
@@ -143,8 +143,9 @@ static FILE * pw_tmpfile(int lockfd)
{
FILE *fd;
char *tmpname = NULL;
+ char *dir = "/etc";
- if ((fd = xfmkstemp(&tmpname)) == NULL) {
+ if ((fd = xfmkstemp(&tmpname, dir)) == NULL) {
ulckpwdf();
err(EXIT_FAILURE, _("can't open temporary file"));
}
diff --git a/term-utils/wall.c b/term-utils/wall.c
index 0291a5b60..3255a5166 100644
--- a/term-utils/wall.c
+++ b/term-utils/wall.c
@@ -190,7 +190,7 @@ makemsg(char *fname, size_t *mbufsize, int print_banner)
line_max = sysconf(_SC_LINE_MAX);
lbuf = xmalloc(line_max);
- if ((fp = xfmkstemp(&tmpname)) == NULL)
+ if ((fp = xfmkstemp(&tmpname, NULL)) == NULL)
err(EXIT_FAILURE, _("can't open temporary file"));
unlink(tmpname);
free(tmpname);