Files
Project_CTR/makerom/romfs_fs.c
T
2015-11-15 03:53:01 +08:00

272 lines
5.3 KiB
C

#include "lib.h"
#include "romfs_fs.h"
#include "utf.h"
/* This is the FS interface for ROMFS generation */
/* Tested working on Windows/Linux/OSX */
int PopulateDir(romfs_dir *dir);
int InitDir(romfs_dir *dir);
int ManageDir(romfs_dir *dir);
u32 fs_strlen(const fs_char *str)
{
#ifdef _WIN32
return strlen_char16(str);
#else
return strlen(str);
#endif
}
u32 romfs_strlen(const romfs_char *str)
{
return strlen_char16(str);
}
int fs_strcmp(const fs_char *str1, const fs_char *str2)
{
#ifdef _WIN32
return wcscmp(str1, str2);
#else
return strcmp(str1, str2);
#endif
}
FILE* fs_fopen(fs_char *path)
{
#ifdef _WIN32
return _wfopen(path, L"rb");
#else
return fopen(path, "rb");
#endif
}
u64 fs_fsize(fs_char *path)
{
#ifdef _WIN32
return wGetFileSize64(path);
#else
return GetFileSize64(path);
#endif
}
fs_char* fs_AppendToPath(const fs_char *src, const fs_char *add)
{
u32 src_len, add_len;
fs_char *new_path;
src_len = fs_strlen(src);
add_len = fs_strlen(add);
new_path = calloc(src_len + add_len + 0x10, sizeof(fs_char));
#ifdef _WIN32
_snwprintf(new_path, src_len + add_len + 0x10, L"%s%c%s", src, FS_PATH_SEPARATOR, add);
#else
snprintf(new_path, src_len + add_len + 0x10, "%s%c%s", src, FS_PATH_SEPARATOR, add);
#endif
return new_path;
}
fs_char* fs_CopyStr(const fs_char *src)
{
#ifdef _WIN32
return strcopy_16to16(src);
#else
return strcopy_8to8(src);
#endif
}
romfs_char* romfs_CopyConvertStr(const fs_char *src)
{
#ifdef _WIN32
return strcopy_16to16(src);
#else
return strcopy_utf8to16(src);
#endif
}
romfs_char* romfs_CopyStr(const romfs_char *src)
{
return strcopy_16to16(src);
}
void fs_fputs(const fs_char *str, FILE *out)
{
#ifdef _WIN32
fwprintf(out,L"%s", str);
#else
fprintf(out,"%s", str);
#endif
}
void romfs_fputs(const romfs_char *str, FILE *out)
{
#ifdef _WIN32
fwprintf(out,L"%s", str);
#else
const char *name = (const char*)str;
for (u32 i = 0; i < romfs_strlen(str)*2; i += 2)
fputc(name[i],out);
#endif
}
int InitDir(romfs_dir *dir)
{
dir->m_child = 10;
dir->u_child = 0;
dir->child = calloc(dir->m_child,sizeof(romfs_dir));
dir->m_file = 10;
dir->u_file = 0;
dir->file = calloc(dir->m_file,sizeof(romfs_file));
if (dir->child == NULL || dir->file == NULL)
return MEM_ERROR;
return 0;
}
int ManageDir(romfs_dir *dir)
{
if (dir->u_child >= dir->m_child) {
dir->m_child = 2 * dir->u_child;
dir->child = realloc(dir->child, dir->m_child*sizeof(romfs_dir));
}
if (dir->u_file >= dir->m_file) {
dir->m_file = 2 * dir->u_file;
dir->file = realloc(dir->file, dir->m_file*sizeof(romfs_file));
}
if (dir->child == NULL || dir->file == NULL)
return MEM_ERROR;
return 0;
}
int OpenRootDir(const char *path, romfs_dir *dir)
{
// Create native FS path
#ifdef _WIN32
dir->path = strcopy_8to16(path);
#else
dir->path = strcopy_8to8(path);
#endif
// Copy romfs name (empty string)
dir->name = romfs_CopyStr(ROMFS_EMPTY_PATH);
dir->namesize = 0;
return PopulateDir(dir);
}
int PopulateDir(romfs_dir *dir)
{
fs_DIR *dp, *tmp_dp;
struct fs_dirent *entry;
if (InitDir(dir))
return MEM_ERROR;
// Open Directory
if((dp = fs_opendir(dir->path)) == NULL)
{
printf("[ROMFS] Failed to open directory: \"");
fs_fputs(dir->path, stdout);
printf("\"\n");
return -1;
}
// Process Entries
while ((entry = fs_readdir(dp)) != NULL)
{
// Skip if "." or ".."
if (fs_strcmp(entry->d_name, FS_CURRENT_DIR_PATH) == 0 || fs_strcmp(entry->d_name, FS_PARENT_DIR_PATH) == 0)
continue;
// Ensures that there is always memory for child directory and file structs
if (ManageDir(dir))
return MEM_ERROR;
// Get native FS path
fs_char *path = fs_AppendToPath(dir->path, entry->d_name);
// Opening directory with fs path to test if directory
if ((tmp_dp = fs_opendir(path)) != NULL) {
fs_closedir(tmp_dp);
dir->child[dir->u_child].path = path;
dir->child[dir->u_child].name = romfs_CopyConvertStr(entry->d_name);
dir->child[dir->u_child].namesize = fs_strlen(entry->d_name)*sizeof(romfs_char);
dir->u_child++;
// Populate directory
PopulateDir(&dir->child[dir->u_child-1]);
}
// Otherwise this is a file
else {
dir->file[dir->u_file].path = path;
dir->file[dir->u_file].name = romfs_CopyConvertStr(entry->d_name);
dir->file[dir->u_file].namesize = fs_strlen(entry->d_name)*sizeof(romfs_char);
dir->file[dir->u_file].size = fs_fsize(path);
dir->u_file++;
}
}
fs_closedir(dp);
return 0;
}
void PrintDir(romfs_dir *dir, u32 depth)
{
for(u32 i = 0; i < depth; i++)
printf(" ");
if (depth > 0)
romfs_fputs(dir->name, stdout);
else
printf("romfs:");
putchar('\n');
if(dir->u_file)
{
for(u32 i = 0; i < dir->u_file; i++)
{
for(u32 j = 0; j < depth+1; j++)
printf(" ");
romfs_fputs(dir->file[i].name, stdout);
printf(" (0x%"PRIx64")\n", dir->file[i].size);
}
}
if(dir->u_child)
{
for(u32 i = 0; i < dir->u_child; i++)
PrintDir(&dir->child[i],depth+1);
}
}
void FreeDir(romfs_dir *dir)
{
//printf("DIR!! free file names\n");
for(u32 i = 0; i < dir->u_file; i++)
{
free(dir->file[i].path);
free(dir->file[i].name);
}
//printf("free file struct\n");
free(dir->file);
//printf("free dir names and\n");
for(u32 i = 0; i < dir->u_child; i++)
{
free(dir->child[i].path);
free(dir->child[i].name);
FreeDir(&dir->child[i]);
}
//printf("free dir struct\n");
free(dir->child);
}