From 26395fcefb8a9855cf9f6467d0eba1ae9b874d00 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Wed, 12 Feb 2025 14:52:47 +0900 Subject: [PATCH] Add flag to force-set permissions for empty dirs Note this only affects file format versions 2 and 3. --- src/archiver.c | 12 ++++++++++-- src/parser.c | 38 ++++++++++++++++++++++++++++++++++++++ src/parser.h | 2 ++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/archiver.c b/src/archiver.c index 6a8edc1..84bb079 100644 --- a/src/archiver.c +++ b/src/archiver.c @@ -8165,7 +8165,11 @@ int simple_archiver_parse_archive_version_2(FILE *in_f, int_fast8_t do_extract, SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX mode_t perms = simple_archiver_internal_bits_to_mode_t(perms_flags); - ret = chmod(abs_dir_path, perms); + ret = chmod(abs_dir_path, + state && (state->parsed->flags & 0x10000) + ? simple_archiver_internal_permissions_to_mode_t( + state->parsed->empty_dir_permissions) + : perms); if (ret != 0) { fprintf(stderr, "WARNING: Failed to set permissions on dir \"%s\"!\n", @@ -9850,7 +9854,11 @@ int simple_archiver_parse_archive_version_3(FILE *in_f, SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX mode_t perms = simple_archiver_internal_bits_to_mode_t(perms_flags); - ret = chmod(abs_dir_path, perms); + ret = chmod(abs_dir_path, + state && (state->parsed->flags & 0x10000) + ? simple_archiver_internal_permissions_to_mode_t( + state->parsed->empty_dir_permissions) + : perms); if (ret != 0) { fprintf(stderr, "WARNING: Failed to set permissions on dir \"%s\"!\n", diff --git a/src/parser.c b/src/parser.c index a84d805..64f8469 100644 --- a/src/parser.c +++ b/src/parser.c @@ -239,6 +239,10 @@ void simple_archiver_print_usage(void) { "--force-dir-permissions <3-octal-values> : Force set permissions " "for directories on archive creation/extraction\n" " Must be three octal characters like \"755\" or \"440\"\n"); + fprintf(stderr, + "--force-empty-dir-permissions <3-octal-values> : Force set EMPTY " + "dir permissions. Like \"--force-dir-permissions\", but for empty " + "directories.\n"); fprintf(stderr, "--version : prints version and exits\n"); fprintf(stderr, "-- : specifies remaining arguments are files to archive/extract\n"); @@ -270,6 +274,7 @@ SDArchiverParsed simple_archiver_create_parsed(void) { parsed.gid = 0; parsed.file_permissions = 0; parsed.dir_permissions = 0; + parsed.empty_dir_permissions = 0; parsed.users_infos = simple_archiver_users_get_system_info(); parsed.mappings.UidToUname = simple_archiver_hash_map_init(); parsed.mappings.UnameToUid = simple_archiver_hash_map_init(); @@ -645,6 +650,39 @@ int simple_archiver_parse_args(int argc, const char **argv, out->flags |= 0x2000; + --argc; + ++argv; + } else if (strcmp(argv[0], "--force-empty-dir-permissions") == 0) { + if (argc < 2 + || strlen(argv[1]) != 3 + || (!(argv[1][0] >= '0' && argv[1][0] <= '7')) + || (!(argv[1][1] >= '0' && argv[1][1] <= '7')) + || (!(argv[1][2] >= '0' && argv[1][2] <= '7')) + ) { + fprintf(stderr, + "ERROR: --force-empty-dir-permissions expects 3 octal values" + " (e.g. \"755\" or \"440\")!\n"); + simple_archiver_print_usage(); + return 1; + } + + uint_fast8_t value = (uint_fast8_t)(argv[1][0] - '0'); + out->empty_dir_permissions |= (value & 4) ? 1 : 0; + out->empty_dir_permissions |= (value & 2) ? 2 : 0; + out->empty_dir_permissions |= (value & 1) ? 4 : 0; + + value = (uint_fast8_t)(argv[1][1] - '0'); + out->empty_dir_permissions |= (value & 4) ? 8 : 0; + out->empty_dir_permissions |= (value & 2) ? 0x10 : 0; + out->empty_dir_permissions |= (value & 1) ? 0x20 : 0; + + value = (uint_fast8_t)(argv[1][2] - '0'); + out->empty_dir_permissions |= (value & 4) ? 0x40 : 0; + out->empty_dir_permissions |= (value & 2) ? 0x80 : 0; + out->empty_dir_permissions |= (value & 1) ? 0x100 : 0; + + out->flags |= 0x10000; + --argc; ++argv; } else if (strcmp(argv[0], "--version") == 0) { diff --git a/src/parser.h b/src/parser.h index 9eadae6..ff0755d 100644 --- a/src/parser.h +++ b/src/parser.h @@ -58,6 +58,7 @@ typedef struct SDArchiverParsed { /// 0b xx1x xxxx xxxx xxxx - Force set directory permissions. /// 0b x1xx xxxx xxxx xxxx - Prefer UID over Username when extracting. /// 0b 1xxx xxxx xxxx xxxx - Prefer GID over Group when extracting. + /// 0b xxxx xxx1 xxxx xxxx xxxx xxxx - Force set empty directory permissions. uint32_t flags; /// Null-terminated string. char *filename; @@ -91,6 +92,7 @@ typedef struct SDArchiverParsed { /// 0b xxx1 xxxx xxxx - other execute uint_fast16_t file_permissions; uint_fast16_t dir_permissions; + uint_fast16_t empty_dir_permissions; UsersInfos users_infos; SDA_UGMapping mappings; /// Prefix for archived/extracted paths. -- 2.49.0