elftoolchain: stop leaving tempfiles on error
Temporary files were not cleaned up, resulting in $TMPDIR or even the current directory becoming littered with ecp.* files. This happened with error and even sometimes on success! Approved by: dim MFC after: 4 weeks Accepted upstream: https://sourceforge.net/p/elftoolchain/code/3918/ Differential Revision: https://reviews.freebsd.org/D28651
This commit is contained in:
parent
37cd6c20db
commit
5ac70383c8
@ -69,9 +69,11 @@ process_ar_obj(struct elfcopy *ecp, struct ar_obj *obj)
|
|||||||
|
|
||||||
/* Output to a temporary file. */
|
/* Output to a temporary file. */
|
||||||
create_tempfile(NULL, &tempfile, &fd);
|
create_tempfile(NULL, &tempfile, &fd);
|
||||||
if ((ecp->eout = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL)
|
if ((ecp->eout = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL) {
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
errx(EXIT_FAILURE, "elf_begin() failed: %s",
|
errx(EXIT_FAILURE, "elf_begin() failed: %s",
|
||||||
elf_errmsg(-1));
|
elf_errmsg(-1));
|
||||||
|
}
|
||||||
elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT);
|
elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT);
|
||||||
create_elf(ecp);
|
create_elf(ecp);
|
||||||
elf_end(ecp->ein);
|
elf_end(ecp->ein);
|
||||||
@ -80,27 +82,40 @@ process_ar_obj(struct elfcopy *ecp, struct ar_obj *obj)
|
|||||||
obj->buf = NULL;
|
obj->buf = NULL;
|
||||||
|
|
||||||
/* Extract archive symbols. */
|
/* Extract archive symbols. */
|
||||||
if (lseek(fd, 0, SEEK_SET) < 0)
|
if (lseek(fd, 0, SEEK_SET) < 0) {
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
err(EXIT_FAILURE, "lseek failed for '%s'", tempfile);
|
err(EXIT_FAILURE, "lseek failed for '%s'", tempfile);
|
||||||
if ((ecp->eout = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
|
}
|
||||||
|
if ((ecp->eout = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
errx(EXIT_FAILURE, "elf_begin() failed: %s",
|
errx(EXIT_FAILURE, "elf_begin() failed: %s",
|
||||||
elf_errmsg(-1));
|
elf_errmsg(-1));
|
||||||
|
}
|
||||||
extract_arsym(ecp);
|
extract_arsym(ecp);
|
||||||
elf_end(ecp->eout);
|
elf_end(ecp->eout);
|
||||||
|
|
||||||
if (fstat(fd, &sb) == -1)
|
if (fstat(fd, &sb) == -1) {
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
err(EXIT_FAILURE, "fstat %s failed", tempfile);
|
err(EXIT_FAILURE, "fstat %s failed", tempfile);
|
||||||
if (lseek(fd, 0, SEEK_SET) < 0)
|
}
|
||||||
|
if (lseek(fd, 0, SEEK_SET) < 0) {
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
err(EXIT_FAILURE, "lseek %s failed", tempfile);
|
err(EXIT_FAILURE, "lseek %s failed", tempfile);
|
||||||
|
}
|
||||||
obj->size = sb.st_size;
|
obj->size = sb.st_size;
|
||||||
if ((obj->maddr = malloc(obj->size)) == NULL)
|
if ((obj->maddr = malloc(obj->size)) == NULL) {
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
err(EXIT_FAILURE, "memory allocation failed for '%s'",
|
err(EXIT_FAILURE, "memory allocation failed for '%s'",
|
||||||
tempfile);
|
tempfile);
|
||||||
if ((size_t) read(fd, obj->maddr, obj->size) != obj->size)
|
}
|
||||||
|
if ((size_t) read(fd, obj->maddr, obj->size) != obj->size) {
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
err(EXIT_FAILURE, "read failed for '%s'", tempfile);
|
err(EXIT_FAILURE, "read failed for '%s'", tempfile);
|
||||||
if (unlink(tempfile))
|
}
|
||||||
|
if (cleanup_tempfile(tempfile) < 0)
|
||||||
err(EXIT_FAILURE, "unlink %s failed", tempfile);
|
err(EXIT_FAILURE, "unlink %s failed", tempfile);
|
||||||
free(tempfile);
|
free(tempfile);
|
||||||
|
tempfile = NULL;
|
||||||
close(fd);
|
close(fd);
|
||||||
if (strlen(obj->name) > _MAXNAMELEN_SVR4)
|
if (strlen(obj->name) > _MAXNAMELEN_SVR4)
|
||||||
add_to_ar_str_table(ecp, obj->name);
|
add_to_ar_str_table(ecp, obj->name);
|
||||||
|
@ -277,6 +277,7 @@ void add_to_symtab(struct elfcopy *_ecp, const char *_name,
|
|||||||
unsigned char _st_info, unsigned char _st_other, int _ndx_known);
|
unsigned char _st_info, unsigned char _st_other, int _ndx_known);
|
||||||
int add_to_inseg_list(struct elfcopy *_ecp, struct section *_sec);
|
int add_to_inseg_list(struct elfcopy *_ecp, struct section *_sec);
|
||||||
void adjust_addr(struct elfcopy *_ecp);
|
void adjust_addr(struct elfcopy *_ecp);
|
||||||
|
int cleanup_tempfile(char *_fn);
|
||||||
void copy_content(struct elfcopy *_ecp);
|
void copy_content(struct elfcopy *_ecp);
|
||||||
void copy_data(struct section *_s);
|
void copy_data(struct section *_s);
|
||||||
void copy_phdr(struct elfcopy *_ecp);
|
void copy_phdr(struct elfcopy *_ecp);
|
||||||
|
@ -510,6 +510,27 @@ free_elf(struct elfcopy *ecp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove a temporary file, without freeing its filename.
|
||||||
|
*
|
||||||
|
* Safe to pass NULL, will just ignore it.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cleanup_tempfile(char *fn)
|
||||||
|
{
|
||||||
|
int errno_save, retval;
|
||||||
|
|
||||||
|
if (fn == NULL)
|
||||||
|
return 0;
|
||||||
|
errno_save = errno;
|
||||||
|
if ((retval = unlink(fn)) < 0) {
|
||||||
|
warn("unlink tempfile %s failed", fn);
|
||||||
|
errno = errno_save;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a temporary file. */
|
/* Create a temporary file. */
|
||||||
void
|
void
|
||||||
create_tempfile(const char *src, char **fn, int *fd)
|
create_tempfile(const char *src, char **fn, int *fd)
|
||||||
@ -656,8 +677,10 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (lseek(ifd, 0, SEEK_SET) < 0)
|
if (lseek(ifd, 0, SEEK_SET) < 0) {
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
err(EXIT_FAILURE, "lseek failed");
|
err(EXIT_FAILURE, "lseek failed");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If input object is not ELF file, convert it to an intermediate
|
* If input object is not ELF file, convert it to an intermediate
|
||||||
@ -677,9 +700,12 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst)
|
|||||||
ecp->oed = ELFDATA2LSB;
|
ecp->oed = ELFDATA2LSB;
|
||||||
}
|
}
|
||||||
create_tempfile(src, &elftemp, &efd);
|
create_tempfile(src, &elftemp, &efd);
|
||||||
if ((ecp->eout = elf_begin(efd, ELF_C_WRITE, NULL)) == NULL)
|
if ((ecp->eout = elf_begin(efd, ELF_C_WRITE, NULL)) == NULL) {
|
||||||
|
cleanup_tempfile(elftemp);
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
errx(EXIT_FAILURE, "elf_begin() failed: %s",
|
errx(EXIT_FAILURE, "elf_begin() failed: %s",
|
||||||
elf_errmsg(-1));
|
elf_errmsg(-1));
|
||||||
|
}
|
||||||
elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT);
|
elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT);
|
||||||
if (ecp->itf == ETF_BINARY)
|
if (ecp->itf == ETF_BINARY)
|
||||||
create_elf_from_binary(ecp, ifd, src);
|
create_elf_from_binary(ecp, ifd, src);
|
||||||
@ -687,31 +713,45 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst)
|
|||||||
create_elf_from_ihex(ecp, ifd);
|
create_elf_from_ihex(ecp, ifd);
|
||||||
else if (ecp->itf == ETF_SREC)
|
else if (ecp->itf == ETF_SREC)
|
||||||
create_elf_from_srec(ecp, ifd);
|
create_elf_from_srec(ecp, ifd);
|
||||||
else
|
else {
|
||||||
|
cleanup_tempfile(elftemp);
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
errx(EXIT_FAILURE, "Internal: invalid target flavour");
|
errx(EXIT_FAILURE, "Internal: invalid target flavour");
|
||||||
|
}
|
||||||
elf_end(ecp->eout);
|
elf_end(ecp->eout);
|
||||||
|
|
||||||
/* Open intermediate ELF object as new input object. */
|
/* Open intermediate ELF object as new input object. */
|
||||||
close(ifd);
|
close(ifd);
|
||||||
if ((ifd = open(elftemp, O_RDONLY)) == -1)
|
if ((ifd = open(elftemp, O_RDONLY)) == -1) {
|
||||||
|
cleanup_tempfile(elftemp);
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
err(EXIT_FAILURE, "open %s failed", src);
|
err(EXIT_FAILURE, "open %s failed", src);
|
||||||
|
}
|
||||||
close(efd);
|
close(efd);
|
||||||
if (unlink(elftemp) < 0)
|
if (cleanup_tempfile(elftemp) < 0) {
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
err(EXIT_FAILURE, "unlink %s failed", elftemp);
|
err(EXIT_FAILURE, "unlink %s failed", elftemp);
|
||||||
|
}
|
||||||
free(elftemp);
|
free(elftemp);
|
||||||
|
elftemp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ecp->ein = elf_begin(ifd, ELF_C_READ, NULL)) == NULL)
|
if ((ecp->ein = elf_begin(ifd, ELF_C_READ, NULL)) == NULL) {
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
errx(EXIT_FAILURE, "elf_begin() failed: %s",
|
errx(EXIT_FAILURE, "elf_begin() failed: %s",
|
||||||
elf_errmsg(-1));
|
elf_errmsg(-1));
|
||||||
|
}
|
||||||
|
|
||||||
switch (elf_kind(ecp->ein)) {
|
switch (elf_kind(ecp->ein)) {
|
||||||
case ELF_K_NONE:
|
case ELF_K_NONE:
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
errx(EXIT_FAILURE, "file format not recognized");
|
errx(EXIT_FAILURE, "file format not recognized");
|
||||||
case ELF_K_ELF:
|
case ELF_K_ELF:
|
||||||
if ((ecp->eout = elf_begin(ofd, ELF_C_WRITE, NULL)) == NULL)
|
if ((ecp->eout = elf_begin(ofd, ELF_C_WRITE, NULL)) == NULL) {
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
errx(EXIT_FAILURE, "elf_begin() failed: %s",
|
errx(EXIT_FAILURE, "elf_begin() failed: %s",
|
||||||
elf_errmsg(-1));
|
elf_errmsg(-1));
|
||||||
|
}
|
||||||
|
|
||||||
/* elfcopy(1) manage ELF layout by itself. */
|
/* elfcopy(1) manage ELF layout by itself. */
|
||||||
elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT);
|
elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT);
|
||||||
@ -730,21 +770,21 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst)
|
|||||||
* Create (another) tempfile for binary/srec/ihex
|
* Create (another) tempfile for binary/srec/ihex
|
||||||
* output object.
|
* output object.
|
||||||
*/
|
*/
|
||||||
if (tempfile != NULL) {
|
if (cleanup_tempfile(tempfile) < 0)
|
||||||
if (unlink(tempfile) < 0)
|
errx(EXIT_FAILURE, "unlink %s failed",
|
||||||
err(EXIT_FAILURE, "unlink %s failed",
|
tempfile);
|
||||||
tempfile);
|
free(tempfile);
|
||||||
free(tempfile);
|
|
||||||
}
|
|
||||||
create_tempfile(src, &tempfile, &ofd0);
|
create_tempfile(src, &tempfile, &ofd0);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rewind the file descriptor being processed.
|
* Rewind the file descriptor being processed.
|
||||||
*/
|
*/
|
||||||
if (lseek(ofd, 0, SEEK_SET) < 0)
|
if (lseek(ofd, 0, SEEK_SET) < 0) {
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
err(EXIT_FAILURE,
|
err(EXIT_FAILURE,
|
||||||
"lseek failed for the output object");
|
"lseek failed for the output object");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call flavour-specific conversion routine.
|
* Call flavour-specific conversion routine.
|
||||||
@ -765,11 +805,13 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst)
|
|||||||
#if WITH_PE
|
#if WITH_PE
|
||||||
create_pe(ecp, ofd, ofd0);
|
create_pe(ecp, ofd, ofd0);
|
||||||
#else
|
#else
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
errx(EXIT_FAILURE, "PE/EFI support not enabled"
|
errx(EXIT_FAILURE, "PE/EFI support not enabled"
|
||||||
" at compile time");
|
" at compile time");
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
errx(EXIT_FAILURE, "Internal: unsupported"
|
errx(EXIT_FAILURE, "Internal: unsupported"
|
||||||
" output flavour %d", ecp->oec);
|
" output flavour %d", ecp->oec);
|
||||||
}
|
}
|
||||||
@ -784,6 +826,7 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst)
|
|||||||
/* XXX: Not yet supported. */
|
/* XXX: Not yet supported. */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
errx(EXIT_FAILURE, "file format not supported");
|
errx(EXIT_FAILURE, "file format not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -802,9 +845,13 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst)
|
|||||||
in_place = 1;
|
in_place = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copy_from_tempfile(tempfile, dst, ofd, &tfd, in_place) < 0)
|
if (copy_from_tempfile(tempfile, dst, ofd,
|
||||||
|
&tfd, in_place) < 0) {
|
||||||
|
cleanup_tempfile(tempfile);
|
||||||
err(EXIT_FAILURE, "creation of %s failed", dst);
|
err(EXIT_FAILURE, "creation of %s failed", dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 'tempfile' has been removed by copy_from_tempfile(). */
|
||||||
free(tempfile);
|
free(tempfile);
|
||||||
tempfile = NULL;
|
tempfile = NULL;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user