On Nintendo Switch if you copy a files/folder over from an old MAC the switch has issues if the archive bit is set wrongly. This bit is stored not on the files but in the file system metadata. So why is it when you send this to the switch the metadata is also being sent? As far as I can remember this makes the file on a switch look like a folder.
In fat32 and exfat we can also set an archive bit by using a meta data file e.g., icon.jpg - icon.jpg.metadata. The meta data contains this - A=1 if the bit is set to on and A=0 if the bit is set to off.
No I know we can just use hekate to fix this, but what if we want to change a files meta data manually, how can we do this?
I made a small program for testing this:
Now I tested it with files in the switch/test folder, it creates these metadata files properly - but the switch doesn't see these files as folders if the bit is set to on so I must be missing something. Does anyone have any Idea what I am missing?
In fat32 and exfat we can also set an archive bit by using a meta data file e.g., icon.jpg - icon.jpg.metadata. The meta data contains this - A=1 if the bit is set to on and A=0 if the bit is set to off.
No I know we can just use hekate to fix this, but what if we want to change a files meta data manually, how can we do this?
I made a small program for testing this:
Code:
#include <switch.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#define METADATA_EXT ".metadata" // Metadata file extension
#define TARGET_DIR "/switch/test" // Directory to scan
// Function to get the metadata filename
void get_metadata_filename(const char* filepath, char* metadata_path, size_t size) {
snprintf(metadata_path, size, "%s%s", filepath, METADATA_EXT);
}
// Function to check if a file is a metadata file
bool is_metadata_file(const char* filename) {
size_t len = strlen(filename);
size_t ext_len = strlen(METADATA_EXT);
if (len > ext_len && strcmp(filename + (len - ext_len), METADATA_EXT) == 0) {
return true; // This is a .metadata file, so ignore it
}
return false;
}
// Function to set the archive bit in metadata
void set_archive_bit(const char* filepath, bool enable) {
if (is_metadata_file(filepath)) return; // Skip processing metadata files
char metadata_path[PATH_MAX];
get_metadata_filename(filepath, metadata_path, sizeof(metadata_path));
FILE* meta_file = fopen(metadata_path, "w");
if (!meta_file) {
printf("[ERROR] Failed to open metadata file: %s\n", metadata_path);
return;
}
fprintf(meta_file, "A=%d\n", enable ? 1 : 0);
fclose(meta_file);
printf("[INFO] Archive bit %s for: %s\n", enable ? "enabled" : "disabled", filepath);
}
// Function to get the archive bit status from metadata
bool is_archive_bit_set(const char* filepath) {
if (is_metadata_file(filepath)) return false; // Ignore metadata files
char metadata_path[PATH_MAX];
get_metadata_filename(filepath, metadata_path, sizeof(metadata_path));
FILE* meta_file = fopen(metadata_path, "r");
if (!meta_file) {
return false; // Assume archive bit is not set if metadata is missing
}
int archive_flag = 0;
fscanf(meta_file, "A=%d\n", &archive_flag);
fclose(meta_file);
return archive_flag == 1;
}
// Function to recursively process directories and apply the archive bit
void process_directory(const char* directory, bool enable) {
DIR* dir = opendir(directory);
if (!dir) {
printf("[ERROR] Failed to open directory: %s\n", directory);
return;
}
struct dirent* entry;
char path[PATH_MAX];
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 || is_metadata_file(entry->d_name)) {
continue; // Skip "." and ".." and metadata files
}
snprintf(path, sizeof(path), "%s/%s", directory, entry->d_name);
struct stat st;
if (stat(path, &st) == 0) {
if (S_ISDIR(st.st_mode)) {
// Recursively process subdirectories
process_directory(path, enable);
}
else {
// Set archive bit on file
set_archive_bit(path, enable);
}
}
else {
printf("[ERROR] Could not stat: %s\n", path);
}
}
closedir(dir);
}
// Function to display files and their archive status
void display_directory_status(const char* directory) {
DIR* dir = opendir(directory);
if (!dir) {
printf("[ERROR] Failed to open directory: %s\n", directory);
return;
}
struct dirent* entry;
char path[PATH_MAX];
printf("[INFO] Listing files in: %s\n", directory);
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 || is_metadata_file(entry->d_name)) {
continue; // Skip "." and ".." and metadata files
}
snprintf(path, sizeof(path), "%s/%s", directory, entry->d_name);
if (is_archive_bit_set(path)) {
printf("[ARCHIVE ON] %s\n", path);
}
else {
printf("[ARCHIVE OFF] %s\n", path);
}
}
closedir(dir);
}
// Main entry point
int main(int argc, char* argv[]) {
consoleInit(NULL);
printf("Nintendo Switch Archive Bit Manager (Fixed Version)\n");
printf("Press A to set archive bit, B to clear it, X to list files, + to exit.\n");
padConfigureInput(1, HidNpadStyleSet_NpadStandard);
PadState pad;
padInitializeDefault(&pad);
while (appletMainLoop()) {
padUpdate(&pad);
u64 kDown = padGetButtonsDown(&pad);
if (kDown & HidNpadButton_A) {
printf("[INFO] Setting archive bit recursively in: %s\n", TARGET_DIR);
process_directory(TARGET_DIR, true);
}
if (kDown & HidNpadButton_B) {
printf("[INFO] Clearing archive bit recursively in: %s\n", TARGET_DIR);
process_directory(TARGET_DIR, false);
}
if (kDown & HidNpadButton_X) {
display_directory_status(TARGET_DIR);
}
if (kDown & HidNpadButton_Plus) break; // Exit program
consoleUpdate(NULL);
}
consoleExit(NULL);
return 0;
Now I tested it with files in the switch/test folder, it creates these metadata files properly - but the switch doesn't see these files as folders if the bit is set to on so I must be missing something. Does anyone have any Idea what I am missing?







