2018-03-03 07:46:44 +00:00
|
|
|
/*
|
|
|
|
4coder_file.h - File enumeration and reading procedures for each platform.
|
2018-05-09 07:10:07 +00:00
|
|
|
*/
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
// TOP
|
|
|
|
|
|
|
|
#if !defined(FCODER_FILE_ENUMERATOR_CPP)
|
|
|
|
#define FCODER_FILE_ENUMERATOR_CPP
|
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
#include "4coder_base_types.h"
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
#include <stdio.h>
|
2018-03-10 00:34:35 +00:00
|
|
|
#include <stdlib.h>
|
2018-10-06 15:49:13 +00:00
|
|
|
#include <string.h>
|
2018-03-03 07:46:44 +00:00
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
#if OS_WINDOWS
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
//// WINDOWS BEGIN ////
|
2019-10-01 21:49:05 +00:00
|
|
|
#undef function
|
2018-03-03 07:46:44 +00:00
|
|
|
#define UNICODE
|
|
|
|
#include <Windows.h>
|
|
|
|
typedef TCHAR Filename_Character;
|
|
|
|
#define SLASH '\\'
|
2019-10-01 21:49:05 +00:00
|
|
|
#define function static
|
2018-03-03 07:46:44 +00:00
|
|
|
//// WINDOWS END ////
|
|
|
|
|
|
|
|
#else
|
2019-12-14 01:00:55 +00:00
|
|
|
#include <dirent.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#define SLASH '/'
|
|
|
|
typedef char Filename_Character;
|
2018-03-03 07:46:44 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
struct Cross_Platform_File_Info{
|
|
|
|
Filename_Character *name;
|
|
|
|
int32_t len;
|
2019-06-01 23:58:28 +00:00
|
|
|
b32 is_folder;
|
2018-03-03 07:46:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Cross_Platform_File_List{
|
|
|
|
Cross_Platform_File_Info *info;
|
|
|
|
int32_t count;
|
2018-03-09 23:19:32 +00:00
|
|
|
int32_t path_length;
|
|
|
|
Filename_Character path_name[4096];
|
2018-03-03 07:46:44 +00:00
|
|
|
};
|
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
typedef b32 File_Filter(Filename_Character *name, int32_t len);
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
static Cross_Platform_File_List
|
2019-06-01 23:58:28 +00:00
|
|
|
get_file_list(Arena *arena, Filename_Character *dir, File_Filter *filter);
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
static Filename_Character*
|
2019-06-01 23:58:28 +00:00
|
|
|
encode(Arena *arena, char *str){
|
2018-03-03 07:46:44 +00:00
|
|
|
int32_t size = 0;
|
|
|
|
for (;str[size]!=0;++size);
|
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
Filename_Character *out = push_array(arena, Filename_Character, size + 1);
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
if (out == 0){
|
|
|
|
fprintf(stdout, "fatal error: ran out of memory encoding string to filename\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t j = 0;
|
|
|
|
for (int32_t i = 0; i <= size; ++i){
|
|
|
|
if (str[i] != '"'){
|
|
|
|
out[j++] = str[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(out);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char*
|
2019-06-01 23:58:28 +00:00
|
|
|
unencode(Arena *arena, Filename_Character *str, int32_t len){
|
|
|
|
Temp_Memory temp = begin_temp(arena);
|
|
|
|
char *out = push_array(arena, char, len + 1);
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
if (out == 0){
|
|
|
|
fprintf(stdout, "fatal error: ran out of memory unencoding string to filename\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int32_t i = 0; i <= len; ++i){
|
|
|
|
if (str[i] <= 127){
|
|
|
|
out[i] = (char)str[i];
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
out = 0;
|
2019-06-01 23:58:28 +00:00
|
|
|
end_temp(temp);
|
2018-03-03 07:46:44 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(out);
|
|
|
|
}
|
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
static b32
|
2018-03-03 07:46:44 +00:00
|
|
|
filter_all(Filename_Character *name, int32_t len){
|
|
|
|
return(true);
|
|
|
|
}
|
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
static b32
|
2018-03-03 07:46:44 +00:00
|
|
|
filter_is_code_file(Filename_Character *name, int32_t len){
|
2019-06-01 23:58:28 +00:00
|
|
|
b32 is_code = false;
|
2018-03-03 07:46:44 +00:00
|
|
|
if (len >= 5){
|
|
|
|
Filename_Character *ext = &name[len - 4];
|
|
|
|
if (ext[0] == '.' && ext[1] == 'c' && ext[2] == 'p' && ext[3] == 'p'){
|
|
|
|
is_code = true;
|
|
|
|
}
|
|
|
|
else if (ext[0] == '.' && ext[1] == 'h' && ext[2] == 'p' && ext[3] == 'p'){
|
|
|
|
is_code = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (len >= 4){
|
|
|
|
Filename_Character *ext = &name[len - 3];
|
|
|
|
if (ext[0] == '.' && ext[1] == 'c' && ext[2] == 'c'){
|
|
|
|
is_code = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (len >= 3){
|
|
|
|
Filename_Character *ext = &name[len - 2];
|
|
|
|
if (ext[0] == '.' && ext[1] == 'h'){
|
|
|
|
is_code = true;
|
|
|
|
}
|
|
|
|
else if (ext[0] == '.' && ext[1] == 'c'){
|
|
|
|
is_code = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(is_code);
|
|
|
|
}
|
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
#if OS_WINDOWS
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
//// WINDOWS BEGIN ////
|
|
|
|
static Cross_Platform_File_List
|
2019-06-01 23:58:28 +00:00
|
|
|
get_file_list(Arena *arena, Filename_Character *pattern, File_Filter *filter){
|
|
|
|
if (arena == 0){
|
2018-03-03 07:46:44 +00:00
|
|
|
fprintf(stdout, "fatal error: NULL part passed to %s\n", __FUNCTION__);
|
|
|
|
exit(1);
|
|
|
|
}
|
2018-03-09 23:19:32 +00:00
|
|
|
if (pattern == 0){
|
|
|
|
fprintf(stdout, "fatal error: NULL pattern passed to %s\n", __FUNCTION__);
|
2018-03-03 07:46:44 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2018-03-09 23:19:32 +00:00
|
|
|
int32_t pattern_length = 0;
|
|
|
|
for (; pattern[pattern_length] != 0; ++pattern_length);
|
|
|
|
int32_t last_slash = pattern_length;
|
2018-06-15 20:10:49 +00:00
|
|
|
for (; last_slash >= 0 && pattern[last_slash] != SLASH; --last_slash);
|
2018-03-09 23:19:32 +00:00
|
|
|
if (last_slash < 0){
|
|
|
|
fprintf(stdout, "fatal error: invalid file pattern\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
pattern[last_slash] = 0;
|
|
|
|
|
2018-03-03 07:46:44 +00:00
|
|
|
HANDLE dir_handle =
|
2018-03-09 23:19:32 +00:00
|
|
|
CreateFile(pattern,
|
2018-03-03 07:46:44 +00:00
|
|
|
FILE_LIST_DIRECTORY,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
|
|
0,
|
|
|
|
OPEN_EXISTING,
|
|
|
|
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
|
|
|
|
0);
|
2018-03-09 23:19:32 +00:00
|
|
|
pattern[last_slash] = SLASH;
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
if (dir_handle == INVALID_HANDLE_VALUE){
|
|
|
|
fprintf(stdout, "fatal error: could not open directory handle\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2018-03-09 23:19:32 +00:00
|
|
|
Filename_Character path_name[4096];
|
|
|
|
DWORD path_length = GetFinalPathNameByHandle(dir_handle, path_name, sizeof(path_name), 0);
|
|
|
|
if (path_length > sizeof(path_name)){
|
2018-03-03 07:46:44 +00:00
|
|
|
fprintf(stdout, "fatal error: path name too long for local buffer\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
CloseHandle(dir_handle);
|
|
|
|
|
2018-03-09 23:19:32 +00:00
|
|
|
path_length -= 4;
|
|
|
|
memmove(path_name, path_name + 4, path_length*sizeof(*path_name));
|
|
|
|
path_name[path_length] = 0;
|
|
|
|
|
|
|
|
// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen):
|
|
|
|
// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen):
|
|
|
|
// Get this working with the new search by pattern structure!!!
|
2018-03-03 07:46:44 +00:00
|
|
|
|
2018-11-20 08:18:54 +00:00
|
|
|
WIN32_FIND_DATA find_data = {};
|
2018-03-09 23:19:32 +00:00
|
|
|
HANDLE search = FindFirstFile(pattern, &find_data);
|
2018-03-03 07:46:44 +00:00
|
|
|
if (search == INVALID_HANDLE_VALUE){
|
|
|
|
fprintf(stdout, "fatal error: could not begin a file search\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t character_count = 0;
|
|
|
|
int32_t file_count = 0;
|
|
|
|
BOOL more_files = true;
|
|
|
|
do{
|
|
|
|
Filename_Character *name = &find_data.cFileName[0];
|
|
|
|
|
|
|
|
int32_t size = 0;
|
|
|
|
for(;name[size];++size);
|
|
|
|
|
|
|
|
uint32_t attribs = find_data.dwFileAttributes;
|
2019-06-01 23:58:28 +00:00
|
|
|
b32 is_folder = ((attribs & FILE_ATTRIBUTE_DIRECTORY) != 0);
|
|
|
|
b32 is_hidden = ((attribs & FILE_ATTRIBUTE_HIDDEN) != 0);
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
if (!is_hidden){
|
|
|
|
if (name[0] != '.' && (is_folder || filter(name, size))){
|
|
|
|
++file_count;
|
|
|
|
character_count += size + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
more_files = FindNextFile(search, &find_data);
|
|
|
|
}while(more_files);
|
|
|
|
FindClose(search);
|
|
|
|
|
2018-11-20 08:18:54 +00:00
|
|
|
Cross_Platform_File_List list = {};
|
2019-06-01 23:58:28 +00:00
|
|
|
Temp_Memory part_reset = begin_temp(arena);
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
int32_t rounded_char_size = (character_count*sizeof(Filename_Character) + 7)&(~7);
|
|
|
|
int32_t memsize = rounded_char_size + file_count*sizeof(Cross_Platform_File_Info);
|
2019-06-01 23:58:28 +00:00
|
|
|
void *mem = push_array(arena, u8, memsize);
|
2018-03-03 07:46:44 +00:00
|
|
|
if (mem == 0){
|
|
|
|
fprintf(stdout, "fatal error: not enough memory on the partition for a file list.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
Filename_Character *char_ptr = (Filename_Character*)mem;
|
|
|
|
Cross_Platform_File_Info *info_ptr = (Cross_Platform_File_Info*)((uint8_t*)mem + rounded_char_size);
|
|
|
|
|
|
|
|
Filename_Character *char_ptr_end = (Filename_Character*)info_ptr;
|
|
|
|
Cross_Platform_File_Info *info_ptr_end = info_ptr + file_count;
|
|
|
|
|
|
|
|
Cross_Platform_File_Info *info_ptr_base = info_ptr;
|
|
|
|
|
2018-03-09 23:19:32 +00:00
|
|
|
search = FindFirstFile(pattern, &find_data);
|
2018-03-03 07:46:44 +00:00
|
|
|
if (search == INVALID_HANDLE_VALUE){
|
|
|
|
fprintf(stdout, "fatal error: could not restart a file search\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t adjusted_file_count = 0;
|
|
|
|
more_files = true;
|
|
|
|
do{
|
|
|
|
Filename_Character *name = &find_data.cFileName[0];
|
|
|
|
|
|
|
|
int32_t size = 0;
|
|
|
|
for(;name[size]!=0;++size);
|
|
|
|
|
|
|
|
uint32_t attribs = find_data.dwFileAttributes;
|
2019-06-01 23:58:28 +00:00
|
|
|
b32 is_folder = ((attribs & FILE_ATTRIBUTE_DIRECTORY) != 0);
|
|
|
|
b32 is_hidden = ((attribs & FILE_ATTRIBUTE_HIDDEN) != 0);
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
if (!is_hidden){
|
|
|
|
if (name[0] != '.' && (is_folder || filter(name, size))){
|
|
|
|
if (info_ptr + 1 > info_ptr_end || char_ptr + size + 1 > char_ptr_end){
|
|
|
|
memset(&list, 0, sizeof(list));
|
2019-06-01 23:58:28 +00:00
|
|
|
end_temp(part_reset);
|
2018-03-03 07:46:44 +00:00
|
|
|
FindClose(search);
|
|
|
|
return(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
info_ptr->name = char_ptr;
|
|
|
|
info_ptr->len = size;
|
|
|
|
info_ptr->is_folder = is_folder;
|
|
|
|
|
|
|
|
memmove(char_ptr, name, size*sizeof(*name));
|
|
|
|
char_ptr[size] = 0;
|
|
|
|
|
|
|
|
char_ptr += size + 1;
|
|
|
|
++info_ptr;
|
|
|
|
++adjusted_file_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
more_files = FindNextFile(search, &find_data);
|
|
|
|
}while(more_files);
|
|
|
|
FindClose(search);
|
|
|
|
|
|
|
|
list.info = info_ptr_base;
|
|
|
|
list.count = adjusted_file_count;
|
2018-03-09 23:19:32 +00:00
|
|
|
list.path_length = path_length;
|
|
|
|
memcpy(list.path_name, path_name, list.path_length*sizeof(*path_name));
|
|
|
|
list.path_name[list.path_length] = 0;
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
return(list);
|
|
|
|
}
|
|
|
|
//// WINDOWS END ////
|
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
#elif OS_LINUX || OS_MAC
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
//// UNIX BEGIN ////
|
2019-06-01 23:58:28 +00:00
|
|
|
static b32
|
2018-03-10 00:34:35 +00:00
|
|
|
match_pattern(Filename_Character *name, Filename_Character *pattern){
|
2019-06-01 23:58:28 +00:00
|
|
|
b32 match = false;
|
2018-03-10 00:34:35 +00:00
|
|
|
if (sizeof(*name) == 1){
|
2019-12-14 01:00:55 +00:00
|
|
|
String_Const_u8 name_str = SCu8(name);
|
|
|
|
String_Const_u8 pattern_str = SCu8(pattern);
|
|
|
|
List_String_Const_u8 list = {};
|
|
|
|
Node_String_Const_u8 node = { NULL, name_str };
|
|
|
|
string_list_push(&list, &node);
|
|
|
|
match = string_wildcard_match(list, pattern_str, StringMatch_Exact);
|
2018-03-10 00:34:35 +00:00
|
|
|
}
|
|
|
|
else{
|
|
|
|
fprintf(stdout, "fatal error: wide characters not supported!\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
return(match);
|
|
|
|
}
|
|
|
|
|
2018-03-03 07:46:44 +00:00
|
|
|
static Cross_Platform_File_List
|
2019-12-14 01:00:55 +00:00
|
|
|
get_file_list(Arena *arena, Filename_Character *pattern, File_Filter *filter){
|
|
|
|
if (arena == 0){
|
|
|
|
fprintf(stdout, "fatal error: NULL arena passed to %s\n", __FUNCTION__);
|
2018-03-03 07:46:44 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
2018-03-10 00:34:35 +00:00
|
|
|
if (pattern == 0){
|
2018-03-03 07:46:44 +00:00
|
|
|
fprintf(stdout, "fatal error: NULL dir passed to %s\n", __FUNCTION__);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2018-03-10 00:34:35 +00:00
|
|
|
int32_t pattern_length = 0;
|
|
|
|
for (; pattern[pattern_length] != 0; ++pattern_length);
|
|
|
|
int32_t last_slash = pattern_length;
|
|
|
|
for (; last_slash > 0 && pattern[last_slash] != SLASH; --last_slash);
|
|
|
|
if (last_slash < 0){
|
|
|
|
fprintf(stdout, "fatal error: invalid file pattern\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
pattern[last_slash] = 0;
|
|
|
|
|
|
|
|
DIR *dir_handle = opendir(pattern);
|
|
|
|
|
2018-03-03 07:46:44 +00:00
|
|
|
if (dir_handle == 0){
|
|
|
|
fprintf(stdout, "fatal error: could not open directory handle\n");
|
2018-03-10 00:34:35 +00:00
|
|
|
if (sizeof(*pattern) == 2){
|
|
|
|
fprintf(stdout, "%ls\n", (wchar_t*)pattern);
|
2018-03-03 07:46:44 +00:00
|
|
|
}
|
|
|
|
else{
|
2018-03-10 00:34:35 +00:00
|
|
|
fprintf(stdout, "%s\n", (char*)pattern);
|
2018-03-03 07:46:44 +00:00
|
|
|
}
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2018-03-10 00:34:35 +00:00
|
|
|
Filename_Character path_name[4096];
|
2019-12-14 01:00:55 +00:00
|
|
|
int32_t path_length = cstring_length(pattern);
|
2018-03-10 00:34:35 +00:00
|
|
|
if (path_length + 1 > sizeof(path_name)){
|
2018-03-03 07:46:44 +00:00
|
|
|
fprintf(stdout, "fatal error: path name too long for local buffer\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
2018-03-10 00:34:35 +00:00
|
|
|
memcpy(path_name, pattern, path_length + 1);
|
|
|
|
|
|
|
|
char *file_pattern = pattern + last_slash + 1;
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
int32_t character_count = 0;
|
|
|
|
int32_t file_count = 0;
|
|
|
|
for (struct dirent *entry = readdir(dir_handle);
|
|
|
|
entry != 0;
|
|
|
|
entry = readdir(dir_handle)){
|
|
|
|
Filename_Character *name = entry->d_name;
|
2018-03-10 00:34:35 +00:00
|
|
|
if (!match_pattern(name, file_pattern)){
|
|
|
|
continue;
|
|
|
|
}
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
int32_t size = 0;
|
|
|
|
for(;name[size];++size);
|
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
b32 is_folder = false;
|
2018-03-03 07:46:44 +00:00
|
|
|
if (entry->d_type == DT_LNK){
|
|
|
|
struct stat st;
|
|
|
|
if (stat(entry->d_name, &st) != -1){
|
|
|
|
is_folder = S_ISDIR(st.st_mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
is_folder = (entry->d_type == DT_DIR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name[0] != '.' && (is_folder || filter(name, size))){
|
|
|
|
++file_count;
|
|
|
|
character_count += size + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-20 08:18:54 +00:00
|
|
|
Cross_Platform_File_List list = {};
|
2019-12-14 01:00:55 +00:00
|
|
|
Temp_Memory part_reset = begin_temp(arena);
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
int32_t rounded_char_size = (character_count*sizeof(Filename_Character) + 7)&(~7);
|
|
|
|
int32_t memsize = rounded_char_size + file_count*sizeof(Cross_Platform_File_Info);
|
2019-12-14 01:00:55 +00:00
|
|
|
void *mem = push_array(arena, uint8_t, memsize);
|
2018-03-03 07:46:44 +00:00
|
|
|
if (mem == 0){
|
|
|
|
fprintf(stdout, "fatal error: not enough memory on the partition for a file list.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
Filename_Character *char_ptr = (Filename_Character*)mem;
|
|
|
|
Cross_Platform_File_Info *info_ptr = (Cross_Platform_File_Info*)((uint8_t*)mem + rounded_char_size);
|
|
|
|
|
|
|
|
Filename_Character *char_ptr_end = (Filename_Character*)info_ptr;
|
|
|
|
Cross_Platform_File_Info *info_ptr_end = info_ptr + file_count;
|
|
|
|
|
|
|
|
Cross_Platform_File_Info *info_ptr_base = info_ptr;
|
|
|
|
|
|
|
|
rewinddir(dir_handle);
|
|
|
|
|
|
|
|
int32_t adjusted_file_count = 0;
|
|
|
|
for (struct dirent *entry = readdir(dir_handle);
|
|
|
|
entry != 0;
|
|
|
|
entry = readdir(dir_handle)){
|
|
|
|
Filename_Character *name = entry->d_name;
|
2018-03-10 00:34:35 +00:00
|
|
|
if (!match_pattern(name, file_pattern)){
|
|
|
|
continue;
|
|
|
|
}
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
int32_t size = 0;
|
|
|
|
for(;name[size];++size);
|
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
b32 is_folder = false;
|
2018-03-03 07:46:44 +00:00
|
|
|
if (entry->d_type == DT_LNK){
|
|
|
|
struct stat st;
|
|
|
|
if (stat(entry->d_name, &st) != -1){
|
|
|
|
is_folder = S_ISDIR(st.st_mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
is_folder = (entry->d_type == DT_DIR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name[0] != '.' && (is_folder || filter(name, size))){
|
|
|
|
if (info_ptr + 1 > info_ptr_end || char_ptr + size + 1 > char_ptr_end){
|
|
|
|
memset(&list, 0, sizeof(list));
|
2019-12-14 01:00:55 +00:00
|
|
|
end_temp(part_reset);
|
2018-03-03 07:46:44 +00:00
|
|
|
closedir(dir_handle);
|
|
|
|
return(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
info_ptr->name = char_ptr;
|
|
|
|
info_ptr->len = size;
|
|
|
|
info_ptr->is_folder = is_folder;
|
|
|
|
|
|
|
|
memmove(char_ptr, name, size*sizeof(*name));
|
|
|
|
char_ptr[size] = 0;
|
|
|
|
|
|
|
|
char_ptr += size + 1;
|
|
|
|
++info_ptr;
|
|
|
|
++adjusted_file_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
closedir(dir_handle);
|
|
|
|
|
|
|
|
list.info = info_ptr_base;
|
|
|
|
list.count = adjusted_file_count;
|
2018-03-10 00:34:35 +00:00
|
|
|
list.path_length = path_length;
|
|
|
|
memcpy(list.path_name, path_name, list.path_length*sizeof(*path_name));
|
|
|
|
list.path_name[list.path_length] = 0;
|
2018-03-03 07:46:44 +00:00
|
|
|
|
|
|
|
return(list);
|
|
|
|
}
|
|
|
|
//// UNIX END ////
|
|
|
|
|
|
|
|
#else
|
|
|
|
# error metdata generator not supported on this platform
|
|
|
|
#endif
|
|
|
|
|
2019-09-04 18:26:51 +00:00
|
|
|
static String_Const_u8
|
2019-06-01 23:58:28 +00:00
|
|
|
file_dump(Arena *arena, char *name){
|
2019-09-04 18:26:51 +00:00
|
|
|
String_Const_u8 text = {};
|
2018-03-03 07:46:44 +00:00
|
|
|
FILE *file = fopen(name, "rb");
|
|
|
|
if (file != 0){
|
|
|
|
fseek(file, 0, SEEK_END);
|
|
|
|
text.size = ftell(file);
|
|
|
|
fseek(file, 0, SEEK_SET);
|
2019-09-04 18:26:51 +00:00
|
|
|
text.str = push_array(arena, u8, text.size + 1);
|
2018-03-03 07:46:44 +00:00
|
|
|
if (text.str == 0){
|
|
|
|
fprintf(stdout, "fatal error: not enough memory in partition for file dumping");
|
|
|
|
exit(1);
|
|
|
|
}
|
2019-12-18 03:38:08 +00:00
|
|
|
fread(text.str, 1, (size_t)text.size, file);
|
2019-06-01 23:58:28 +00:00
|
|
|
text.str[text.size] = 0;
|
2018-03-03 07:46:44 +00:00
|
|
|
fclose(file);
|
|
|
|
}
|
|
|
|
return(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// BOTTOM
|
|
|
|
|