Refactorings for v1 extract, other refactorings
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 5s
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 5s
This commit is contained in:
parent
b09948d245
commit
c7cd445139
5 changed files with 273 additions and 9 deletions
|
@ -118,8 +118,16 @@ Following the link-count bytes, the following bytes are added for each symlink:
|
|||
1. The first byte.
|
||||
1. The first bit is UNSET if relative links are preferred, and is SET if
|
||||
absolute links are preferred.
|
||||
2. The second bit is "user read permission".
|
||||
3. The third bit is "user write permission".
|
||||
4. The fourth bit is "user execute permission".
|
||||
5. The fifth bit is "group read permission".
|
||||
6. The sixth bit is "group write permission".
|
||||
7. The seventh bit is "group execute permission".
|
||||
8. The eighth bit is "other read permission".
|
||||
2. The second byte.
|
||||
1. Currently unused.
|
||||
1. The first bit is "other write permission".
|
||||
2. The second bit is "other execute permission".
|
||||
2. 2 bytes 16-bit unsigned integer "link name" in big-endian. This does not
|
||||
include the NULL at the end of the string. Must not be zero.
|
||||
3. X bytes of link-name (length defined by previous value). Is a NULL-terminated
|
||||
|
|
Binary file not shown.
250
src/archiver.c
250
src/archiver.c
|
@ -1112,6 +1112,86 @@ void cleanup_internal_file_info(SDArchiverInternalFileInfo **file_info) {
|
|||
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||
mode_t permissions_from_bits_v1_symlink(const uint8_t flags[2],
|
||||
uint_fast8_t print) {
|
||||
mode_t permissions = 0;
|
||||
|
||||
if ((flags[0] & 2) != 0) {
|
||||
permissions |= S_IRUSR;
|
||||
if (print) {
|
||||
fprintf(stderr, "r");
|
||||
}
|
||||
} else if (print) {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((flags[0] & 4) != 0) {
|
||||
permissions |= S_IWUSR;
|
||||
if (print) {
|
||||
fprintf(stderr, "w");
|
||||
}
|
||||
} else if (print) {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((flags[0] & 8) != 0) {
|
||||
permissions |= S_IXUSR;
|
||||
if (print) {
|
||||
fprintf(stderr, "x");
|
||||
}
|
||||
} else if (print) {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((flags[0] & 0x10) != 0) {
|
||||
permissions |= S_IRGRP;
|
||||
if (print) {
|
||||
fprintf(stderr, "r");
|
||||
}
|
||||
} else if (print) {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((flags[0] & 0x20) != 0) {
|
||||
permissions |= S_IWGRP;
|
||||
if (print) {
|
||||
fprintf(stderr, "w");
|
||||
}
|
||||
} else if (print) {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((flags[0] & 0x40) != 0) {
|
||||
permissions |= S_IXGRP;
|
||||
if (print) {
|
||||
fprintf(stderr, "x");
|
||||
}
|
||||
} else if (print) {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((flags[0] & 0x80) != 0) {
|
||||
permissions |= S_IROTH;
|
||||
if (print) {
|
||||
fprintf(stderr, "r");
|
||||
}
|
||||
} else if (print) {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((flags[1] & 1) != 0) {
|
||||
permissions |= S_IWOTH;
|
||||
if (print) {
|
||||
fprintf(stderr, "w");
|
||||
}
|
||||
} else if (print) {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((flags[1] & 2) != 0) {
|
||||
permissions |= S_IXOTH;
|
||||
if (print) {
|
||||
fprintf(stderr, "x");
|
||||
}
|
||||
} else if (print) {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
mode_t permissions_from_bits_version_1(const uint8_t flags[4],
|
||||
uint_fast8_t print) {
|
||||
mode_t permissions = 0;
|
||||
|
@ -1191,6 +1271,55 @@ mode_t permissions_from_bits_version_1(const uint8_t flags[4],
|
|||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
void print_permissions(mode_t permissions) {
|
||||
if ((permissions & S_IRUSR)) {
|
||||
fprintf(stderr, "r");
|
||||
} else {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((permissions & S_IWUSR)) {
|
||||
fprintf(stderr, "w");
|
||||
} else {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((permissions & S_IXUSR)) {
|
||||
fprintf(stderr, "x");
|
||||
} else {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((permissions & S_IRGRP)) {
|
||||
fprintf(stderr, "r");
|
||||
} else {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((permissions & S_IWGRP)) {
|
||||
fprintf(stderr, "w");
|
||||
} else {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((permissions & S_IXGRP)) {
|
||||
fprintf(stderr, "x");
|
||||
} else {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((permissions & S_IROTH)) {
|
||||
fprintf(stderr, "r");
|
||||
} else {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((permissions & S_IWOTH)) {
|
||||
fprintf(stderr, "w");
|
||||
} else {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((permissions & S_IXOTH)) {
|
||||
fprintf(stderr, "x");
|
||||
} else {
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void simple_archiver_internal_cleanup_int_fd(int *fd) {
|
||||
|
@ -1451,6 +1580,18 @@ int simple_archiver_write_v0(FILE *out_f, SDArchiverState *state,
|
|||
|
||||
int simple_archiver_write_v1(FILE *out_f, SDArchiverState *state,
|
||||
const SDArchiverLinkedList *filenames) {
|
||||
// First create a "set" of absolute paths to given filenames.
|
||||
__attribute__((cleanup(simple_archiver_hash_map_free)))
|
||||
SDArchiverHashMap *abs_filenames = simple_archiver_hash_map_init();
|
||||
void **ptr_array = malloc(sizeof(void *) * 2);
|
||||
ptr_array[0] = abs_filenames;
|
||||
ptr_array[1] = (void *)state->parsed->user_cwd;
|
||||
if (simple_archiver_list_get(filenames, filenames_to_abs_map_fn, ptr_array)) {
|
||||
free(ptr_array);
|
||||
return SDAS_FAILED_TO_CREATE_MAP;
|
||||
}
|
||||
free(ptr_array);
|
||||
|
||||
// TODO Impl.
|
||||
fprintf(stderr, "Writing v1 unimplemented\n");
|
||||
return SDAS_INTERNAL_ERROR;
|
||||
|
@ -2396,6 +2537,13 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|||
return SDAS_INVALID_FILE;
|
||||
}
|
||||
const uint_fast8_t absolute_preferred = (buf[0] & 1) ? 1 : 0;
|
||||
|
||||
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||
mode_t permissions = permissions_from_bits_v1_symlink(buf, 0);
|
||||
#endif
|
||||
|
||||
uint_fast8_t link_extracted = 0;
|
||||
uint_fast8_t skip_due_to_map = 0;
|
||||
|
||||
|
@ -2417,6 +2565,13 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|||
|
||||
if (!do_extract) {
|
||||
fprintf(stderr, " Link name: %s\n", link_name);
|
||||
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||
fprintf(stderr, " Link Permissions: ");
|
||||
print_permissions(permissions);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (working_files_map &&
|
||||
|
@ -2445,12 +2600,49 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||
simple_archiver_helper_make_dirs(link_name);
|
||||
int_fast8_t link_create_retry = 0;
|
||||
V1_SYMLINK_CREATE_RETRY_0:
|
||||
ret = symlink(path, link_name);
|
||||
if (ret == -1) {
|
||||
if (link_create_retry) {
|
||||
fprintf(stderr,
|
||||
"WARNING: Failed to create symlink after removing existing "
|
||||
"symlink!\n");
|
||||
goto V1_SYMLINK_CREATE_AFTER_0;
|
||||
} else if (errno == EEXIST) {
|
||||
if ((state->parsed->flags & 8) == 0) {
|
||||
fprintf(stderr,
|
||||
"WARNING: Symlink already exists and "
|
||||
"\"--overwrite-extract\" is not specified, skipping!\n");
|
||||
goto V1_SYMLINK_CREATE_AFTER_0;
|
||||
} else {
|
||||
fprintf(
|
||||
stderr,
|
||||
"NOTICE: Symlink already exists and \"--overwrite-extract\" "
|
||||
"specified, attempting to overwrite...\n");
|
||||
unlink(link_name);
|
||||
link_create_retry = 1;
|
||||
goto V1_SYMLINK_CREATE_RETRY_0;
|
||||
}
|
||||
}
|
||||
return SDAS_FAILED_TO_EXTRACT_SYMLINK;
|
||||
}
|
||||
ret = fchmodat(AT_FDCWD, link_name, permissions, AT_SYMLINK_NOFOLLOW);
|
||||
if (ret == -1) {
|
||||
if (errno == EOPNOTSUPP) {
|
||||
fprintf(stderr,
|
||||
"NOTICE: Setting permissions of symlink is not supported "
|
||||
"by FS/OS!\n");
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"WARNING: Failed to set permissions of symlink (%d)!\n",
|
||||
errno);
|
||||
}
|
||||
}
|
||||
link_extracted = 1;
|
||||
fprintf(stderr, " %s -> %s\n", link_name, path);
|
||||
V1_SYMLINK_CREATE_AFTER_0:
|
||||
link_create_retry = 1;
|
||||
#endif
|
||||
} else {
|
||||
fprintf(stderr, " Abs path: %s\n", path);
|
||||
|
@ -2478,12 +2670,49 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
||||
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
||||
simple_archiver_helper_make_dirs(link_name);
|
||||
int_fast8_t link_create_retry = 0;
|
||||
V1_SYMLINK_CREATE_RETRY_1:
|
||||
ret = symlink(path, link_name);
|
||||
if (ret == -1) {
|
||||
if (link_create_retry) {
|
||||
fprintf(stderr,
|
||||
"WARNING: Failed to create symlink after removing existing "
|
||||
"symlink!\n");
|
||||
goto V1_SYMLINK_CREATE_AFTER_1;
|
||||
} else if (errno == EEXIST) {
|
||||
if ((state->parsed->flags & 8) == 0) {
|
||||
fprintf(stderr,
|
||||
"WARNING: Symlink already exists and "
|
||||
"\"--overwrite-extract\" is not specified, skipping!\n");
|
||||
goto V1_SYMLINK_CREATE_AFTER_1;
|
||||
} else {
|
||||
fprintf(
|
||||
stderr,
|
||||
"NOTICE: Symlink already exists and \"--overwrite-extract\" "
|
||||
"specified, attempting to overwrite...\n");
|
||||
unlink(link_name);
|
||||
link_create_retry = 1;
|
||||
goto V1_SYMLINK_CREATE_RETRY_1;
|
||||
}
|
||||
}
|
||||
return SDAS_FAILED_TO_EXTRACT_SYMLINK;
|
||||
}
|
||||
ret = fchmodat(AT_FDCWD, link_name, permissions, AT_SYMLINK_NOFOLLOW);
|
||||
if (ret == -1) {
|
||||
if (errno == EOPNOTSUPP) {
|
||||
fprintf(stderr,
|
||||
"NOTICE: Setting permissions of symlink is not supported "
|
||||
"by FS/OS!\n");
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"WARNING: Failed to set permissions of symlink (%d)!\n",
|
||||
errno);
|
||||
}
|
||||
}
|
||||
link_extracted = 1;
|
||||
fprintf(stderr, " %s -> %s\n", link_name, path);
|
||||
V1_SYMLINK_CREATE_AFTER_1:
|
||||
link_create_retry = 1;
|
||||
#endif
|
||||
} else {
|
||||
fprintf(stderr, " Rel path: %s\n", path);
|
||||
|
@ -2539,6 +2768,27 @@ int simple_archiver_parse_archive_version_1(FILE *in_f, int_fast8_t do_extract,
|
|||
}
|
||||
file_info->filename[u16] = 0;
|
||||
|
||||
if (state && state->parsed && (state->parsed->flags & 8) != 0) {
|
||||
int fd = open((const char *)buf, O_RDONLY | O_NOFOLLOW);
|
||||
if (fd == -1) {
|
||||
if (errno == ELOOP) {
|
||||
// Exists as a symlink.
|
||||
fprintf(stderr,
|
||||
"WARNING: Filename \"%s\" already exists as symlink, "
|
||||
"removing...\n",
|
||||
(const char *)buf);
|
||||
unlink((const char *)buf);
|
||||
} else {
|
||||
// File doesn't exist, do nothing.
|
||||
}
|
||||
} else {
|
||||
close(fd);
|
||||
fprintf(stderr, "WARNING: File \"%s\" already exists, removing...\n",
|
||||
(const char *)buf);
|
||||
unlink((const char *)buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (fread(file_info->bit_flags, 1, 4, in_f) != 4) {
|
||||
return SDAS_INVALID_FILE;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ typedef struct SDArchiverState {
|
|||
size_t digits;
|
||||
} SDArchiverState;
|
||||
|
||||
enum SDArchiverStateReturns {
|
||||
typedef enum SDArchiverStateReturns {
|
||||
SDAS_SUCCESS = 0,
|
||||
SDAS_HEADER_ALREADY_WRITTEN = 1,
|
||||
SDAS_FAILED_TO_WRITE,
|
||||
|
@ -53,7 +53,7 @@ enum SDArchiverStateReturns {
|
|||
SDAS_FAILED_TO_EXTRACT_SYMLINK,
|
||||
SDAS_FAILED_TO_CHANGE_CWD,
|
||||
SDAS_INVALID_WRITE_VERSION
|
||||
};
|
||||
} SDArchiverStateReturns;
|
||||
|
||||
/// Returned pointer must not be freed.
|
||||
char *simple_archiver_error_to_string(enum SDArchiverStateReturns error);
|
||||
|
|
18
src/main.c
18
src/main.c
|
@ -97,7 +97,8 @@ int main(int argc, const char **argv) {
|
|||
int ret = simple_archiver_write_all(file, state, filenames);
|
||||
if (ret != SDAS_SUCCESS) {
|
||||
fprintf(stderr, "Error during writing.\n");
|
||||
char *error_str = simple_archiver_error_to_string(ret);
|
||||
char *error_str =
|
||||
simple_archiver_error_to_string((SDArchiverStateReturns)ret);
|
||||
fprintf(stderr, " %s\n", error_str);
|
||||
}
|
||||
fclose(file);
|
||||
|
@ -113,7 +114,8 @@ int main(int argc, const char **argv) {
|
|||
int ret = simple_archiver_write_all(stdout, state, filenames);
|
||||
if (ret != SDAS_SUCCESS) {
|
||||
fprintf(stderr, "Error during writing.\n");
|
||||
char *error_str = simple_archiver_error_to_string(ret);
|
||||
char *error_str =
|
||||
simple_archiver_error_to_string((SDArchiverStateReturns)ret);
|
||||
fprintf(stderr, " %s\n", error_str);
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +132,8 @@ int main(int argc, const char **argv) {
|
|||
int ret = simple_archiver_parse_archive_info(file, 0, NULL);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Error during archive checking/examining.\n");
|
||||
char *error_str = simple_archiver_error_to_string(ret);
|
||||
char *error_str =
|
||||
simple_archiver_error_to_string((SDArchiverStateReturns)ret);
|
||||
fprintf(stderr, " %s\n", error_str);
|
||||
}
|
||||
fclose(file);
|
||||
|
@ -138,7 +141,8 @@ int main(int argc, const char **argv) {
|
|||
int ret = simple_archiver_parse_archive_info(stdin, 0, NULL);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Error during archive checking/examining.\n");
|
||||
char *error_str = simple_archiver_error_to_string(ret);
|
||||
char *error_str =
|
||||
simple_archiver_error_to_string((SDArchiverStateReturns)ret);
|
||||
fprintf(stderr, " %s\n", error_str);
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +161,8 @@ int main(int argc, const char **argv) {
|
|||
int ret = simple_archiver_parse_archive_info(file, 1, state);
|
||||
if (ret != SDAS_SUCCESS) {
|
||||
fprintf(stderr, "Error during archive extracting.\n");
|
||||
char *error_str = simple_archiver_error_to_string(ret);
|
||||
char *error_str =
|
||||
simple_archiver_error_to_string((SDArchiverStateReturns)ret);
|
||||
fprintf(stderr, " %s\n", error_str);
|
||||
}
|
||||
fclose(file);
|
||||
|
@ -165,7 +170,8 @@ int main(int argc, const char **argv) {
|
|||
int ret = simple_archiver_parse_archive_info(stdin, 1, state);
|
||||
if (ret != SDAS_SUCCESS) {
|
||||
fprintf(stderr, "Error during archive extracting.\n");
|
||||
char *error_str = simple_archiver_error_to_string(ret);
|
||||
char *error_str =
|
||||
simple_archiver_error_to_string((SDArchiverStateReturns)ret);
|
||||
fprintf(stderr, " %s\n", error_str);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue