2024-06-27 02:57:29 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2024 Stephen Seo
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*
|
|
|
|
* `parser.c` is the source file for parsing args.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "parser.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2024-07-03 11:01:03 +00:00
|
|
|
#include "platforms.h"
|
2024-07-03 11:25:42 +00:00
|
|
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX || \
|
2024-07-04 02:54:15 +00:00
|
|
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
2024-07-03 11:25:42 +00:00
|
|
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN
|
2024-07-03 10:54:44 +00:00
|
|
|
#include <dirent.h>
|
2024-07-03 11:25:42 +00:00
|
|
|
#include <fcntl.h>
|
2024-07-03 10:54:44 +00:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
2024-07-04 05:48:56 +00:00
|
|
|
#include <unistd.h>
|
2024-07-03 10:54:44 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "data_structures/hash_map.h"
|
|
|
|
#include "data_structures/linked_list.h"
|
2024-07-04 05:48:56 +00:00
|
|
|
#include "helpers.h"
|
2024-07-01 06:13:06 +00:00
|
|
|
#include "parser_internal.h"
|
|
|
|
|
|
|
|
/// Gets the first non "./"-like character in the filename.
|
|
|
|
unsigned int simple_archiver_parser_internal_filename_idx(
|
|
|
|
const char *filename) {
|
|
|
|
unsigned int idx = 0;
|
|
|
|
unsigned int known_good_idx = 0;
|
|
|
|
const unsigned int length = strlen(filename);
|
|
|
|
|
|
|
|
// 0b0001 - checked that idx char is '.'
|
|
|
|
// 0b0010 - checked that idx char is '/'
|
|
|
|
unsigned int flags = 0;
|
|
|
|
|
|
|
|
for (; idx < length; ++idx) {
|
|
|
|
if ((flags & 3) == 0) {
|
|
|
|
if (filename[idx] == 0) {
|
|
|
|
return known_good_idx;
|
|
|
|
} else if (filename[idx] == '.') {
|
|
|
|
flags |= 1;
|
|
|
|
} else {
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
} else if ((flags & 3) == 1) {
|
|
|
|
if (filename[idx] == 0) {
|
|
|
|
return known_good_idx;
|
|
|
|
} else if (filename[idx] == '/') {
|
|
|
|
flags |= 2;
|
|
|
|
} else {
|
|
|
|
return idx - 1;
|
|
|
|
}
|
|
|
|
} else if ((flags & 3) == 3) {
|
|
|
|
if (filename[idx] == 0) {
|
|
|
|
return known_good_idx;
|
|
|
|
} else if (filename[idx] == '/') {
|
|
|
|
continue;
|
|
|
|
} else if (filename[idx] == '.') {
|
|
|
|
flags &= 0xFFFFFFFC;
|
|
|
|
known_good_idx = idx;
|
|
|
|
--idx;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (filename[idx] == 0) {
|
|
|
|
return known_good_idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
2024-07-04 05:48:56 +00:00
|
|
|
void simple_archiver_parser_internal_remove_end_slash(char *filename) {
|
|
|
|
int len = strlen(filename);
|
|
|
|
int idx;
|
|
|
|
for (idx = len; idx-- > 0;) {
|
|
|
|
if (filename[idx] != '/') {
|
|
|
|
++idx;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (idx < len && idx > 0) {
|
|
|
|
filename[idx] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void simple_archiver_internal_free_file_info_fn(void *data) {
|
|
|
|
SDArchiverFileInfo *file_info = data;
|
|
|
|
if (file_info) {
|
|
|
|
if (file_info->filename) {
|
|
|
|
free(file_info->filename);
|
|
|
|
}
|
|
|
|
if (file_info->link_dest) {
|
|
|
|
free(file_info->link_dest);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
|
2024-07-03 10:54:44 +00:00
|
|
|
int list_get_last_fn(void *data, void *ud) {
|
|
|
|
char **last = ud;
|
|
|
|
*last = data;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void container_no_free_fn(__attribute__((unused)) void *data) { return; }
|
|
|
|
|
|
|
|
int list_remove_same_str_fn(void *data, void *ud) {
|
|
|
|
if (strcmp((char *)data, (char *)ud) == 0) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-06-27 02:57:29 +00:00
|
|
|
void simple_archiver_print_usage(void) {
|
2024-07-16 07:16:58 +00:00
|
|
|
fprintf(stderr, "Usage flags:\n");
|
|
|
|
fprintf(stderr, "-c : create archive file\n");
|
|
|
|
fprintf(stderr, "-x : extract archive file\n");
|
2024-07-17 03:13:33 +00:00
|
|
|
fprintf(stderr, "-t : examine archive file\n");
|
2024-07-16 07:16:58 +00:00
|
|
|
fprintf(stderr, "-f <filename> : filename to work on\n");
|
2024-07-19 07:45:51 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
" Use \"-f -\" to work on stdout when creating archive or stdin "
|
|
|
|
"when reading archive\n");
|
2024-07-16 07:16:58 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"--compressor <full_compress_cmd> : requires --decompressor\n");
|
|
|
|
fprintf(stderr,
|
|
|
|
"--decompressor <full_decompress_cmd> : requires --compressor\n");
|
2024-07-18 04:16:24 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
" Specifying \"--decompressor\" when extracting overrides archive "
|
|
|
|
"file's stored decompressor\n");
|
2024-07-16 07:16:58 +00:00
|
|
|
fprintf(stderr, "--overwrite-create : allows overwriting an archive file\n");
|
2024-07-18 04:16:24 +00:00
|
|
|
fprintf(stderr, "--overwrite-extract : allows overwriting when extracting\n");
|
2024-07-24 04:32:39 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"--no-abs-symlink : do not store absolute paths for symlinks\n");
|
2024-07-16 07:16:58 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"-- : specifies remaining arguments are files to archive/extract\n");
|
|
|
|
fprintf(
|
|
|
|
stderr,
|
|
|
|
"If creating archive file, remaining args specify files to archive.\n");
|
|
|
|
fprintf(
|
|
|
|
stderr,
|
|
|
|
"If extracting archive file, remaining args specify files to extract.\n");
|
2024-06-27 02:57:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDArchiverParsed simple_archiver_create_parsed(void) {
|
|
|
|
SDArchiverParsed parsed;
|
|
|
|
|
|
|
|
parsed.flags = 0;
|
|
|
|
parsed.filename = NULL;
|
|
|
|
parsed.compressor = NULL;
|
|
|
|
parsed.decompressor = NULL;
|
|
|
|
parsed.working_files = NULL;
|
|
|
|
|
|
|
|
return parsed;
|
|
|
|
}
|
|
|
|
|
|
|
|
int simple_archiver_parse_args(int argc, const char **argv,
|
|
|
|
SDArchiverParsed *out) {
|
|
|
|
if (out->filename) {
|
|
|
|
free(out->filename);
|
|
|
|
out->filename = NULL;
|
|
|
|
}
|
|
|
|
if (out->compressor) {
|
|
|
|
free(out->compressor);
|
|
|
|
out->compressor = NULL;
|
|
|
|
}
|
|
|
|
if (out->decompressor) {
|
|
|
|
free(out->decompressor);
|
|
|
|
out->decompressor = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip program name as it is the first arg usually.
|
|
|
|
--argc;
|
|
|
|
++argv;
|
|
|
|
|
|
|
|
int is_remaining_args = 0;
|
|
|
|
|
|
|
|
while (argc > 0) {
|
|
|
|
if (!is_remaining_args) {
|
2024-07-16 07:16:58 +00:00
|
|
|
if (strcmp(argv[0], "-h") == 0 || strcmp(argv[0], "--help") == 0) {
|
|
|
|
simple_archiver_print_usage();
|
|
|
|
exit(0);
|
|
|
|
} else if (strcmp(argv[0], "-c") == 0) {
|
2024-07-17 03:13:33 +00:00
|
|
|
// unset first two bits.
|
|
|
|
out->flags &= 0xFFFFFFFC;
|
2024-06-27 02:57:29 +00:00
|
|
|
} else if (strcmp(argv[0], "-x") == 0) {
|
2024-07-17 03:13:33 +00:00
|
|
|
// unset first two bits.
|
|
|
|
out->flags &= 0xFFFFFFFC;
|
2024-06-27 02:57:29 +00:00
|
|
|
// set first bit.
|
|
|
|
out->flags |= 0x1;
|
2024-07-17 03:13:33 +00:00
|
|
|
} else if (strcmp(argv[0], "-t") == 0) {
|
|
|
|
// unset first two bits.
|
|
|
|
out->flags &= 0xFFFFFFFC;
|
|
|
|
// set second bit.
|
|
|
|
out->flags |= 0x2;
|
2024-06-27 02:57:29 +00:00
|
|
|
} else if (strcmp(argv[0], "-f") == 0 && argc > 1) {
|
2024-07-19 07:45:51 +00:00
|
|
|
if (strcmp(argv[1], "-") == 0) {
|
|
|
|
out->flags |= 0x10;
|
|
|
|
if (out->filename) {
|
|
|
|
free(out->filename);
|
|
|
|
}
|
|
|
|
out->filename = NULL;
|
|
|
|
} else {
|
|
|
|
out->flags &= 0xFFFFFFEF;
|
|
|
|
int size = strlen(argv[1]) + 1;
|
|
|
|
out->filename = malloc(size);
|
|
|
|
strncpy(out->filename, argv[1], size);
|
|
|
|
}
|
2024-06-27 02:57:29 +00:00
|
|
|
--argc;
|
|
|
|
++argv;
|
|
|
|
} else if (strcmp(argv[0], "--compressor") == 0 && argc > 1) {
|
|
|
|
int size = strlen(argv[1]) + 1;
|
|
|
|
out->compressor = malloc(size);
|
|
|
|
strncpy(out->compressor, argv[1], size);
|
|
|
|
--argc;
|
|
|
|
++argv;
|
|
|
|
} else if (strcmp(argv[0], "--decompressor") == 0 && argc > 1) {
|
|
|
|
int size = strlen(argv[1]) + 1;
|
|
|
|
out->decompressor = malloc(size);
|
|
|
|
strncpy(out->decompressor, argv[1], size);
|
|
|
|
--argc;
|
|
|
|
++argv;
|
2024-07-11 07:56:23 +00:00
|
|
|
} else if (strcmp(argv[0], "--overwrite-create") == 0) {
|
2024-07-17 03:13:33 +00:00
|
|
|
out->flags |= 0x4;
|
2024-07-18 04:16:24 +00:00
|
|
|
} else if (strcmp(argv[0], "--overwrite-extract") == 0) {
|
|
|
|
out->flags |= 0x8;
|
2024-07-24 04:32:39 +00:00
|
|
|
} else if (strcmp(argv[0], "--no-abs-symlink") == 0) {
|
|
|
|
out->flags |= 0x20;
|
2024-07-01 06:13:06 +00:00
|
|
|
} else if (argv[0][0] == '-' && argv[0][1] == '-' && argv[0][2] == 0) {
|
|
|
|
is_remaining_args = 1;
|
2024-06-27 02:57:29 +00:00
|
|
|
} else if (argv[0][0] != '-') {
|
|
|
|
is_remaining_args = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (out->working_files == NULL) {
|
|
|
|
out->working_files = malloc(sizeof(char *) * 2);
|
2024-07-01 06:13:06 +00:00
|
|
|
unsigned int arg_idx =
|
|
|
|
simple_archiver_parser_internal_filename_idx(argv[0]);
|
|
|
|
int arg_length = strlen(argv[0] + arg_idx) + 1;
|
2024-06-27 02:57:29 +00:00
|
|
|
out->working_files[0] = malloc(arg_length);
|
2024-07-01 06:13:06 +00:00
|
|
|
strncpy(out->working_files[0], argv[0] + arg_idx, arg_length);
|
2024-07-04 05:48:56 +00:00
|
|
|
simple_archiver_parser_internal_remove_end_slash(out->working_files[0]);
|
2024-06-27 02:57:29 +00:00
|
|
|
out->working_files[1] = NULL;
|
|
|
|
} else {
|
|
|
|
int working_size = 1;
|
|
|
|
char **ptr = out->working_files;
|
|
|
|
while (ptr && *ptr) {
|
|
|
|
++working_size;
|
|
|
|
++ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO verify this is necessary, using different variables.
|
|
|
|
ptr = out->working_files;
|
2024-06-27 04:30:18 +00:00
|
|
|
out->working_files = realloc(ptr, sizeof(char *) * (working_size + 1));
|
2024-06-27 02:57:29 +00:00
|
|
|
|
|
|
|
// Set new actual last element to NULL.
|
|
|
|
out->working_files[working_size] = NULL;
|
2024-07-01 06:13:06 +00:00
|
|
|
unsigned int arg_idx =
|
|
|
|
simple_archiver_parser_internal_filename_idx(argv[0]);
|
|
|
|
int size = strlen(argv[0] + arg_idx) + 1;
|
2024-06-27 02:57:29 +00:00
|
|
|
// Set last element to the arg.
|
|
|
|
out->working_files[working_size - 1] = malloc(size);
|
2024-07-01 06:13:06 +00:00
|
|
|
strncpy(out->working_files[working_size - 1], argv[0] + arg_idx, size);
|
2024-07-04 05:48:56 +00:00
|
|
|
simple_archiver_parser_internal_remove_end_slash(
|
|
|
|
out->working_files[working_size - 1]);
|
2024-06-27 02:57:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
--argc;
|
|
|
|
++argv;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void simple_archiver_free_parsed(SDArchiverParsed *parsed) {
|
|
|
|
parsed->flags = 0;
|
|
|
|
if (parsed->filename) {
|
|
|
|
free(parsed->filename);
|
|
|
|
parsed->filename = NULL;
|
|
|
|
}
|
|
|
|
if (parsed->compressor) {
|
|
|
|
free(parsed->compressor);
|
|
|
|
parsed->compressor = NULL;
|
|
|
|
}
|
|
|
|
if (parsed->decompressor) {
|
|
|
|
free(parsed->decompressor);
|
|
|
|
parsed->decompressor = NULL;
|
|
|
|
}
|
|
|
|
if (parsed->working_files) {
|
|
|
|
char **ptr = parsed->working_files;
|
|
|
|
unsigned int idx = 0;
|
|
|
|
while (ptr[idx]) {
|
|
|
|
free(ptr[idx]);
|
|
|
|
++idx;
|
|
|
|
}
|
|
|
|
free(parsed->working_files);
|
|
|
|
parsed->working_files = NULL;
|
|
|
|
}
|
|
|
|
}
|
2024-07-03 10:54:44 +00:00
|
|
|
|
|
|
|
SDArchiverLinkedList *simple_archiver_parsed_to_filenames(
|
|
|
|
const SDArchiverParsed *parsed) {
|
|
|
|
SDArchiverLinkedList *files_list = simple_archiver_list_init();
|
|
|
|
__attribute__((cleanup(simple_archiver_hash_map_free)))
|
|
|
|
SDArchiverHashMap *hash_map = simple_archiver_hash_map_init();
|
|
|
|
int hash_map_sentinel = 1;
|
|
|
|
#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \
|
2024-07-04 02:54:15 +00:00
|
|
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \
|
2024-07-03 10:54:44 +00:00
|
|
|
SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
|
|
|
|
for (char **iter = parsed->working_files; iter && *iter; ++iter) {
|
|
|
|
struct stat st;
|
2024-07-04 05:48:56 +00:00
|
|
|
memset(&st, 0, sizeof(struct stat));
|
2024-07-03 11:25:42 +00:00
|
|
|
fstatat(AT_FDCWD, *iter, &st, AT_SYMLINK_NOFOLLOW);
|
2024-07-04 05:48:56 +00:00
|
|
|
if ((st.st_mode & S_IFMT) == S_IFREG || (st.st_mode & S_IFMT) == S_IFLNK) {
|
|
|
|
// Is a regular file or a symbolic link.
|
2024-07-03 10:54:44 +00:00
|
|
|
int len = strlen(*iter) + 1;
|
|
|
|
char *filename = malloc(len);
|
|
|
|
strncpy(filename, *iter, len);
|
|
|
|
if (simple_archiver_hash_map_get(hash_map, filename, len - 1) == NULL) {
|
2024-07-04 05:48:56 +00:00
|
|
|
SDArchiverFileInfo *file_info = malloc(sizeof(SDArchiverFileInfo));
|
|
|
|
file_info->filename = filename;
|
|
|
|
if ((st.st_mode & S_IFMT) == S_IFLNK) {
|
|
|
|
file_info->link_dest = malloc(MAX_SYMBOLIC_LINK_SIZE);
|
|
|
|
ssize_t count = readlinkat(AT_FDCWD, filename, file_info->link_dest,
|
|
|
|
MAX_SYMBOLIC_LINK_SIZE - 1);
|
|
|
|
if (count >= MAX_SYMBOLIC_LINK_SIZE - 1) {
|
|
|
|
file_info->link_dest[MAX_SYMBOLIC_LINK_SIZE - 1] = 0;
|
|
|
|
} else if (count > 0) {
|
|
|
|
file_info->link_dest[count] = 0;
|
|
|
|
} else {
|
|
|
|
// Failure.
|
|
|
|
free(file_info->link_dest);
|
|
|
|
free(file_info);
|
|
|
|
free(filename);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
file_info->link_dest = NULL;
|
|
|
|
}
|
|
|
|
simple_archiver_list_add(files_list, file_info,
|
|
|
|
simple_archiver_internal_free_file_info_fn);
|
2024-07-03 10:54:44 +00:00
|
|
|
simple_archiver_hash_map_insert(&hash_map, &hash_map_sentinel, filename,
|
|
|
|
len - 1, container_no_free_fn,
|
|
|
|
container_no_free_fn);
|
|
|
|
} else {
|
|
|
|
free(filename);
|
|
|
|
}
|
|
|
|
} else if ((st.st_mode & S_IFMT) == S_IFDIR) {
|
2024-07-04 04:50:32 +00:00
|
|
|
// Is a directory.
|
2024-07-03 10:54:44 +00:00
|
|
|
__attribute__((cleanup(simple_archiver_list_free)))
|
|
|
|
SDArchiverLinkedList *dir_list = simple_archiver_list_init();
|
|
|
|
simple_archiver_list_add(dir_list, *iter, container_no_free_fn);
|
|
|
|
char *next;
|
|
|
|
while (dir_list->count != 0) {
|
|
|
|
simple_archiver_list_get(dir_list, list_get_last_fn, &next);
|
|
|
|
if (!next) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
DIR *dir = opendir(next);
|
|
|
|
struct dirent *dir_entry;
|
|
|
|
do {
|
|
|
|
dir_entry = readdir(dir);
|
|
|
|
if (dir_entry) {
|
|
|
|
if (strcmp(dir_entry->d_name, ".") == 0 ||
|
|
|
|
strcmp(dir_entry->d_name, "..") == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2024-07-24 06:05:01 +00:00
|
|
|
// fprintf(stderr, "dir entry in %s is %s\n", next,
|
|
|
|
// dir_entry->d_name);
|
2024-07-03 10:54:44 +00:00
|
|
|
int combined_size = strlen(next) + strlen(dir_entry->d_name) + 2;
|
|
|
|
char *combined_path = malloc(combined_size);
|
|
|
|
snprintf(combined_path, combined_size, "%s/%s", next,
|
|
|
|
dir_entry->d_name);
|
2024-07-04 05:48:56 +00:00
|
|
|
unsigned int valid_idx =
|
|
|
|
simple_archiver_parser_internal_filename_idx(combined_path);
|
|
|
|
if (valid_idx > 0) {
|
|
|
|
char *new_path = malloc(combined_size - valid_idx);
|
|
|
|
strncpy(new_path, combined_path + valid_idx,
|
|
|
|
combined_size - valid_idx);
|
|
|
|
free(combined_path);
|
|
|
|
combined_path = new_path;
|
|
|
|
combined_size -= valid_idx;
|
|
|
|
}
|
|
|
|
memset(&st, 0, sizeof(struct stat));
|
2024-07-03 11:25:42 +00:00
|
|
|
fstatat(AT_FDCWD, combined_path, &st, AT_SYMLINK_NOFOLLOW);
|
2024-07-04 05:48:56 +00:00
|
|
|
if ((st.st_mode & S_IFMT) == S_IFREG ||
|
|
|
|
(st.st_mode & S_IFMT) == S_IFLNK) {
|
|
|
|
// Is a file or a symbolic link.
|
2024-07-03 10:54:44 +00:00
|
|
|
if (simple_archiver_hash_map_get(hash_map, combined_path,
|
|
|
|
combined_size - 1) == NULL) {
|
2024-07-04 05:48:56 +00:00
|
|
|
SDArchiverFileInfo *file_info =
|
|
|
|
malloc(sizeof(SDArchiverFileInfo));
|
|
|
|
file_info->filename = combined_path;
|
|
|
|
if ((st.st_mode & S_IFMT) == S_IFLNK) {
|
|
|
|
file_info->link_dest = malloc(MAX_SYMBOLIC_LINK_SIZE);
|
|
|
|
ssize_t count =
|
|
|
|
readlinkat(AT_FDCWD, combined_path, file_info->link_dest,
|
|
|
|
MAX_SYMBOLIC_LINK_SIZE - 1);
|
|
|
|
if (count >= MAX_SYMBOLIC_LINK_SIZE - 1) {
|
|
|
|
file_info->link_dest[MAX_SYMBOLIC_LINK_SIZE - 1] = 0;
|
|
|
|
} else if (count > 0) {
|
|
|
|
file_info->link_dest[count] = 0;
|
|
|
|
} else {
|
|
|
|
// Failure.
|
|
|
|
free(file_info->link_dest);
|
|
|
|
free(file_info);
|
|
|
|
free(combined_path);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
file_info->link_dest = NULL;
|
|
|
|
}
|
|
|
|
simple_archiver_list_add(
|
|
|
|
files_list, file_info,
|
|
|
|
simple_archiver_internal_free_file_info_fn);
|
2024-07-03 10:54:44 +00:00
|
|
|
simple_archiver_hash_map_insert(
|
|
|
|
&hash_map, &hash_map_sentinel, combined_path,
|
|
|
|
combined_size - 1, container_no_free_fn,
|
|
|
|
container_no_free_fn);
|
|
|
|
} else {
|
|
|
|
free(combined_path);
|
|
|
|
}
|
|
|
|
} else if ((st.st_mode & S_IFMT) == S_IFDIR) {
|
|
|
|
// Is a directory.
|
|
|
|
simple_archiver_list_add_front(dir_list, combined_path, NULL);
|
|
|
|
} else {
|
2024-07-03 11:25:42 +00:00
|
|
|
// Unhandled type. TODO handle this.
|
2024-07-03 10:54:44 +00:00
|
|
|
free(combined_path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (dir_entry != NULL);
|
|
|
|
closedir(dir);
|
|
|
|
if (simple_archiver_list_remove(dir_list, list_remove_same_str_fn,
|
|
|
|
next) == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2024-07-03 11:25:42 +00:00
|
|
|
// Unhandled type. TODO handle this.
|
2024-07-03 10:54:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Remove leading "./" entries from files_list.
|
|
|
|
for (SDArchiverLLNode *iter = files_list->head->next;
|
|
|
|
iter != files_list->tail; iter = iter->next) {
|
2024-07-04 05:48:56 +00:00
|
|
|
SDArchiverFileInfo *file_info = iter->data;
|
|
|
|
unsigned int idx =
|
|
|
|
simple_archiver_parser_internal_filename_idx(file_info->filename);
|
2024-07-03 10:54:44 +00:00
|
|
|
if (idx > 0) {
|
2024-07-04 05:48:56 +00:00
|
|
|
int len = strlen(file_info->filename) + 1 - idx;
|
2024-07-03 10:54:44 +00:00
|
|
|
char *substr = malloc(len);
|
2024-07-04 05:48:56 +00:00
|
|
|
strncpy(substr, file_info->filename + idx, len);
|
|
|
|
free(file_info->filename);
|
|
|
|
file_info->filename = substr;
|
2024-07-03 10:54:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return files_list;
|
|
|
|
}
|