diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-12-02 21:44:41 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-12-02 21:44:41 +0000 |
commit | 8c31d71b0620b543aee5a1e43cec42eeddecf7bb (patch) | |
tree | 05eb2b26e8df5e4dc051e6f8355cc98a3ffd9f35 /contrib | |
parent | c4a1cde95eb58f68da1b396292ec7229f1fb3bde (diff) | |
download | src-test2-8c31d71b0620b543aee5a1e43cec42eeddecf7bb.tar.gz src-test2-8c31d71b0620b543aee5a1e43cec42eeddecf7bb.zip |
Notes
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/elftoolchain/elfcopy/archive.c | 2 | ||||
-rw-r--r-- | contrib/elftoolchain/elfcopy/elfcopy.h | 2 | ||||
-rw-r--r-- | contrib/elftoolchain/elfcopy/main.c | 79 |
3 files changed, 48 insertions, 35 deletions
diff --git a/contrib/elftoolchain/elfcopy/archive.c b/contrib/elftoolchain/elfcopy/archive.c index efdde7263766..9e23b831fdca 100644 --- a/contrib/elftoolchain/elfcopy/archive.c +++ b/contrib/elftoolchain/elfcopy/archive.c @@ -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)); diff --git a/contrib/elftoolchain/elfcopy/elfcopy.h b/contrib/elftoolchain/elfcopy/elfcopy.h index 3a6fdc76136b..b8845a574428 100644 --- a/contrib/elftoolchain/elfcopy/elfcopy.h +++ b/contrib/elftoolchain/elfcopy/elfcopy.h @@ -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); diff --git a/contrib/elftoolchain/elfcopy/main.c b/contrib/elftoolchain/elfcopy/main.c index fa636820e6e6..c02bb296c4a3 100644 --- a/contrib/elftoolchain/elfcopy/main.c +++ b/contrib/elftoolchain/elfcopy/main.c @@ -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); /* |