From: Dave Reisner Date: Sat, 2 Jun 2012 17:31:30 +0000 (+0200) Subject: fileutils: xmkstemp() interface change X-Git-Tag: v2.22-rc1~315^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3c4fed097ddb65dbe3d88f60caee78fb60756f3e;p=thirdparty%2Futil-linux.git fileutils: xmkstemp() interface change We can not let the user control where TMPDIR is for this tempfile. This will be where we write the updated passwd file, and must be capable of being moved atomically with rename(2). Therefore, it cannot be on a different device, or setpwnam() and vipw/vigr programs will invariably fail with EXDEV. Signed-off-by: Dave Reisner Signed-off-by: Sami Kerola --- diff --git a/include/fileutils.h b/include/fileutils.h index 33aba0a0d5..cf29e1b83d 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 0d4656f110..ff8bb8617f 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 44dda98e73..23aef532dd 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 66c682dc03..a5982813bf 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 0291a5b609..3255a51668 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);