Login
1 branch 0 tags
Ben (Desktop/Arch) Fixed now playing screen showing wrong data for 1 frame 73cc7c1 1 month ago 68 Commits
moon / sdl_src / storage_sdl.c
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "storage.h"

#define SDCARD_PATH "./sdcard"

static bool mounted = false;

bool storage_init(void) {
	struct stat st;

	// Check if sdcard directory exists
	if (stat(SDCARD_PATH, &st) == -1) {
		// Try to create it
		if (mkdir(SDCARD_PATH, 0755) == -1) {
			fprintf(stderr, "storage: failed to create %s: %s\n", SDCARD_PATH,
			        strerror(errno));
			return false;
		}
		printf("storage: created %s directory\n", SDCARD_PATH);
	} else if (!S_ISDIR(st.st_mode)) {
		fprintf(stderr, "storage: %s exists but is not a directory\n",
		        SDCARD_PATH);
		return false;
	}

	mounted = true;
	printf("storage: mounted %s\n", SDCARD_PATH);
	return true;
}

bool storage_mkdir(const char* path) {
	if (!mounted || !path) {
		return false;
	}

	const char* rel = (path[0] == '/') ? path + 1 : path;
	char full_path[STORAGE_MAX_PATH];
	snprintf(full_path, sizeof(full_path), "%s/%s", SDCARD_PATH, rel);

	struct stat st;
	if (stat(full_path, &st) == 0) {
		return S_ISDIR(st.st_mode);
	}
	return mkdir(full_path, 0755) == 0;
}

bool storage_remove(const char* path) {
	if (!mounted || !path) {
		return false;
	}

	const char* rel = (path[0] == '/') ? path + 1 : path;
	char full_path[STORAGE_MAX_PATH];
	snprintf(full_path, sizeof(full_path), "%s/%s", SDCARD_PATH, rel);

	if (remove(full_path) != 0 && errno != ENOENT) {
		fprintf(stderr, "storage: failed to remove %s: %s\n", full_path,
		        strerror(errno));
		return false;
	}
	return true;
}

bool storage_is_mounted(void) {
	return mounted;
}

void storage_unmount(void) {}

bool storage_remount(void) {
	return true;
}

int storage_list_dir(const char* path, storage_entry_t* entries, int max) {
	if (!mounted || !entries || max <= 0) {
		return -1;
	}

	char full_path[STORAGE_MAX_PATH];
	if (path == NULL || path[0] == '\0' || strcmp(path, "/") == 0) {
		snprintf(full_path, sizeof(full_path), "%s", SDCARD_PATH);
	} else {
		// Strip leading slash to avoid double-slash in path
		const char* rel = (path[0] == '/') ? path + 1 : path;
		snprintf(full_path, sizeof(full_path), "%s/%s", SDCARD_PATH, rel);
	}

	DIR* dir = opendir(full_path);
	if (!dir) {
		fprintf(stderr, "storage: failed to open directory %s: %s\n", full_path,
		        strerror(errno));
		return -1;
	}

	int count = 0;
	struct dirent* ent;
	while ((ent = readdir(dir)) != NULL && count < max) {
		// Skip . and ..
		if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
			continue;
		}

		strncpy(entries[count].name, ent->d_name, STORAGE_MAX_NAME - 1);
		entries[count].name[STORAGE_MAX_NAME - 1] = '\0';

		// Get file info
		char file_path[STORAGE_MAX_PATH * 2];
		snprintf(file_path, sizeof(file_path), "%s/%s", full_path, ent->d_name);

		struct stat st;
		if (stat(file_path, &st) == 0) {
			entries[count].type =
			    S_ISDIR(st.st_mode) ? STORAGE_TYPE_DIR : STORAGE_TYPE_FILE;
			entries[count].size = (size_t)st.st_size;
		} else {
			entries[count].type = STORAGE_TYPE_FILE;
			entries[count].size = 0;
		}

		count++;
	}

	closedir(dir);
	return count;
}

storage_file_t storage_open(const char* path, const char* mode) {
	if (!mounted || !path || !mode) {
		return NULL;
	}

	const char* rel = (path[0] == '/') ? path + 1 : path;
	char full_path[STORAGE_MAX_PATH];
	snprintf(full_path, sizeof(full_path), "%s/%s", SDCARD_PATH, rel);

	FILE* f = fopen(full_path, mode);
	return (storage_file_t)f;
}

size_t storage_read(storage_file_t file, void* buf, size_t size) {
	if (!file || !buf) {
		return 0;
	}
	return fread(buf, 1, size, (FILE*)file);
}

size_t storage_write(storage_file_t file, const void* buf, size_t size) {
	if (!file || !buf) {
		return 0;
	}
	return fwrite(buf, 1, size, (FILE*)file);
}

int storage_close(storage_file_t file) {
	if (!file) {
		return -1;
	}
	return fclose((FILE*)file);
}