mirror of
https://github.com/joel16/VITAlbum.git
synced 2024-11-27 05:20:29 +00:00
183 lines
5.1 KiB
C++
183 lines
5.1 KiB
C++
#include <psp2/io/fcntl.h>
|
|
#include <psp2/io/stat.h>
|
|
#include <algorithm>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <filesystem>
|
|
|
|
#include "fs.h"
|
|
#include "log.h"
|
|
#include "utils.h"
|
|
|
|
namespace FS {
|
|
std::string CWD;
|
|
|
|
int GetFileSize(const std::string &path, SceOff *size) {
|
|
int ret = 0;
|
|
SceIoStat stat;
|
|
|
|
if (R_FAILED(ret = sceIoGetstat(path.c_str(), &stat)))
|
|
return ret;
|
|
|
|
*size = stat.st_size;
|
|
return 0;
|
|
}
|
|
|
|
std::string GetFileExt(const std::string &filename) {
|
|
std::string ext = std::filesystem::path(filename).extension();
|
|
std::transform(ext.begin(), ext.end(), ext.begin(), ::toupper);
|
|
return ext;
|
|
}
|
|
|
|
static SceOff CountFiles(const std::string &path) {
|
|
int ret = 0;
|
|
SceOff entry_count = 0;
|
|
SceUID dir = sceIoDopen(path.c_str());
|
|
|
|
do {
|
|
SceIoDirent entries;
|
|
std::memset(&entries, 0, sizeof(SceIoDirent));
|
|
|
|
ret = sceIoDread(dir, &entries);
|
|
if (ret > 0)
|
|
entry_count++;
|
|
} while (ret > 0);
|
|
|
|
sceIoDclose(dir);
|
|
return entry_count;
|
|
}
|
|
|
|
static int sort(const void *p1, const void *p2) {
|
|
SceIoDirent *entryA = (SceIoDirent *)p1;
|
|
SceIoDirent *entryB = (SceIoDirent *)p2;
|
|
|
|
if ((SCE_S_ISDIR(entryA->d_stat.st_mode)) && !(SCE_S_ISDIR(entryB->d_stat.st_mode)))
|
|
return -1;
|
|
else if (!(SCE_S_ISDIR(entryA->d_stat.st_mode)) && (SCE_S_ISDIR(entryB->d_stat.st_mode)))
|
|
return 1;
|
|
|
|
return strcasecmp(entryA->d_name, entryB->d_name);
|
|
}
|
|
|
|
SceOff GetDirList(const std::string &path, SceIoDirent **entriesp) {
|
|
int ret = 0, i = ((path == "ux0:")? 0 : 1);
|
|
SceOff entry_count = 0;
|
|
SceUID dir = 0;
|
|
|
|
entry_count = CountFiles(path) + ((path == "ux0:")? 0 : 1);
|
|
Log::Debug("entry_count(%s) = %llu\n", path.c_str(), entry_count);
|
|
|
|
if (R_FAILED(dir = sceIoDopen(path.c_str()))) {
|
|
Log::Debug("sceIoDopen failed 0x%08x\n", dir);
|
|
return dir;
|
|
}
|
|
|
|
Log::Debug("Before malloc\n");
|
|
SceIoDirent *entries = new SceIoDirent[entry_count * sizeof(entries)];
|
|
Log::Debug("After malloc\n");
|
|
|
|
// Add parent directory entry if not on root path
|
|
if (path != "ux0:") {
|
|
std::strcpy(entries[0].d_name, "..");
|
|
entries[0].d_stat.st_mode = SCE_S_IFDIR;
|
|
}
|
|
|
|
do {
|
|
ret = sceIoDread(dir, &entries[i]);
|
|
i++;
|
|
} while (ret > 0);
|
|
|
|
std::qsort(entries, entry_count, sizeof(SceIoDirent), sort);
|
|
|
|
if (R_FAILED(ret = sceIoDclose(dir))) {
|
|
Log::Debug("sceIoDopen failed 0x%08x\n", ret);
|
|
delete entries;
|
|
return ret;
|
|
}
|
|
|
|
*entriesp = entries;
|
|
return entry_count;
|
|
}
|
|
|
|
//TODO: Clean up change directory impl.
|
|
static SceOff ChangeDir(const std::string &path, SceIoDirent **entries) {
|
|
SceIoDirent *new_entries;
|
|
|
|
SceOff num_entries = GetDirList(path, &new_entries);
|
|
if (num_entries < 0)
|
|
return -1;
|
|
|
|
// Free entries and change the current working directory.
|
|
delete *entries;
|
|
CWD = path;
|
|
*entries = new_entries;
|
|
return num_entries;
|
|
}
|
|
|
|
static int ChangeDirUp(char path[256]) {
|
|
if (CWD.length() <= 1 && CWD.c_str()[0] == '/')
|
|
return -1;
|
|
|
|
// Remove upmost directory
|
|
bool copy = false;
|
|
int len = 0;
|
|
for (ssize_t i = CWD.length(); i >= 0; i--) {
|
|
if (CWD.c_str()[i] == '/')
|
|
copy = true;
|
|
if (copy) {
|
|
path[i] = CWD.c_str()[i];
|
|
len++;
|
|
}
|
|
}
|
|
|
|
// remove trailing slash
|
|
if (len > 1 && path[len - 1] == '/')
|
|
len--;
|
|
|
|
path[len] = '\0';
|
|
return 0;
|
|
}
|
|
|
|
SceOff ChangeDirNext(const std::string &path, SceIoDirent **entries) {
|
|
std::string new_path = CWD;
|
|
new_path.append("/");
|
|
new_path.append(path);
|
|
return ChangeDir(new_path, entries);
|
|
}
|
|
|
|
SceOff ChangeDirPrev(SceIoDirent **entries) {
|
|
char new_path[256];
|
|
if (ChangeDirUp(new_path) < 0)
|
|
return -1;
|
|
|
|
return ChangeDir(std::string(new_path), entries);
|
|
}
|
|
|
|
const std::string BuildPath(SceIoDirent *entry) {
|
|
std::string path = CWD;
|
|
path.append("/");
|
|
path.append(entry->d_name);
|
|
return path;
|
|
}
|
|
|
|
int ReadFile(const std::string &path, unsigned char **buffer, SceOff *size) {
|
|
SceUID file = 0;
|
|
int ret = 0;
|
|
|
|
if (R_FAILED(ret = file = sceIoOpen(path.c_str(), SCE_O_RDONLY, 0)))
|
|
return ret;
|
|
|
|
*size = sceIoLseek(file, 0, SEEK_END);
|
|
*buffer = (unsigned char *)std::malloc(*size);
|
|
|
|
if (R_FAILED(ret = sceIoPread(file, *buffer, *size, SCE_SEEK_SET)))
|
|
return ret;
|
|
|
|
if (R_FAILED(ret = sceIoClose(file)))
|
|
return ret;
|
|
|
|
return 0;
|
|
}
|
|
}
|