Fix extracting when no compressor was used
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 4s

This commit is contained in:
Stephen Seo 2024-07-18 14:17:50 +09:00
parent 4cb4184338
commit 5b3a7e3994

View file

@ -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;