From c311874da007dc60d9aa8c0dd563a1ab99883720 Mon Sep 17 00:00:00 2001 From: Christopher Bonhage <me@christopherbonhage.com> Date: Sun, 9 Feb 2025 12:08:46 -0500 Subject: [PATCH] Hide Windows/macOS cruft in file browser (#217) <!--- Provide a general summary of your changes in the Title above --> ## Description Hides: * `desktop.ini` - Windows Explorer directory settings * `Thumbs.db` - Windows Explorer image thumbnails * `.DS_Store` - macOS Finder directory settings * `._`-prefixed files - macOS "AppleDouble" metadata ## Motivation and Context [N64brew sc64-forum post: File list shows 4096 B "Dummy Files"?](https://discord.com/channels/205520502922543113/1337028964606283806) ## How Has This Been Tested? On SC64 with an SD card containing all of the offending files in the root and in subdirectories. ## Screenshots Tough to prove a negative here with a screenshot; here's a video: https://github.com/user-attachments/assets/f1843b29-dee0-442f-bf9a-897a69c39169 ## Types of changes <!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: --> - [X] Improvement (non-breaking change that adds a new feature) - [X] Bug fix (fixes an issue) - [ ] Breaking change (breaking change) - [ ] Documentation Improvement - [ ] Config and build (change in the configuration and build system, has no impact on code or features) ## Checklist: <!--- Go over all the following points, and put an `x` in all the boxes that apply. --> <!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> - [X] My code follows the code style of this project. - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. <!--- It would be nice if you could sign off your contribution by replacing the name with your GitHub user name and GitHub email contact. --> Signed-off-by: meeq <me@christopherbonhage.com> Co-authored-by: Robin Jones <networkfusion@users.noreply.github.com> --- .gitignore | 5 +++- src/menu/views/browser.c | 55 ++++++++++++++++++++++++++++++++++------ src/utils/fs.c | 4 +++ src/utils/fs.h | 1 + 4 files changed, 56 insertions(+), 9 deletions(-) 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);