]> git.seodisparate.com - SimpleArchiver/commitdiff
Add flag to force-set permissions for empty dirs
authorStephen Seo <seo.disparate@gmail.com>
Wed, 12 Feb 2025 05:52:47 +0000 (14:52 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Wed, 12 Feb 2025 05:52:47 +0000 (14:52 +0900)
Note this only affects file format versions 2 and 3.

src/archiver.c
src/parser.c
src/parser.h

index 6a8edc1bcb8b55954114eb9f103d51d550f7c620..84bb079331cd4aad4494ce7ab9f10c3fcb34cfb9 100644 (file)
@@ -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",
index a84d80560e3acc73c600f18ef60ba08ead81ff41..64f846928dcb1d42d65d204c6230ccdc5dca5bf8 100644 (file)
@@ -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) {
index 9eadae60821d6988127544facb61bdc8b184e519..ff0755df8ac62778ea3ff40c856ea0c001ad2888 100644 (file)
@@ -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.