Skip to content

Commit

Permalink
Make sure the utilities don't lose appended junk on FatELF files.
Browse files Browse the repository at this point in the history
Otherwise, if you split a self-extracting .zip file, you lose the .zip data.
  • Loading branch information
icculus committed Oct 24, 2009
1 parent 2b0954d commit 2345ab2
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 0 deletions.
1 change: 1 addition & 0 deletions utils/fatelf-extract.c
Expand Up @@ -21,6 +21,7 @@ static int fatelf_extract(const char *out, const char *fname,
unlink_on_xfail = out;

xcopyfile_range(fname, fd, out, outfd, rec->offset, rec->size);
xappend_junk(fname, fd, out, outfd, header);
xclose(out, outfd);
xclose(fname, fd);
free(header);
Expand Down
7 changes: 7 additions & 0 deletions utils/fatelf-info.c
Expand Up @@ -14,10 +14,17 @@ static int fatelf_info(const char *fname)
const int fd = xopen(fname, O_RDONLY, 0755);
FATELF_header *header = xread_fatelf_header(fname, fd);
unsigned int i = 0;
uint64_t junkoffset, junksize;

printf("%s: FatELF format version %d\n", fname, (int) header->version);
printf("%d records.\n", (int) header->num_records);

if (xfind_junk(fname, fd, header, &junkoffset, &junksize))
{
printf("%llu bytes of junk appended, starting at offset %llu.\n",
(unsigned long long) junksize, (unsigned long long) junkoffset);
} // if

for (i = 0; i < header->num_records; i++)
{
const FATELF_record *rec = &header->records[i];
Expand Down
2 changes: 2 additions & 0 deletions utils/fatelf-remove.c
Expand Up @@ -50,6 +50,8 @@ static int fatelf_remove(const char *out, const char *fname,
memmove(dst, src, sizeof (FATELF_record) * count);
} // if

xappend_junk(fname, fd, out, outfd, header);

// Write the actual FatELF header now...
xwrite_fatelf_header(out, outfd, header);

Expand Down
2 changes: 2 additions & 0 deletions utils/fatelf-replace.c
Expand Up @@ -61,6 +61,8 @@ static int fatelf_replace(const char *out, const char *fname,
offset = binary_offset + rec->size;
} // for

xappend_junk(fname, fd, out, outfd, header);

// Write the actual FatELF header now...
xwrite_fatelf_header(out, outfd, header);

Expand Down
1 change: 1 addition & 0 deletions utils/fatelf-split.c
Expand Up @@ -116,6 +116,7 @@ static int fatelf_split(const char *fname)
outfd = xopen(out, O_WRONLY | O_CREAT | O_TRUNC, 0755);
unlink_on_xfail = out;
xcopyfile_range(fname, fd, out, outfd, rec->offset, rec->size);
xappend_junk(fname, fd, out, outfd, header);
xclose(out, outfd);
unlink_on_xfail = NULL;
free(out);
Expand Down
65 changes: 65 additions & 0 deletions utils/fatelf-utils.c
Expand Up @@ -169,6 +169,15 @@ void xlseek(const char *fname, const int fd,
} // xlseek


uint64_t xget_file_size(const char *fname, const int fd)
{
struct stat statbuf;
if (fstat(fd, &statbuf) == -1)
xfail("Failed to fstat '%s': %s", fname, strerror(errno));
return (uint64_t) statbuf.st_size;
} // xget_file_size


static uint8_t copybuf[256 * 1024];

// xfail() on error.
Expand Down Expand Up @@ -771,6 +780,30 @@ int fatelf_record_matches(const FATELF_record *a, const FATELF_record *b)
} // fatelf_record_matches


int find_furthest_record(const FATELF_header *header)
{
// there's nothing that says the records have to be in order, although
// we probably _should_. Just in case, check them all.
const int total = (int) header->num_records;
uint64_t furthest = 0;
int retval = -1;
int i;

for (i = 0; i < total; i++)
{
const FATELF_record *rec = &header->records[i];
const uint64_t edge = rec->offset + rec->size;
if (edge > furthest)
{
retval = i;
furthest = edge;
} // if
} // for

return retval;
} // find_furthest_record


const char *fatelf_get_wordsize_string(const uint8_t wordsize)
{
if (wordsize == FATELF_32BITS)
Expand Down Expand Up @@ -864,6 +897,38 @@ const char *fatelf_get_target_name(const FATELF_record *rec, const int wants)
} // fatelf_get_target_name


int xfind_junk(const char *fname, const int fd, const FATELF_header *header,
uint64_t *offset, uint64_t *size)
{
const int furthest = find_furthest_record(header);

if (furthest >= 0) // presumably, we failed elsewhere, but oh well.
{
const uint64_t fsize = xget_file_size(fname, fd);
const FATELF_record *rec = &header->records[furthest];
const uint64_t edge = rec->offset + rec->size;
if (fsize > edge)
{
*offset = edge;
*size = fsize - edge;
return 1;
} // if
} // if

return 0;
} // xfind_junk


void xappend_junk(const char *fname, const int fd,
const char *out, const int outfd,
const FATELF_header *header)
{
uint64_t offset, size;
if (xfind_junk(fname, fd, header, &offset, &size))
xcopyfile_range(fname, fd, out, outfd, offset, size);
} // xappend_junk


void xfatelf_init(int argc, const char **argv)
{
memset(zerobuf, '\0', sizeof (zerobuf)); // just in case.
Expand Down
20 changes: 20 additions & 0 deletions utils/fatelf-utils.h
Expand Up @@ -17,6 +17,8 @@
#include <fcntl.h>
#include <stdint.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "fatelf.h"

Expand Down Expand Up @@ -89,6 +91,9 @@ void xcopyfile_range(const char *in, const int infd,
const char *out, const int outfd,
const uint64_t offset, const uint64_t size);

// get the length of an open file in bytes.
uint64_t xget_file_size(const char *fname, const int fd);

// read the parts of an ELF header we care about.
void xread_elf_header(const char *fname, const int fd, const uint64_t offset,
FATELF_record *rec);
Expand All @@ -104,9 +109,24 @@ void xwrite_fatelf_header(const char *fname, const int fd,
// don't forget to free() the returned pointer!
FATELF_header *xread_fatelf_header(const char *fname, const int fd);

// Locate non-FatELF data at the end of a FatELF file fd, based on
// header header. Returns non-zero if junk found, and fills in offset and
// size.
int xfind_junk(const char *fname, const int fd, const FATELF_header *header,
uint64_t *offset, uint64_t *size);

// Write non-FatELF data at the end of FatELF file fd to current position in
// outfd, based on header header.
void xappend_junk(const char *fname, const int fd,
const char *out, const int outfd,
const FATELF_header *header);

// Align a value to the page size.
uint64_t align_to_page(const uint64_t offset);

// find the record closest to the end of the file. -1 on error!
int find_furthest_record(const FATELF_header *header);

const fatelf_machine_info *get_machine_by_id(const uint16_t id);
const fatelf_machine_info *get_machine_by_name(const char *name);
const fatelf_osabi_info *get_osabi_by_id(const uint8_t id);
Expand Down

0 comments on commit 2345ab2

Please sign in to comment.