return 1;
}
- if ((stat_buf.st_mode & S_IRUSR) != 0) {
- ((uint8_t *)temp_to_write->buf)[0] |= 0x2;
- }
- if ((stat_buf.st_mode & S_IWUSR) != 0) {
- ((uint8_t *)temp_to_write->buf)[0] |= 0x4;
- }
- if ((stat_buf.st_mode & S_IXUSR) != 0) {
- ((uint8_t *)temp_to_write->buf)[0] |= 0x8;
- }
- if ((stat_buf.st_mode & S_IRGRP) != 0) {
- ((uint8_t *)temp_to_write->buf)[0] |= 0x10;
- }
- if ((stat_buf.st_mode & S_IWGRP) != 0) {
- ((uint8_t *)temp_to_write->buf)[0] |= 0x20;
- }
- if ((stat_buf.st_mode & S_IXGRP) != 0) {
- ((uint8_t *)temp_to_write->buf)[0] |= 0x40;
- }
- if ((stat_buf.st_mode & S_IROTH) != 0) {
- ((uint8_t *)temp_to_write->buf)[0] |= 0x80;
- }
- if ((stat_buf.st_mode & S_IWOTH) != 0) {
- ((uint8_t *)temp_to_write->buf)[1] |= 0x1;
- }
- if ((stat_buf.st_mode & S_IXOTH) != 0) {
- ((uint8_t *)temp_to_write->buf)[1] |= 0x2;
+ if (state->parsed->flags & 0x1000) {
+ ((uint8_t *)temp_to_write->buf)[0] |= (state->parsed->file_permissions & 0x7F) << 1;
+ ((uint8_t *)temp_to_write->buf)[1] |= (state->parsed->file_permissions & 0x18) >> 7;
+ } else {
+ if ((stat_buf.st_mode & S_IRUSR) != 0) {
+ ((uint8_t *)temp_to_write->buf)[0] |= 0x2;
+ }
+ if ((stat_buf.st_mode & S_IWUSR) != 0) {
+ ((uint8_t *)temp_to_write->buf)[0] |= 0x4;
+ }
+ if ((stat_buf.st_mode & S_IXUSR) != 0) {
+ ((uint8_t *)temp_to_write->buf)[0] |= 0x8;
+ }
+ if ((stat_buf.st_mode & S_IRGRP) != 0) {
+ ((uint8_t *)temp_to_write->buf)[0] |= 0x10;
+ }
+ if ((stat_buf.st_mode & S_IWGRP) != 0) {
+ ((uint8_t *)temp_to_write->buf)[0] |= 0x20;
+ }
+ if ((stat_buf.st_mode & S_IXGRP) != 0) {
+ ((uint8_t *)temp_to_write->buf)[0] |= 0x40;
+ }
+ if ((stat_buf.st_mode & S_IROTH) != 0) {
+ ((uint8_t *)temp_to_write->buf)[0] |= 0x80;
+ }
+ if ((stat_buf.st_mode & S_IWOTH) != 0) {
+ ((uint8_t *)temp_to_write->buf)[1] |= 0x1;
+ }
+ if ((stat_buf.st_mode & S_IXOTH) != 0) {
+ ((uint8_t *)temp_to_write->buf)[1] |= 0x2;
+ }
}
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
((uint8_t *)temp_to_write->buf)[0] |= 0xE;
#endif
+ if (state->parsed->flags & 0x1000) {
+ ((uint8_t *)temp_to_write->buf)[0] = (uint8_t)((state->parsed->file_permissions & 0x7F) << 1);
+
+ ((uint8_t *)temp_to_write->buf)[1] &= 0xC;
+ ((uint8_t *)temp_to_write->buf)[1] |= (uint8_t)((state->parsed->file_permissions & 0x18) >> 7);
+ }
+
simple_archiver_list_add(to_write, temp_to_write, free_internal_to_write);
// Write file length.
const char *user_cwd = ptr_array[2];
SDArchiverPHeap *pheap = ptr_array[3];
SDArchiverLinkedList *dirs_list = ptr_array[4];
+ const SDArchiverState *state = ptr_array[5];
if (file_info->filename) {
if (file_info->link_dest) {
+ // Is a symbolic link.
simple_archiver_list_add(
symlinks_list, file_info->filename,
simple_archiver_helper_datastructure_cleanup_nop);
} else if (dirs_list && (file_info->flags & 1) != 0) {
+ // Is a directory.
simple_archiver_list_add(
dirs_list, file_info->filename,
simple_archiver_helper_datastructure_cleanup_nop);
} else {
+ // Is a file.
SDArchiverInternalFileInfo *file_info_struct =
malloc(sizeof(SDArchiverInternalFileInfo));
file_info_struct->filename = strdup(file_info->filename);
file_info_struct->uid = stat_buf.st_uid;
file_info_struct->gid = stat_buf.st_gid;
#endif
+ if (state->parsed->flags & 0x1000) {
+ file_info_struct->bit_flags[0] = 0;
+ file_info_struct->bit_flags[1] &= 0xFE;
+
+ file_info_struct->bit_flags[0] |=
+ state->parsed->file_permissions & 0xFF;
+ file_info_struct->bit_flags[1] |=
+ (state->parsed->file_permissions & 0x100) >> 8;
+ }
+ if (state->parsed->flags & 0x400) {
+ file_info_struct->uid = state->parsed->uid;
+ }
+ if (state->parsed->flags & 0x800) {
+ file_info_struct->gid = state->parsed->gid;
+ }
__attribute__((cleanup(simple_archiver_helper_cleanup_FILE))) FILE *fd =
fopen(file_info_struct->filename, "rb");
if (!fd) {
int internal_write_dir_entries(void *data, void *ud) {
const char *dir = data;
- FILE *out_f = ud;
+ void **ptrs = ud;
+ FILE *out_f = ptrs[0];
+ const SDArchiverState *state = ptrs[1];
fprintf(stderr, " %s\n", dir);
uint8_t u8 = 0;
- if ((stat_buf.st_mode & S_IRUSR) != 0) {
- u8 |= 1;
- }
- if ((stat_buf.st_mode & S_IWUSR) != 0) {
- u8 |= 2;
- }
- if ((stat_buf.st_mode & S_IXUSR) != 0) {
- u8 |= 4;
- }
- if ((stat_buf.st_mode & S_IRGRP) != 0) {
- u8 |= 8;
- }
- if ((stat_buf.st_mode & S_IWGRP) != 0) {
- u8 |= 0x10;
- }
- if ((stat_buf.st_mode & S_IXGRP) != 0) {
- u8 |= 0x20;
- }
- if ((stat_buf.st_mode & S_IROTH) != 0) {
- u8 |= 0x40;
- }
- if ((stat_buf.st_mode & S_IWOTH) != 0) {
- u8 |= 0x80;
+ if (state && state->parsed->flags & 0x2000) {
+ u8 = state->parsed->dir_permissions & 0xFF;
+ } else {
+ if ((stat_buf.st_mode & S_IRUSR) != 0) {
+ u8 |= 1;
+ }
+ if ((stat_buf.st_mode & S_IWUSR) != 0) {
+ u8 |= 2;
+ }
+ if ((stat_buf.st_mode & S_IXUSR) != 0) {
+ u8 |= 4;
+ }
+ if ((stat_buf.st_mode & S_IRGRP) != 0) {
+ u8 |= 8;
+ }
+ if ((stat_buf.st_mode & S_IWGRP) != 0) {
+ u8 |= 0x10;
+ }
+ if ((stat_buf.st_mode & S_IXGRP) != 0) {
+ u8 |= 0x20;
+ }
+ if ((stat_buf.st_mode & S_IROTH) != 0) {
+ u8 |= 0x40;
+ }
+ if ((stat_buf.st_mode & S_IWOTH) != 0) {
+ u8 |= 0x80;
+ }
}
if(fwrite(&u8, 1, 1, out_f) != 1) {
}
u8 = 0;
- if ((stat_buf.st_mode & S_IXOTH) != 0) {
- u8 |= 1;
+ if (state && state->parsed->flags & 0x2000) {
+ u8 = (state->parsed->dir_permissions & 0x100) >> 8;
+ } else {
+ if ((stat_buf.st_mode & S_IXOTH) != 0) {
+ u8 |= 1;
+ }
}
if (fwrite(&u8, 1, 1, out_f) != 1) {
return 0;
}
+mode_t simple_archiver_internal_permissions_to_mode_t(uint_fast16_t permissions)
+{
+ return
+ ((permissions & 1) ? S_IRUSR : 0)
+ | ((permissions & 2) ? S_IWUSR : 0)
+ | ((permissions & 4) ? S_IXUSR : 0)
+ | ((permissions & 8) ? S_IRGRP : 0)
+ | ((permissions & 0x10) ? S_IWGRP : 0)
+ | ((permissions & 0x20) ? S_IXGRP : 0)
+ | ((permissions & 0x40) ? S_IROTH : 0)
+ | ((permissions & 0x80) ? S_IWOTH : 0)
+ | ((permissions & 0x100) ? S_IXOTH : 0);
+}
+
char *simple_archiver_error_to_string(enum SDArchiverStateReturns error) {
switch (error) {
case SDAS_SUCCESS:
? simple_archiver_priority_heap_init_less_fn(greater_fn)
: NULL;
- ptr_array = malloc(sizeof(void *) * 5);
+ ptr_array = malloc(sizeof(void *) * 6);
ptr_array[0] = symlinks_list;
ptr_array[1] = files_list;
ptr_array[2] = (void *)state->parsed->user_cwd;
ptr_array[3] = files_pheap;
ptr_array[4] = NULL;
+ ptr_array[5] = state;
if (simple_archiver_list_get(filenames, symlinks_and_files_from_files,
ptr_array)) {
return SDAS_FAILED_TO_WRITE;
}
// UID and GID.
+
+ // Forced UID/GID is already handled by "symlinks_and_files_from_files".
+
u32 = file_info_struct->uid;
simple_archiver_helper_32_bit_be(&u32);
if (fwrite(&u32, 4, 1, out_f) != 1) {
return SDAS_FAILED_TO_WRITE;
}
+
u32 = file_info_struct->gid;
simple_archiver_helper_32_bit_be(&u32);
if (fwrite(&u32, 4, 1, out_f) != 1) {
? simple_archiver_priority_heap_init_less_fn(greater_fn)
: NULL;
- ptr_array = malloc(sizeof(void *) * 5);
+ ptr_array = malloc(sizeof(void *) * 6);
ptr_array[0] = symlinks_list;
ptr_array[1] = files_list;
ptr_array[2] = (void *)state->parsed->user_cwd;
ptr_array[3] = files_pheap;
ptr_array[4] = dirs_list;
+ ptr_array[5] = state;
if (simple_archiver_list_get(filenames, symlinks_and_files_from_files,
ptr_array)) {
return SDAS_FAILED_TO_WRITE;
}
// UID and GID.
+
+ // Forced UID/GID is already handled by "symlinks_and_files_from_files".
+
u32 = file_info_struct->uid;
simple_archiver_helper_32_bit_be(&u32);
if (fwrite(&u32, 4, 1, out_f) != 1) {
return SDAS_FAILED_TO_WRITE;
}
- if (simple_archiver_list_get(dirs_list, internal_write_dir_entries, out_f)) {
+ void **void_ptrs = malloc(sizeof(void*) * 2);
+ void_ptrs[0] = out_f;
+ void_ptrs[1] = state;
+
+ if (simple_archiver_list_get(dirs_list,
+ internal_write_dir_entries,
+ void_ptrs)) {
+ free(void_ptrs);
return SDAS_INTERNAL_ERROR;
}
+ free(void_ptrs);
return SDAS_SUCCESS;
}
#endif
+ if (state && state->parsed->flags & 0x1000 && do_extract) {
+ fprintf(stderr,
+ "NOTICE: Forcing permissions as specified by "
+ "\"--force-file-permissions\"!\n");
+ permissions =
+ simple_archiver_internal_permissions_to_mode_t(
+ state->parsed->file_permissions);
+ }
+
if ((buf[0] & 1) == 0) {
// Not a sybolic link.
if (fread(&u64, 8, 1, in_f) != 1) {
if (do_extract && !skip && !skip_due_to_map) {
fprintf(stderr, " Extracting...\n");
- simple_archiver_helper_make_dirs((const char *)out_f_name);
+ simple_archiver_helper_make_dirs_perms(
+ (const char *)out_f_name,
+ (state->parsed->flags & 0x2000)
+ ? simple_archiver_internal_permissions_to_mode_t(
+ state->parsed->dir_permissions)
+ : (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH),
+ (state->parsed->flags & 0x400) ? state->parsed->uid : getuid(),
+ (state->parsed->flags & 0x800) ? state->parsed->gid : getgid());
+
out_f = fopen(out_f_name, "wb");
if (!out_f) {
fprintf(stderr,
}
if (do_extract && !skip) {
- simple_archiver_helper_make_dirs((const char *)out_f_name);
+ simple_archiver_helper_make_dirs_perms(
+ (const char *)out_f_name,
+ (state->parsed->flags & 0x2000)
+ ? simple_archiver_internal_permissions_to_mode_t(
+ state->parsed->dir_permissions)
+ : (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH),
+ (state->parsed->flags & 0x400) ? state->parsed->uid : getuid(),
+ (state->parsed->flags & 0x800) ? state->parsed->gid : getgid());
if (abs_path && rel_path) {
if (abs_preferred) {
#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_LINUX
- simple_archiver_helper_make_dirs(link_name);
+ simple_archiver_helper_make_dirs_perms(
+ link_name,
+ (state->parsed->flags & 0x2000)
+ ? simple_archiver_internal_permissions_to_mode_t(
+ state->parsed->dir_permissions)
+ : (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH),
+ (state->parsed->flags & 0x400) ? state->parsed->uid : getuid(),
+ (state->parsed->flags & 0x800) ? state->parsed->gid : getgid());
int_fast8_t link_create_retry = 0;
V1_SYMLINK_CREATE_RETRY_0:
ret = symlink(path, link_name);
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
- simple_archiver_helper_make_dirs(link_name);
+ simple_archiver_helper_make_dirs_perms(
+ link_name,
+ (state->parsed->flags & 0x2000)
+ ? simple_archiver_internal_permissions_to_mode_t(
+ state->parsed->dir_permissions)
+ : (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH),
+ (state->parsed->flags & 0x400) ? state->parsed->uid : getuid(),
+ (state->parsed->flags & 0x800) ? state->parsed->gid : getgid());
int_fast8_t link_create_retry = 0;
V1_SYMLINK_CREATE_RETRY_1:
ret = symlink(path, link_name);
errno);
}
}
+ if (state->parsed->flags & 0x400 || state->parsed->flags & 0x800) {
+ ret = fchownat(
+ AT_FDCWD,
+ link_name,
+ state->parsed->flags & 0x400 ? state->parsed->uid : getuid(),
+ state->parsed->flags & 0x800 ? state->parsed->gid : getgid(),
+ AT_SYMLINK_NOFOLLOW);
+ if (ret == -1) {
+ fprintf(stderr,
+ "WARNING: Failed to force set UID/GID of symlink \"%s\""
+ "(errno %d)!\n",
+ link_name,
+ errno);
+ }
+ }
link_extracted = 1;
fprintf(stderr, " %s -> %s\n", link_name, path);
V1_SYMLINK_CREATE_AFTER_1:
}
memcpy(&u32, buf, 4);
simple_archiver_helper_32_bit_be(&u32);
- file_info->uid = u32;
+ if (state && (state->parsed->flags & 0x400)) {
+ file_info->uid = state->parsed->uid;
+ } else {
+ file_info->uid = u32;
+ }
if (fread(buf, 1, 4, in_f) != 4) {
return SDAS_INVALID_FILE;
}
memcpy(&u32, buf, 4);
simple_archiver_helper_32_bit_be(&u32);
- file_info->gid = u32;
+ if (state && (state->parsed->flags & 0x800)) {
+ file_info->gid = state->parsed->gid;
+ } else {
+ file_info->gid = u32;
+ }
if (fread(buf, 1, 8, in_f) != 8) {
return SDAS_INVALID_FILE;
#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_version_1(file_info->bit_flags, 0);
+ mode_t permissions;
+ if (state->parsed->flags & 0x1000) {
+ permissions =
+ simple_archiver_internal_permissions_to_mode_t(
+ state->parsed->file_permissions);
+ } else {
+ permissions = permissions_from_bits_version_1(
+ file_info->bit_flags,
+ 0);
+ }
#endif
if ((state->parsed->flags & 8) == 0) {
// Check if file already exists.
}
}
- simple_archiver_helper_make_dirs(file_info->filename);
+ simple_archiver_helper_make_dirs_perms(
+ file_info->filename,
+ (state->parsed->flags & 0x2000)
+ ? simple_archiver_internal_permissions_to_mode_t(
+ state->parsed->dir_permissions)
+ : (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH),
+ (state->parsed->flags & 0x400) ? state->parsed->uid : getuid(),
+ (state->parsed->flags & 0x800) ? state->parsed->gid : getgid());
int ret = read_decomp_to_out_file(
file_info->filename, pipe_outof_read, (char *)buf,
SIMPLE_ARCHIVER_BUFFER_SIZE, file_info->file_size,
#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 =
+ mode_t permissions;
+
+ if (state->parsed->flags & 0x1000) {
+ permissions = simple_archiver_internal_permissions_to_mode_t(
+ state->parsed->file_permissions);
+ fprintf(stderr,
+ "NOTICE: Forcing permissions as specified by "
+ "\"--force-file-permissions\"!\n");
+ } else {
+ permissions =
permissions_from_bits_version_1(file_info->bit_flags, 0);
+ }
#endif
if ((state->parsed->flags & 8) == 0) {
// Check if file already exists.
continue;
}
}
- simple_archiver_helper_make_dirs(file_info->filename);
+ simple_archiver_helper_make_dirs_perms(
+ file_info->filename,
+ (state->parsed->flags & 0x2000)
+ ? simple_archiver_internal_permissions_to_mode_t(
+ state->parsed->dir_permissions)
+ : (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH),
+ (state->parsed->flags & 0x400) ? state->parsed->uid : getuid(),
+ (state->parsed->flags & 0x800) ? state->parsed->gid : getgid());
__attribute__((cleanup(simple_archiver_helper_cleanup_FILE)))
FILE *out_fd = fopen(file_info->filename, "wb");
int ret = read_fd_to_out_fd(in_f, out_fd, (char *)buf,
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
if (chmod(file_info->filename, permissions) == -1) {
+ fprintf(stderr,
+ "ERROR Failed to set permissions of file \"%s\"!\n",
+ file_info->filename);
return SDAS_INTERNAL_ERROR;
} else if (geteuid() == 0 &&
chown(file_info->filename, file_info->uid,
//fprintf(stderr, "DEBUG: abs_path is \"%s\"!\n", abs_path);
int ret = simple_archiver_helper_make_dirs_perms(
- abs_path,
- permissions_from_bits_version_1(perms_flags, 0),
- uid,
- gid);
+ abs_path,
+ state && (state->parsed->flags & 0x2000)
+ ? simple_archiver_internal_permissions_to_mode_t(
+ state->parsed->dir_permissions)
+ : (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH),
+ state && (state->parsed->flags & 0x400) ? state->parsed->uid : getuid(),
+ state && (state->parsed->flags & 0x800) ? state->parsed->gid : getgid());
if (ret != 0) {
fprintf(stderr, "ERROR: Failed to make dirs (%d)!\n", ret);
return SDAS_INTERNAL_ERROR;
fprintf(stderr,
"--no-preserve-empty-dirs : do NOT preserve empty dirs (only for file"
" format 2 and onwards)\n");
+ fprintf(stderr,
+ "--force-uid <uid> : Force set UID on archive creation/extraction\n");
+ fprintf(stderr,
+ "--force-gid <gid> : Force set GID on archive creation/extraction\n");
+ fprintf(stderr,
+ "--force-file-permissions <3-octal-values> : Force set permissions "
+ "for files on archive creation/extraction\n"
+ " Must be three octal characters like \"755\" or \"440\"\n");
+ fprintf(stderr,
+ "--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,
"-- : specifies remaining arguments are files to archive/extract\n");
fprintf(
parsed.user_cwd = NULL;
parsed.write_version = 2;
parsed.minimum_chunk_size = 4194304;
+ parsed.uid = 0;
+ parsed.gid = 0;
+ parsed.file_permissions = 0;
+ parsed.dir_permissions = 0;
return parsed;
}
out->flags &= 0xFFFFFFBF;
} else if (strcmp(argv[0], "--no-preserve-empty-dirs") == 0) {
out->flags |= 0x200;
+ } else if (strcmp(argv[0], "--force-uid") == 0) {
+ if (argc < 2) {
+ fprintf(stderr, "ERROR: --force-uid expects an integer argument!\n");
+ simple_archiver_print_usage();
+ return 1;
+ }
+ unsigned long long uid = strtoull(argv[1], NULL, 10);
+ if (uid == 0 && strcmp(argv[1], "0") != 0) {
+ fprintf(stderr, "ERROR: Failed to parse --force-uid <UID>!\n");
+ simple_archiver_print_usage();
+ return 1;
+ } else if (uid > 0xFFFFFFFF) {
+ fprintf(stderr,
+ "ERROR: UID Is too large (expecting unsigned 32-bit "
+ "value)!\n");
+ simple_archiver_print_usage();
+ return 1;
+ }
+ out->uid = (uint32_t)uid;
+ out->flags |= 0x400;
+ --argc;
+ ++argv;
+ } else if (strcmp(argv[0], "--force-gid") == 0) {
+ if (argc < 2) {
+ fprintf(stderr, "ERROR: --force-gid expects an integer argument!\n");
+ simple_archiver_print_usage();
+ return 1;
+ }
+ unsigned long long gid = strtoull(argv[1], NULL, 10);
+ if (gid == 0 && strcmp(argv[1], "0") != 0) {
+ fprintf(stderr, "ERROR: Failed to parse --force-gid <GID>!\n");
+ simple_archiver_print_usage();
+ return 1;
+ } else if (gid > 0xFFFFFFFF) {
+ fprintf(stderr,
+ "ERROR: GID Is too large (expecting unsigned 32-bit "
+ "value)!\n");
+ simple_archiver_print_usage();
+ return 1;
+ }
+ out->gid = (uint32_t)gid;
+ out->flags |= 0x800;
+ --argc;
+ ++argv;
+ } else if (strcmp(argv[0], "--force-file-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-file-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->file_permissions |= (value & 4) ? 1 : 0;
+ out->file_permissions |= (value & 2) ? 2 : 0;
+ out->file_permissions |= (value & 1) ? 4 : 0;
+
+ value = (uint_fast8_t)(argv[1][1] - '0');
+ out->file_permissions |= (value & 4) ? 8 : 0;
+ out->file_permissions |= (value & 2) ? 0x10 : 0;
+ out->file_permissions |= (value & 1) ? 0x20 : 0;
+
+ value = (uint_fast8_t)(argv[1][2] - '0');
+ out->file_permissions |= (value & 4) ? 0x40 : 0;
+ out->file_permissions |= (value & 2) ? 0x80 : 0;
+ out->file_permissions |= (value & 1) ? 0x100 : 0;
+
+ out->flags |= 0x1000;
+
+ --argc;
+ ++argv;
+ } else if (strcmp(argv[0], "--force-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-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->dir_permissions |= (value & 4) ? 1 : 0;
+ out->dir_permissions |= (value & 2) ? 2 : 0;
+ out->dir_permissions |= (value & 1) ? 4 : 0;
+
+ value = (uint_fast8_t)(argv[1][1] - '0');
+ out->dir_permissions |= (value & 4) ? 8 : 0;
+ out->dir_permissions |= (value & 2) ? 0x10 : 0;
+ out->dir_permissions |= (value & 1) ? 0x20 : 0;
+
+ value = (uint_fast8_t)(argv[1][2] - '0');
+ out->dir_permissions |= (value & 4) ? 0x40 : 0;
+ out->dir_permissions |= (value & 2) ? 0x80 : 0;
+ out->dir_permissions |= (value & 1) ? 0x100 : 0;
+
+ out->flags |= 0x2000;
+
+ --argc;
+ ++argv;
} else if (argv[0][0] == '-' && argv[0][1] == '-' && argv[0][2] == 0) {
is_remaining_args = 1;
} else if (argv[0][0] != '-') {