mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-14 20:37:06 +00:00
When elftoolchain's objcopy (or strip) is rewriting a file in-place,
make it create the temporary file in the same directory as the source file by default, instead of always using $TMPDIR or /tmp. If creating that file fails because the directory is not writable, also fallback to $TMPDIR or /tmp. This has also been submitted upstream as: https://sourceforge.net/p/elftoolchain/tickets/597/ Reported by: cem PR: 250872 MFC after: 2 weeks
This commit is contained in:
parent
1e4309ae4e
commit
1e4896b176
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=367809
|
@ -68,7 +68,7 @@ process_ar_obj(struct elfcopy *ecp, struct ar_obj *obj)
|
|||
int fd;
|
||||
|
||||
/* Output to a temporary file. */
|
||||
create_tempfile(&tempfile, &fd);
|
||||
create_tempfile(NULL, &tempfile, &fd);
|
||||
if ((ecp->eout = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL)
|
||||
errx(EXIT_FAILURE, "elf_begin() failed: %s",
|
||||
elf_errmsg(-1));
|
||||
|
|
|
@ -298,7 +298,7 @@ void create_scn(struct elfcopy *_ecp);
|
|||
void create_srec(struct elfcopy *_ecp, int _ifd, int _ofd, const char *_ofn);
|
||||
void create_symtab(struct elfcopy *_ecp);
|
||||
void create_symtab_data(struct elfcopy *_ecp);
|
||||
void create_tempfile(char **_fn, int *_fd);
|
||||
void create_tempfile(const char *_src, char **_fn, int *_fd);
|
||||
void finalize_external_symtab(struct elfcopy *_ecp);
|
||||
void free_elf(struct elfcopy *_ecp);
|
||||
void free_sec_act(struct elfcopy *_ecp);
|
||||
|
|
|
@ -512,44 +512,57 @@ free_elf(struct elfcopy *ecp)
|
|||
|
||||
/* Create a temporary file. */
|
||||
void
|
||||
create_tempfile(char **fn, int *fd)
|
||||
create_tempfile(const char *src, char **fn, int *fd)
|
||||
{
|
||||
static const char _TEMPDIR[] = "/tmp/";
|
||||
static const char _TEMPFILE[] = "ecp.XXXXXXXX";
|
||||
const char *tmpdir;
|
||||
char *cp, *tmpf;
|
||||
size_t tlen, plen;
|
||||
|
||||
#define _TEMPFILE "ecp.XXXXXXXX"
|
||||
#define _TEMPFILEPATH "/tmp/ecp.XXXXXXXX"
|
||||
char *tmpf;
|
||||
size_t tlen, slen, plen;
|
||||
|
||||
if (fn == NULL || fd == NULL)
|
||||
return;
|
||||
/* Repect TMPDIR environment variable. */
|
||||
tmpdir = getenv("TMPDIR");
|
||||
if (tmpdir != NULL && *tmpdir != '\0') {
|
||||
tlen = strlen(tmpdir);
|
||||
plen = strlen(_TEMPFILE);
|
||||
tmpf = malloc(tlen + plen + 2);
|
||||
for (;;) {
|
||||
if (src == NULL) {
|
||||
/* Respect TMPDIR environment variable. */
|
||||
tmpdir = getenv("TMPDIR");
|
||||
if (tmpdir == NULL || *tmpdir == '\0')
|
||||
tmpdir = _TEMPDIR;
|
||||
tlen = strlen(tmpdir);
|
||||
slen = tmpdir[tlen - 1] == '/' ? 0 : 1;
|
||||
} else {
|
||||
/* Create temporary file relative to source file. */
|
||||
if ((tmpdir = strrchr(src, '/')) == NULL) {
|
||||
/* No path, only use a template filename. */
|
||||
tlen = 0;
|
||||
} else {
|
||||
/* Append the template after the slash. */
|
||||
tlen = ++tmpdir - src;
|
||||
tmpdir = src;
|
||||
}
|
||||
slen = 0;
|
||||
}
|
||||
plen = strlen(_TEMPFILE) + 1;
|
||||
tmpf = malloc(tlen + slen + plen);
|
||||
if (tmpf == NULL)
|
||||
err(EXIT_FAILURE, "malloc failed");
|
||||
strncpy(tmpf, tmpdir, tlen);
|
||||
cp = &tmpf[tlen - 1];
|
||||
if (*cp++ != '/')
|
||||
*cp++ = '/';
|
||||
strncpy(cp, _TEMPFILE, plen);
|
||||
cp[plen] = '\0';
|
||||
} else {
|
||||
tmpf = strdup(_TEMPFILEPATH);
|
||||
if (tmpf == NULL)
|
||||
err(EXIT_FAILURE, "strdup failed");
|
||||
if (tlen > 0)
|
||||
memcpy(tmpf, tmpdir, tlen);
|
||||
if (slen > 0)
|
||||
tmpf[tlen] = '/';
|
||||
/* Copy template filename including NUL terminator. */
|
||||
memcpy(tmpf + tlen + slen, _TEMPFILE, plen);
|
||||
if ((*fd = mkstemp(tmpf)) != -1)
|
||||
break;
|
||||
if (errno != EACCES || src == NULL)
|
||||
err(EXIT_FAILURE, "mkstemp %s failed", tmpf);
|
||||
/* Permission denied, try again using TMPDIR or /tmp. */
|
||||
free(tmpf);
|
||||
src = NULL;
|
||||
}
|
||||
if ((*fd = mkstemp(tmpf)) == -1)
|
||||
err(EXIT_FAILURE, "mkstemp %s failed", tmpf);
|
||||
if (fchmod(*fd, 0644) == -1)
|
||||
err(EXIT_FAILURE, "fchmod %s failed", tmpf);
|
||||
*fn = tmpf;
|
||||
|
||||
#undef _TEMPFILE
|
||||
#undef _TEMPFILEPATH
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -571,16 +584,16 @@ copy_from_tempfile(const char *src, const char *dst, int infd, int *outfd,
|
|||
if (rename(src, dst) >= 0) {
|
||||
*outfd = infd;
|
||||
return (0);
|
||||
} else if (errno != EXDEV)
|
||||
} else if (errno != EXDEV && errno != EACCES)
|
||||
return (-1);
|
||||
|
||||
|
||||
/*
|
||||
* If the rename() failed due to 'src' and 'dst' residing in
|
||||
* two different file systems, invoke a helper function in
|
||||
* libelftc to do the copy.
|
||||
*/
|
||||
|
||||
if (unlink(dst) < 0)
|
||||
if (errno != EACCES && unlink(dst) < 0)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
@ -630,7 +643,7 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst)
|
|||
err(EXIT_FAILURE, "fstat %s failed", src);
|
||||
|
||||
if (dst == NULL)
|
||||
create_tempfile(&tempfile, &ofd);
|
||||
create_tempfile(src, &tempfile, &ofd);
|
||||
else
|
||||
if ((ofd = open(dst, O_RDWR|O_CREAT, 0755)) == -1)
|
||||
err(EXIT_FAILURE, "open %s failed", dst);
|
||||
|
@ -663,7 +676,7 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst)
|
|||
if (ecp->oed == ELFDATANONE)
|
||||
ecp->oed = ELFDATA2LSB;
|
||||
}
|
||||
create_tempfile(&elftemp, &efd);
|
||||
create_tempfile(src, &elftemp, &efd);
|
||||
if ((ecp->eout = elf_begin(efd, ELF_C_WRITE, NULL)) == NULL)
|
||||
errx(EXIT_FAILURE, "elf_begin() failed: %s",
|
||||
elf_errmsg(-1));
|
||||
|
@ -723,7 +736,7 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst)
|
|||
tempfile);
|
||||
free(tempfile);
|
||||
}
|
||||
create_tempfile(&tempfile, &ofd0);
|
||||
create_tempfile(src, &tempfile, &ofd0);
|
||||
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue