Fix crunchgen usage of mkstemp()

On Glibc systems mkstemp can only be used once with the same template
string since it will be modified in-place and no longer contain any 'X' chars.
It is fine to reuse the same file here but we need to be explicit and use
open() instead of mkstemp() on the second use.

While touching this file also avoid a hardcoded /bin/pwd since that may not
work when building on non-FreeBSD systems.

Reviewed By:	brooks
Differential Revision: https://reviews.freebsd.org/D25990
This commit is contained in:
Alex Richardson 2020-08-12 15:49:06 +00:00
parent 6d84e76a25
commit 188d6f4bc6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=364166

View File

@ -39,10 +39,13 @@ __FBSDID("$FreeBSD$");
#include <ctype.h>
#include <err.h>
#include <fcntl.h>
#include <paths.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
#define CRUNCH_VERSION "0.2"
@ -91,6 +94,7 @@ prog_t *progs = NULL;
char confname[MAXPATHLEN], infilename[MAXPATHLEN];
char outmkname[MAXPATHLEN], outcfname[MAXPATHLEN], execfname[MAXPATHLEN];
char tempfname[MAXPATHLEN], cachename[MAXPATHLEN], curfilename[MAXPATHLEN];
bool tempfname_initialized = false;
char outhdrname[MAXPATHLEN] ; /* user-supplied header for *.mk */
char *objprefix; /* where are the objects ? */
char *path_make;
@ -216,6 +220,7 @@ main(int argc, char **argv)
snprintf(cachename, sizeof(cachename), "%s.cache", confname);
snprintf(tempfname, sizeof(tempfname), "%s/crunchgen_%sXXXXXX",
getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP, confname);
tempfname_initialized = false;
parse_conf_file();
if (list_mode)
@ -648,8 +653,7 @@ fillin_program(prog_t *p)
/* Determine the actual srcdir (maybe symlinked). */
if (p->srcdir) {
snprintf(line, MAXLINELEN, "cd %s && echo -n `/bin/pwd`",
p->srcdir);
snprintf(line, MAXLINELEN, "cd %s && pwd", p->srcdir);
f = popen(line,"r");
if (!f)
errx(1, "Can't execute: %s\n", line);
@ -721,14 +725,26 @@ fillin_program_objs(prog_t *p, char *path)
/* discover the objs from the srcdir Makefile */
if ((fd = mkstemp(tempfname)) == -1) {
perror(tempfname);
exit(1);
/*
* We reuse the same temporary file name for multiple objects. However,
* some libc implementations (such as glibc) return EINVAL if there
* are no XXXXX characters in the template. This happens after the
* first call to mkstemp since the argument is modified in-place.
* To avoid this error we use open() instead of mkstemp() after the
* call to mkstemp().
*/
if (tempfname_initialized) {
if ((fd = open(tempfname, O_CREAT | O_EXCL | O_RDWR, 0600)) == -1) {
err(EX_OSERR, "open(%s)", tempfname);
}
} else if ((fd = mkstemp(tempfname)) == -1) {
err(EX_OSERR, "mkstemp(%s)", tempfname);
}
tempfname_initialized = true;
if ((f = fdopen(fd, "w")) == NULL) {
warn("%s", tempfname);
warn("fdopen(%s)", tempfname);
goterror = 1;
return;
goto out;
}
if (p->objvar)
objvar = p->objvar;
@ -763,14 +779,14 @@ fillin_program_objs(prog_t *p, char *path)
if ((f = popen(line, "r")) == NULL) {
warn("submake pipe");
goterror = 1;
return;
goto out;
}
while(fgets(line, MAXLINELEN, f)) {
if (strncmp(line, "OBJS= ", 6)) {
warnx("make error: %s", line);
goterror = 1;
continue;
goto out;
}
cp = line + 6;
@ -793,7 +809,7 @@ fillin_program_objs(prog_t *p, char *path)
warnx("make error: make returned %d", rc);
goterror = 1;
}
out:
unlink(tempfname);
}