Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 39 additions & 12 deletions cctools/ld64/src/ld/ResponseFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,21 +209,11 @@ struct string_list* at_paths, int *hint_p)
}

char* addr = NULL;
size_t size = sb.st_size;
bool used_mmap = true;
bool used_mmap = false;
if (sb.st_size) {
addr = (char*)mmap(0, (size_t)sb.st_size, PROT_READ | PROT_WRITE,
MAP_FILE | MAP_PRIVATE, fd, 0);
if (MAP_FAILED == addr) {
used_mmap = false;
addr = (char *)malloc(size + 1);
if (-1 == read(fd, addr, size)) {
close(fd);
throwf("can't read %s: %s\n", at_path, strerror(errno));
return EXPAND_ERROR;
}
addr[size] = '\0';
}
used_mmap = MAP_FAILED != addr;
}

if (close(fd)) {
Expand All @@ -233,6 +223,43 @@ struct string_list* at_paths, int *hint_p)
return EXPAND_ERROR;
}

// if mmap fails then the input file is likely a special file (e.g. a
// pipe) that doesn't necessarily support st_size or some other method to
// ascertain the input size, so we fall back to allocating as we go
if (!used_mmap) {
size_t size = 4096;
size_t total_read = 0;
size_t num_read;
size_t request;;

FILE *fp = fopen(at_path, "rb");

addr = (char *)malloc(size + 1);

while (
request = size - total_read,
num_read = fread(addr + total_read, 1, request, fp),
total_read += num_read,
request == num_read
) {
size *= 2;
addr = (char*)realloc(addr, size + 1);
}

if (-1 == num_read) {
close(fd);
throwf("can't read %s: %s\n", at_path, strerror(errno));
return EXPAND_ERROR;
}

addr[total_read] = '\0';

if (fclose(fp)) {
throwf("can't close %s: %s\n", at_path, strerror(errno));
return EXPAND_ERROR;
}
}

// build a new argument list now
if (0 == newargs.nstr) {
string_list_add_argv(&newargs, i, args->strs);
Expand Down