mirror of
https://github.com/joel16/VITAlbum.git
synced 2024-11-27 05:20:29 +00:00
236 lines
6.8 KiB
C++
236 lines
6.8 KiB
C++
#include <psp2/io/fcntl.h>
|
|
#include <psp2/io/stat.h>
|
|
#include <psp2/kernel/clib.h>
|
|
#include <algorithm>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <filesystem>
|
|
|
|
#include "config.h"
|
|
#include "fs.h"
|
|
#include "log.h"
|
|
#include "utils.h"
|
|
|
|
namespace FS {
|
|
bool FileExists(const std::string &path) {
|
|
SceUID file = 0;
|
|
|
|
if (R_SUCCEEDED(file = sceIoOpen(path.c_str(), SCE_O_RDONLY, 0777))) {
|
|
sceIoClose(file);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool DirExists(const std::string &path) {
|
|
SceUID dir = 0;
|
|
|
|
if (R_SUCCEEDED(dir = sceIoDopen(path.c_str()))) {
|
|
sceIoDclose(dir);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int GetFileSize(const std::string &path, SceOff &size) {
|
|
int ret = 0;
|
|
SceIoStat stat;
|
|
|
|
if (R_FAILED(ret = sceIoGetstat(path.c_str(), &stat))) {
|
|
Log::Error("sceIoGetstat(%s) failed: 0x%lx\n", path.c_str(), ret);
|
|
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;
|
|
}
|
|
|
|
bool IsImageType(const std::string &filename) {
|
|
std::string ext = FS::GetFileExt(filename);
|
|
|
|
if ((!ext.compare(".BMP")) || (!ext.compare(".GIF")) || (!ext.compare(".ICO")) || (!ext.compare(".JPG")) || (!ext.compare(".JPEG"))
|
|
|| (!ext.compare(".PGM")) || (!ext.compare(".PPM")) || (!ext.compare(".PNG")) || (!ext.compare(".PSD")) || (!ext.compare(".SVG"))
|
|
|| (!ext.compare(".TGA")) || (!ext.compare(".TIFF")) || (!ext.compare(".WEBP")))
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
int GetDirList(const std::string &path, std::vector<SceIoDirent> &entries) {
|
|
int ret = 0;
|
|
SceUID dir = 0;
|
|
entries.clear();
|
|
|
|
// Create ".." entry
|
|
SceIoDirent entry;
|
|
std::strncpy(entry.d_name, "..", 3);
|
|
entry.d_stat.st_mode = SCE_S_IFDIR;
|
|
entry.d_stat.st_size = 0;
|
|
entries.push_back(entry);
|
|
|
|
if (R_FAILED(ret = dir = sceIoDopen(path.c_str()))) {
|
|
Log::Error("sceIoDopen(%s) failed: %08x\n", path.c_str(), ret);
|
|
return ret;
|
|
}
|
|
|
|
while (true) {
|
|
SceIoDirent entry;
|
|
sceClibMemset(&entry, 0, sizeof(entry));
|
|
|
|
if (R_FAILED(ret = sceIoDread(dir, &entry))) {
|
|
Log::Error("sceIoDread(%s) failed: %08x\n", path.c_str(), ret);
|
|
sceIoDclose(dir);
|
|
return ret;
|
|
}
|
|
|
|
if (ret) {
|
|
if ((!FS::IsImageType(entry.d_name)) && (!SCE_S_ISDIR(entry.d_stat.st_mode)))
|
|
continue;
|
|
}
|
|
else
|
|
break;
|
|
|
|
entries.push_back(entry);
|
|
}
|
|
|
|
sceIoDclose(dir);
|
|
return 0;
|
|
}
|
|
|
|
//TODO: Clean up change directory impl.
|
|
static int ChangeDir(const std::string &path, std::vector<SceIoDirent> &entries) {
|
|
int ret = 0;
|
|
std::vector<SceIoDirent> new_entries;
|
|
|
|
if (R_FAILED(ret = FS::GetDirList(path, new_entries)))
|
|
return ret;
|
|
|
|
// Free entries and change the current working directory.
|
|
entries.clear();
|
|
cfg.cwd = path;
|
|
Config::Save(cfg);
|
|
entries = new_entries;
|
|
return 0;
|
|
}
|
|
|
|
static int GetPrevPath(char path[256]) {
|
|
if (cfg.cwd.c_str() == "ux0:")
|
|
return -1;
|
|
|
|
// Remove upmost directory
|
|
bool copy = false;
|
|
int len = 0;
|
|
for (ssize_t i = cfg.cwd.length(); i >= 0; i--) {
|
|
if (cfg.cwd.c_str()[i] == '/')
|
|
copy = true;
|
|
if (copy) {
|
|
path[i] = cfg.cwd.c_str()[i];
|
|
len++;
|
|
}
|
|
}
|
|
|
|
// remove trailing slash
|
|
if (len > 1 && path[len - 1] == '/')
|
|
len--;
|
|
|
|
path[len] = '\0';
|
|
return 0;
|
|
}
|
|
|
|
int ChangeDirNext(const std::string &path, std::vector<SceIoDirent> &entries) {
|
|
std::string new_path = cfg.cwd;
|
|
new_path.append("/");
|
|
new_path.append(path);
|
|
return FS::ChangeDir(new_path, entries);
|
|
}
|
|
|
|
int ChangeDirPrev(std::vector<SceIoDirent> &entries) {
|
|
char new_path[256];
|
|
if (FS::GetPrevPath(new_path) < 0)
|
|
return -1;
|
|
|
|
return FS::ChangeDir(std::string(new_path), entries);
|
|
}
|
|
|
|
const std::string BuildPath(SceIoDirent &entry) {
|
|
std::string path = cfg.cwd;
|
|
path.append("/");
|
|
path.append(entry.d_name);
|
|
return path;
|
|
}
|
|
|
|
int CreateFile(const std::string &path) {
|
|
int ret = 0;
|
|
SceUID file = 0;
|
|
|
|
if (R_FAILED(ret = file = sceIoOpen(path.c_str(), SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777))) {
|
|
Log::Error("sceIoOpen(%s) failed: 0x%lx\n", path.c_str(), ret);
|
|
return ret;
|
|
}
|
|
|
|
if (R_FAILED(ret = sceIoClose(file))) {
|
|
Log::Error("sceIoClose(%s) failed: 0x%lx\n", path.c_str(), ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ReadFile(const std::string &path, unsigned char **buffer, SceOff &size) {
|
|
int ret = 0;
|
|
SceUID file = 0;
|
|
|
|
if (R_FAILED(ret = file = sceIoOpen(path.c_str(), SCE_O_RDONLY, 0))) {
|
|
Log::Error("sceIoOpen(%s) failed: 0x%lx\n", path.c_str(), ret);
|
|
return ret;
|
|
}
|
|
|
|
size = sceIoLseek(file, 0, SEEK_END);
|
|
*buffer = new unsigned char[size];
|
|
|
|
if (R_FAILED(ret = sceIoPread(file, *buffer, size, SCE_SEEK_SET))) {
|
|
Log::Error("sceIoPread(%s) failed: 0x%lx\n", path.c_str(), ret);
|
|
return ret;
|
|
}
|
|
|
|
if (R_FAILED(ret = sceIoClose(file))) {
|
|
Log::Error("sceIoClose(%s) failed: 0x%lx\n", path.c_str(), ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int WriteFile(const std::string &path, const void *data, SceSize size) {
|
|
int ret = 0, bytes_written = 0;
|
|
SceUID file = 0;
|
|
|
|
if (R_FAILED(ret = file = sceIoOpen(path.c_str(), SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777))) {
|
|
Log::Error("sceIoOpen(%s) failed: 0x%lx\n", path.c_str(), ret);
|
|
return ret;
|
|
}
|
|
|
|
if (R_FAILED(ret = bytes_written = sceIoWrite(file, data, size))) {
|
|
Log::Error("sceIoWrite(%s) failed: 0x%lx\n", path.c_str(), ret);
|
|
sceIoClose(file);
|
|
return ret;
|
|
}
|
|
|
|
if (R_FAILED(ret = sceIoClose(file))) {
|
|
Log::Error("sceIoClose(%s) failed: 0x%lx\n", path.c_str(), ret);
|
|
return ret;
|
|
}
|
|
|
|
return bytes_written;
|
|
}
|
|
}
|