diff --git a/.gitignore b/.gitignore index dcc08de7..3ccc4cee 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,7 @@ # Ignore any N64 ROM **/*.n64 **/*.v64 -**/*.z64 \ No newline at end of file +**/*.z64 + +# Ignore macOS filesystem cruft +.DS_Store diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index 21c4f76a..37c61dc7 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -36,6 +36,52 @@ static const char *hidden_paths[] = { NULL, }; +struct substr { const char *str; size_t len; }; +#define substr(str) ((struct substr){ str, sizeof(str) - 1 }) + +static const struct substr hidden_basenames[] = { + substr("desktop.ini"), // Windows Explorer settings + substr("Thumbs.db"), // Windows Explorer thumbnails + substr(".DS_Store"), // macOS Finder settings +}; +#define HIDDEN_BASENAMES_COUNT (sizeof(hidden_basenames) / sizeof(hidden_basenames[0])) + +static const struct substr hidden_prefixes[] = { + substr("._"), // macOS "AppleDouble" metadata files +}; +#define HIDDEN_PREFIXES_COUNT (sizeof(hidden_prefixes) / sizeof(hidden_prefixes[0])) + + +static bool path_is_hidden (path_t *path) { + char *stripped_path = strip_fs_prefix(path_get(path)); + + // Check for hidden files based on full path + for (int i = 0; hidden_paths[i] != NULL; i++) { + if (strcmp(stripped_path, hidden_paths[i]) == 0) { + return true; + } + } + + char *basename = file_basename(stripped_path); + int basename_len = strlen(basename); + + // Check for hidden files based on filename + for (int i = 0; i < HIDDEN_BASENAMES_COUNT; i++) { + if (basename_len == hidden_basenames[i].len && + strncmp(basename, hidden_basenames[i].str, hidden_basenames[i].len) == 0) { + return true; + } + } + // Check for hidden files based on filename prefix + for (int i = 0; i < HIDDEN_PREFIXES_COUNT; i++) { + if (basename_len > hidden_prefixes[i].len && + strncmp(basename, hidden_prefixes[i].str, hidden_prefixes[i].len) == 0) { + return true; + } + } + + return false; +} static int compare_entry (const void *pa, const void *pb) { entry_t *a = (entry_t *) (pa); @@ -108,14 +154,7 @@ static bool load_directory (menu_t *menu) { if (!menu->settings.show_protected_entries) { path_push(path, info.d_name); - - for (int i = 0; hidden_paths[i] != NULL; i++) { - if (strcmp(strip_fs_prefix(path_get(path)), hidden_paths[i]) == 0) { - hide = true; - break; - } - } - + hide = path_is_hidden(path); path_pop(path); } diff --git a/src/utils/fs.c b/src/utils/fs.c index b02b2e2c..607e2025 100644 --- a/src/utils/fs.c +++ b/src/utils/fs.c @@ -17,6 +17,10 @@ char *strip_fs_prefix (char *path) { return path; } +char *file_basename (char *path) { + char *base = strrchr(path, '/'); + return base ? base + 1 : path; +} bool file_exists (char *path) { struct stat st; diff --git a/src/utils/fs.h b/src/utils/fs.h index 88f81a7a..ce342a33 100644 --- a/src/utils/fs.h +++ b/src/utils/fs.h @@ -11,6 +11,7 @@ char *strip_fs_prefix (char *path); +char *file_basename (char *path); bool file_exists (char *path); int64_t file_get_size (char *path);