Fix extracting when no compressor was used
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 4s
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 4s
This commit is contained in:
parent
4cb4184338
commit
5b3a7e3994
1 changed files with 131 additions and 98 deletions
229
src/archiver.c
229
src/archiver.c
|
@ -831,141 +831,174 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
|
||||||
|
|
||||||
if (do_extract && !skip) {
|
if (do_extract && !skip) {
|
||||||
fprintf(stderr, " Extracting...\n");
|
fprintf(stderr, " Extracting...\n");
|
||||||
|
|
||||||
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
||||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
||||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||||
int pipe_into_cmd[2];
|
if (is_compressed) {
|
||||||
int pipe_outof_cmd[2];
|
int pipe_into_cmd[2];
|
||||||
pid_t decompressor_pid;
|
int pipe_outof_cmd[2];
|
||||||
if (pipe(pipe_into_cmd) != 0) {
|
pid_t decompressor_pid;
|
||||||
// Unable to create pipes.
|
if (pipe(pipe_into_cmd) != 0) {
|
||||||
break;
|
// Unable to create pipes.
|
||||||
} else if (pipe(pipe_outof_cmd) != 0) {
|
break;
|
||||||
// Unable to create second set of pipes.
|
} else if (pipe(pipe_outof_cmd) != 0) {
|
||||||
close(pipe_into_cmd[0]);
|
// Unable to create second set of pipes.
|
||||||
close(pipe_into_cmd[1]);
|
close(pipe_into_cmd[0]);
|
||||||
return 1;
|
close(pipe_into_cmd[1]);
|
||||||
} else if (fcntl(pipe_into_cmd[1], F_SETFL, O_NONBLOCK) != 0) {
|
return 1;
|
||||||
// Unable to set non-blocking on into-write-pipe.
|
} else if (fcntl(pipe_into_cmd[1], F_SETFL, O_NONBLOCK) != 0) {
|
||||||
close(pipe_into_cmd[0]);
|
// Unable to set non-blocking on into-write-pipe.
|
||||||
close(pipe_into_cmd[1]);
|
close(pipe_into_cmd[0]);
|
||||||
close(pipe_outof_cmd[0]);
|
|
||||||
close(pipe_outof_cmd[1]);
|
|
||||||
return 1;
|
|
||||||
} else if (fcntl(pipe_outof_cmd[0], F_SETFL, O_NONBLOCK) != 0) {
|
|
||||||
// Unable to set non-blocking on outof-read-pipe.
|
|
||||||
close(pipe_into_cmd[0]);
|
|
||||||
close(pipe_into_cmd[1]);
|
|
||||||
close(pipe_outof_cmd[0]);
|
|
||||||
close(pipe_outof_cmd[1]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state && state->parsed && state->parsed->decompressor) {
|
|
||||||
if (simple_archiver_de_compress(pipe_into_cmd, pipe_outof_cmd,
|
|
||||||
state->parsed->decompressor,
|
|
||||||
&decompressor_pid) != 0) {
|
|
||||||
// Failed to spawn compressor.
|
|
||||||
close(pipe_into_cmd[1]);
|
close(pipe_into_cmd[1]);
|
||||||
close(pipe_outof_cmd[0]);
|
close(pipe_outof_cmd[0]);
|
||||||
|
close(pipe_outof_cmd[1]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} else if (fcntl(pipe_outof_cmd[0], F_SETFL, O_NONBLOCK) != 0) {
|
||||||
} else {
|
// Unable to set non-blocking on outof-read-pipe.
|
||||||
if (simple_archiver_de_compress(pipe_into_cmd, pipe_outof_cmd,
|
close(pipe_into_cmd[0]);
|
||||||
decompressor_cmd,
|
|
||||||
&decompressor_pid) != 0) {
|
|
||||||
// Failed to spawn compressor.
|
|
||||||
close(pipe_into_cmd[1]);
|
close(pipe_into_cmd[1]);
|
||||||
close(pipe_outof_cmd[0]);
|
close(pipe_outof_cmd[0]);
|
||||||
|
close(pipe_outof_cmd[1]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Close unnecessary pipe fds on this end of the transfer.
|
if (state && state->parsed && state->parsed->decompressor) {
|
||||||
close(pipe_into_cmd[0]);
|
if (simple_archiver_de_compress(pipe_into_cmd, pipe_outof_cmd,
|
||||||
close(pipe_outof_cmd[1]);
|
state->parsed->decompressor,
|
||||||
|
&decompressor_pid) != 0) {
|
||||||
|
// Failed to spawn compressor.
|
||||||
|
close(pipe_into_cmd[1]);
|
||||||
|
close(pipe_outof_cmd[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (simple_archiver_de_compress(pipe_into_cmd, pipe_outof_cmd,
|
||||||
|
decompressor_cmd,
|
||||||
|
&decompressor_pid) != 0) {
|
||||||
|
// Failed to spawn compressor.
|
||||||
|
close(pipe_into_cmd[1]);
|
||||||
|
close(pipe_outof_cmd[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t compressed_file_size = u64;
|
// Close unnecessary pipe fds on this end of the transfer.
|
||||||
int write_again = 0;
|
close(pipe_into_cmd[0]);
|
||||||
int write_pipe_done = 0;
|
close(pipe_outof_cmd[1]);
|
||||||
int read_pipe_done = 0;
|
|
||||||
ssize_t fread_ret;
|
uint64_t compressed_file_size = u64;
|
||||||
char recv_buf[1024];
|
int write_again = 0;
|
||||||
size_t amount_to_read;
|
int write_pipe_done = 0;
|
||||||
while (!write_pipe_done || !read_pipe_done) {
|
int read_pipe_done = 0;
|
||||||
// Read from file.
|
ssize_t fread_ret;
|
||||||
if (!write_pipe_done) {
|
char recv_buf[1024];
|
||||||
if (!write_again && compressed_file_size != 0) {
|
size_t amount_to_read;
|
||||||
if (compressed_file_size > 1024) {
|
while (!write_pipe_done || !read_pipe_done) {
|
||||||
amount_to_read = 1024;
|
// Read from file.
|
||||||
} else {
|
if (!write_pipe_done) {
|
||||||
amount_to_read = compressed_file_size;
|
if (!write_again && compressed_file_size != 0) {
|
||||||
|
if (compressed_file_size > 1024) {
|
||||||
|
amount_to_read = 1024;
|
||||||
|
} else {
|
||||||
|
amount_to_read = compressed_file_size;
|
||||||
|
}
|
||||||
|
fread_ret = fread(buf, 1, amount_to_read, in_f);
|
||||||
|
if (fread_ret > 0) {
|
||||||
|
compressed_file_size -= fread_ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fread_ret = fread(buf, 1, amount_to_read, in_f);
|
|
||||||
|
// Send over pipe to decompressor.
|
||||||
if (fread_ret > 0) {
|
if (fread_ret > 0) {
|
||||||
compressed_file_size -= fread_ret;
|
ssize_t write_ret = write(pipe_into_cmd[1], buf, fread_ret);
|
||||||
|
if (write_ret == fread_ret) {
|
||||||
|
// Successful write.
|
||||||
|
write_again = 0;
|
||||||
|
if (compressed_file_size == 0) {
|
||||||
|
close(pipe_into_cmd[1]);
|
||||||
|
write_pipe_done = 1;
|
||||||
|
}
|
||||||
|
} else if (write_ret == -1) {
|
||||||
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
|
write_again = 1;
|
||||||
|
} else {
|
||||||
|
// Error.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Should be unreachable, error.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send over pipe to decompressor.
|
// Read output from decompressor and write to file.
|
||||||
if (fread_ret > 0) {
|
if (!read_pipe_done) {
|
||||||
ssize_t write_ret = write(pipe_into_cmd[1], buf, fread_ret);
|
ssize_t read_ret = read(pipe_outof_cmd[0], recv_buf, 1024);
|
||||||
if (write_ret == fread_ret) {
|
if (read_ret > 0) {
|
||||||
// Successful write.
|
size_t fwrite_ret = fwrite(recv_buf, 1, read_ret, out_f);
|
||||||
write_again = 0;
|
if (fwrite_ret == (size_t)read_ret) {
|
||||||
if (compressed_file_size == 0) {
|
// Success.
|
||||||
close(pipe_into_cmd[1]);
|
} else if (ferror(out_f)) {
|
||||||
write_pipe_done = 1;
|
// Error.
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
// Invalid state, error.
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (write_ret == -1) {
|
} else if (read_ret == -1) {
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
write_again = 1;
|
// No bytes to read yet.
|
||||||
} else {
|
} else {
|
||||||
// Error.
|
// Error.
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
} else if (read_ret == 0) {
|
||||||
|
// EOF.
|
||||||
|
read_pipe_done = 1;
|
||||||
|
close(pipe_outof_cmd[0]);
|
||||||
|
free_FILE_helper(&out_f);
|
||||||
} else {
|
} else {
|
||||||
// Should be unreachable, error.
|
// Invalid state (unreachable?), error.
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read output from decompressor and write to file.
|
waitpid(decompressor_pid, NULL, 0);
|
||||||
if (!read_pipe_done) {
|
} else {
|
||||||
ssize_t read_ret = read(pipe_outof_cmd[0], recv_buf, 1024);
|
uint64_t compressed_file_size = u64;
|
||||||
if (read_ret > 0) {
|
ssize_t fread_ret;
|
||||||
size_t fwrite_ret = fwrite(recv_buf, 1, read_ret, out_f);
|
while (compressed_file_size != 0) {
|
||||||
if (fwrite_ret == (size_t)read_ret) {
|
if (compressed_file_size > 1024) {
|
||||||
// Success.
|
fread_ret = fread(buf, 1, 1024, in_f);
|
||||||
} else if (ferror(out_f)) {
|
if (ferror(in_f)) {
|
||||||
// Error.
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
// Invalid state, error.
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else if (read_ret == -1) {
|
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
||||||
// No bytes to read yet.
|
|
||||||
} else {
|
|
||||||
// Error.
|
// Error.
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (read_ret == 0) {
|
fwrite(buf, 1, fread_ret, out_f);
|
||||||
// EOF.
|
if (ferror(out_f)) {
|
||||||
read_pipe_done = 1;
|
// Error.
|
||||||
close(pipe_outof_cmd[0]);
|
return 1;
|
||||||
free_FILE_helper(&out_f);
|
}
|
||||||
|
compressed_file_size -= fread_ret;
|
||||||
} else {
|
} else {
|
||||||
// Invalid state (unreachable?), error.
|
fread_ret = fread(buf, 1, compressed_file_size, in_f);
|
||||||
return 1;
|
if (ferror(in_f)) {
|
||||||
|
// Error.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fwrite(buf, 1, fread_ret, out_f);
|
||||||
|
if (ferror(out_f)) {
|
||||||
|
// Error.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
compressed_file_size -= fread_ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
waitpid(decompressor_pid, NULL, 0);
|
|
||||||
|
|
||||||
if (chmod((const char *)out_f_name, permissions) == -1) {
|
if (chmod((const char *)out_f_name, permissions) == -1) {
|
||||||
// Error.
|
// Error.
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Reference in a new issue