Files
ps4-ezremote-server/source/fs.cpp
T
2026-05-30 04:05:31 -07:00

484 lines
12 KiB
C++

#include "fs.h"
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <dirent.h>
#include <sys/time.h>
// #include <filesystem>
#include <stdio.h>
#include <unistd.h>
#include <vector>
#include <sys/stat.h>
#include "util.h"
#if defined(EZREMOTE_ENABLE_UI)
#include "windows.h"
#endif
namespace FS
{
int hasEndSlash(const char *path)
{
return path[strlen(path) - 1] == '/';
}
void MkDirs(const std::string &ppath, bool prev)
{
std::string path = ppath;
if (!prev)
{
path.push_back('/');
}
auto ptr = path.begin();
while (true)
{
ptr = std::find(ptr, path.end(), '/');
if (ptr == path.end())
break;
char last = *ptr;
*ptr = 0;
int err = mkdir(path.c_str(), 0777);
*ptr = last;
++ptr;
}
}
void Rm(const std::string &file)
{
remove(file.c_str());
}
void RmDir(const std::string &path)
{
rmdir(path.c_str());
}
int64_t GetSize(const std::string &path)
{
struct stat file_stat = {0};
int err = stat(path.c_str(), &file_stat);
if (err < 0)
{
return -1;
}
return file_stat.st_size;
}
bool FileExists(const std::string &path)
{
struct stat file_stat = {0};
return (stat(path.c_str(), std::addressof(file_stat)) == 0 && S_ISREG(file_stat.st_mode));
}
bool FolderExists(const std::string &path)
{
struct stat dir_stat = {0};
return (stat(path.c_str(), &dir_stat) == 0);
}
int IsFolder(const std::string &path)
{
struct stat dir_stat = {0};
if (stat(path.c_str(), &dir_stat) != 0)
return -1;
if (S_ISDIR(dir_stat.st_mode))
return 1;
return 0;
}
void Rename(const std::string &from, const std::string &to)
{
int res = rename(from.c_str(), to.c_str());
}
FILE *Create(const std::string &path)
{
FILE *fd = fopen(path.c_str(), "w");
return fd;
}
FILE *OpenRW(const std::string &path)
{
FILE *fd = fopen(path.c_str(), "w+");
return fd;
}
FILE *OpenRead(const std::string &path)
{
FILE *fd = fopen(path.c_str(), "rb");
return fd;
}
FILE *Append(const std::string &path)
{
FILE *fd = fopen(path.c_str(), "ab");
return fd;
}
int64_t Seek(FILE *f, uint64_t offset)
{
auto const pos = fseek(f, offset, SEEK_SET);
return pos;
}
int Read(FILE *f, void *buffer, uint32_t size)
{
const auto read = fread(buffer, 1, size, f);
return read;
}
int Write(FILE *f, const void *buffer, uint32_t size)
{
int write = fwrite(buffer, 1, size, f);
return write;
}
void Close(FILE *fd)
{
int err = fclose(fd);
}
std::vector<char> Load(const std::string &path)
{
FILE *fd = fopen(path.c_str(), "rb");
if (fd == nullptr)
return std::vector<char>(0);
const auto size = GetSize(path);
std::vector<char> data(size);
const auto read = fread(data.data(), 1, data.size(), fd);
fclose(fd);
if (read < 0)
return std::vector<char>(0);
data.resize(read+1);
data[data.size()-1]=0;
return data;
}
bool LoadText(std::vector<std::string> *lines, const std::string &path)
{
FILE *fd = fopen(path.c_str(), "rb");
if (fd == nullptr)
return false;
lines->clear();
char buffer[1024];
short bytes_read;
std::vector<char> line = std::vector<char>(0);
do
{
bytes_read = fread(buffer, sizeof(char), 1024, fd);
if (bytes_read < 0)
{
fclose(fd);
return false;
}
for (short i = 0; i < bytes_read; i++)
{
if (buffer[i] != '\r' && buffer[i] != '\n')
{
line.push_back(buffer[i]);
}
else
{
lines->push_back(std::string(line.data(), line.size()));
line = std::vector<char>(0);
if (buffer[i] == '\r' && buffer[i+1] == '\n')
i++;
}
}
} while (bytes_read == 1024);
if (line.size()>0)
lines->push_back(std::string(line.data(), line.size()));
fclose(fd);
if (lines->size() == 0)
lines->push_back("");
return true;
}
bool SaveText(std::vector<std::string> *lines, const std::string &path)
{
FILE *fd = OpenRW(path);
if (fd == nullptr)
return false;
char nl[1] = {'\n'};
for (int i=0; i < lines->size(); i++)
{
Write(fd, lines->at(i).c_str(), lines->at(i).length());
Write(fd, nl, 1);
}
fclose(fd);
return true;
}
bool Save(const std::string &path, const void *data, uint32_t size)
{
FILE *fd = fopen(path.c_str(), "w+");
if (fd == nullptr)
return false;
const char *data8 = static_cast<const char *>(data);
while (size != 0)
{
int written = fwrite(data8, 1, size, fd);
fclose(fd);
if (written <= 0)
return false;
data8 += written;
size -= written;
}
return true;
}
std::vector<std::string> ListFiles(const std::string &path)
{
DIR *fd = opendir(path.c_str());
if (fd == NULL)
return std::vector<std::string>(0);
std::vector<std::string> out;
while (true)
{
struct dirent *dirent;
dirent = readdir(fd);
if (dirent == NULL)
{
closedir(fd);
return out;
}
if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0)
{
continue;
}
if (dirent->d_type & DT_DIR)
{
/*
std::vector<std::string> files = FS::ListFiles(path + "/" + dirent->d_name);
for (std::vector<std::string>::iterator it = files.begin(); it != files.end();)
{
out.push_back(std::string(dirent->d_name) + "/" + *it);
++it;
}
*/
}
else
{
out.push_back(dirent->d_name);
}
}
closedir(fd);
return out;
}
int RmRecursive(const std::string &path)
{
#if defined(EZREMOTE_ENABLE_UI)
if (stop_activity)
return 1;
#else
bool stop_activity = false;
#endif
DIR *dfd = opendir(path.c_str());
if (dfd != NULL)
{
struct dirent *dir = NULL;
do
{
dir = readdir(dfd);
if (dir == NULL || strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0)
{
continue;
}
char new_path[512];
snprintf(new_path, 512, "%s%s%s", path.c_str(), hasEndSlash(path.c_str()) ? "" : "/", dir->d_name);
if (dir->d_type & DT_DIR)
{
int ret = RmRecursive(new_path);
if (ret <= 0)
{
#if defined(EZREMOTE_ENABLE_UI)
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_DIR_MSG], new_path);
#endif
closedir(dfd);
return ret;
}
}
else
{
#if defined(EZREMOTE_ENABLE_UI)
snprintf(activity_message, 1024, "%s %s", lang_strings[STR_DELETING], new_path);
#endif
int ret = remove(new_path);
if (ret < 0)
{
#if defined(EZREMOTE_ENABLE_UI)
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_FILE_MSG], new_path);
#endif
closedir(dfd);
return ret;
}
}
} while (dir != NULL && !stop_activity);
closedir(dfd);
if (stop_activity)
return 0;
int ret = rmdir(path.c_str());
if (ret < 0)
{
#if defined(EZREMOTE_ENABLE_UI)
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_DIR_MSG], path.c_str());
#endif
return ret;
}
#if defined(EZREMOTE_ENABLE_UI)
snprintf(activity_message, 1024, "%s %s", lang_strings[STR_DELETED], path.c_str());
#endif
}
else
{
int ret = remove(path.c_str());
if (ret < 0)
{
#if defined(EZREMOTE_ENABLE_UI)
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_FILE_MSG], path.c_str());
#endif
return ret;
}
#if defined(EZREMOTE_ENABLE_UI)
snprintf(activity_message, 1024, "%s %s", lang_strings[STR_DELETED], path.c_str());
#endif
}
return 1;
}
std::string GetPath(const std::string &ppath1, const std::string &ppath2)
{
std::string path1 = ppath1;
std::string path2 = ppath2;
path2 = Util::Rtrim(Util::Trim(path2, " "), "/");
return path1 + "/" + path2;
}
int Head(const std::string &path, void *buffer, uint16_t len)
{
FILE *file = OpenRead(path);
if (file == nullptr)
return 0;
int ret = Read(file, buffer, len);
if (ret != len)
{
Close(file);
return 0;
}
Close(file);
return 1;
}
bool Copy(const std::string &from, const std::string &to)
{
#if !defined(EZREMOTE_ENABLE_UI)
uint64_t bytes_to_download;
uint64_t bytes_transfered;
#endif
MkDirs(to, true);
if (from.compare(to) == 0)
return true;
FILE *src = fopen(from.c_str(), "rb");
if (!src)
{
return false;
}
struct stat file_stat = {0};
if (stat(from.c_str(), &file_stat) != 0)
{
return false;
}
bytes_to_download = file_stat.st_size;
FILE *dest = fopen(to.c_str(), "wb");
if (!dest)
{
fclose(src);
return false;
}
size_t bytes_read = 0;
bytes_transfered = 0;
#if defined(EZREMOTE_ENABLE_UI)
prev_tick = Util::GetTick();
#endif
const size_t buf_size = 0x10000;
unsigned char *buf = new unsigned char[buf_size];
do
{
bytes_read = fread(buf, sizeof(unsigned char), buf_size, src);
if (bytes_read < 0)
{
delete[] buf;
fclose(src);
fclose(dest);
return false;
}
size_t bytes_written = fwrite(buf, sizeof(unsigned char), bytes_read, dest);
if (bytes_written != bytes_read)
{
delete[] buf;
fclose(src);
fclose(dest);
return false;
}
bytes_transfered += bytes_read;
} while (bytes_transfered < bytes_to_download);
delete[] buf;
fclose(src);
fclose(dest);
return true;
}
bool Move(const std::string &from, const std::string &to)
{
if (from.compare(to) == 0)
return true;
errno = 0;
int ret = rename(from.c_str(), to.c_str());
if (ret != 0 && (errno == EXDEV || errno == EEXIST))
{
bool res = Copy(from, to);
if (res)
Rm(from);
else
return res;
}
return true;
}
}