lovr/src/filesystem/filesystem.c

202 lines
4.4 KiB
C
Raw Normal View History

2016-11-19 09:28:01 +00:00
#include "filesystem/filesystem.h"
#include "util.h"
2016-11-01 00:14:31 +00:00
#include <physfs.h>
2016-11-07 22:30:32 +00:00
#include <stdio.h>
2017-01-22 02:18:12 +00:00
#include <stdlib.h>
2016-11-07 02:39:16 +00:00
#ifdef __APPLE__
2016-11-01 00:14:31 +00:00
#include <mach-o/dyld.h>
2016-11-14 22:16:16 +00:00
#elif _WIN32
2016-11-12 09:19:47 +00:00
#include <windows.h>
#include <initguid.h>
#include <KnownFolders.h>
#include <ShlObj.h>
#include <wchar.h>
2016-11-01 00:14:31 +00:00
#endif
2016-11-07 22:30:32 +00:00
static FilesystemState state;
2016-11-01 00:14:31 +00:00
void lovrFilesystemInit(const char* arg0) {
if (!PHYSFS_init(arg0)) {
error("Could not initialize filesystem: %s", PHYSFS_getLastError());
}
2016-11-07 22:30:32 +00:00
state.gameSource = NULL;
state.identity = NULL;
2017-01-22 02:18:12 +00:00
atexit(lovrFilesystemDestroy);
2016-11-01 00:14:31 +00:00
}
void lovrFilesystemDestroy() {
2016-11-08 06:23:13 +00:00
free(state.savePathFull);
free(state.savePathRelative);
2016-11-01 00:14:31 +00:00
PHYSFS_deinit();
}
2016-11-07 22:31:11 +00:00
int lovrFilesystemAppend(const char* path, const char* content, int size) {
if (!PHYSFS_isInit() || !state.identity) {
error("Can not write files until lovr.filesystem.setIdentity is called");
}
// Open file
PHYSFS_file* handle = PHYSFS_openAppend(path);
if (!handle) {
return 0;
}
// Perform write
int bytesWritten = PHYSFS_write(handle, content, 1, size);
PHYSFS_close(handle);
return bytesWritten;
}
2016-11-01 00:14:31 +00:00
int lovrFilesystemExists(const char* path) {
return PHYSFS_exists(path);
}
2016-11-07 22:30:32 +00:00
int lovrFilesystemGetExecutablePath(char* dest, unsigned int size) {
2016-11-07 02:39:16 +00:00
#ifdef __APPLE__
2016-11-07 22:30:32 +00:00
if (_NSGetExecutablePath(dest, &size) == 0) {
return 0;
2016-11-01 00:14:31 +00:00
}
2016-11-14 22:16:16 +00:00
#elif _WIN32
2016-11-12 09:19:47 +00:00
return !GetModuleFileName(NULL, dest, size);
2016-11-14 22:16:16 +00:00
#else
#error "This platform is missing an implementation for lovrFilesystemGetExecutablePath"
2016-11-01 00:14:31 +00:00
#endif
2016-11-07 22:30:32 +00:00
return 1;
}
const char* lovrFilesystemGetIdentity() {
return state.identity;
}
const char* lovrFilesystemGetRealDirectory(const char* path) {
if (!PHYSFS_isInit()) {
return NULL;
}
return PHYSFS_getRealDir(path);
}
const char* lovrFilesystemGetSource() {
return state.gameSource;
}
const char* lovrFilesystemGetUserDirectory() {
if (!PHYSFS_isInit()) {
return NULL;
}
return PHYSFS_getUserDir();
2016-11-01 00:14:31 +00:00
}
2016-11-01 01:35:00 +00:00
int lovrFilesystemIsDirectory(const char* path) {
return PHYSFS_isDirectory(path);
}
int lovrFilesystemIsFile(const char* path) {
return lovrFilesystemExists(path) && !lovrFilesystemIsDirectory(path);
}
2016-11-05 22:55:01 +00:00
void* lovrFilesystemRead(const char* path, int* bytesRead) {
2016-11-07 22:30:32 +00:00
if (!PHYSFS_isInit()) {
return NULL;
}
2016-11-02 03:27:15 +00:00
2016-11-05 22:55:01 +00:00
// Open file
PHYSFS_file* handle = PHYSFS_openRead(path);
2016-11-02 03:27:15 +00:00
if (!handle) {
return NULL;
}
2016-11-05 22:55:01 +00:00
// Get file size
int size = PHYSFS_fileLength(handle);
if (size < 0) {
return NULL;
}
// Allocate buffer
void* data = malloc(size);
if (!data) {
return NULL;
}
// Perform read
*bytesRead = PHYSFS_read(handle, data, 1, size);
PHYSFS_close(handle);
2016-11-02 03:27:15 +00:00
2016-11-05 22:55:01 +00:00
// Make sure we got everything
if (*bytesRead != size) {
free(data);
2016-11-02 03:27:15 +00:00
return NULL;
}
return data;
}
2016-11-07 22:30:32 +00:00
int lovrFilesystemSetIdentity(const char* identity) {
state.identity = identity;
// Unmount old write directory
if (state.savePathFull && state.savePathRelative) {
PHYSFS_removeFromSearchPath(state.savePathRelative);
} else {
state.savePathRelative = malloc(LOVR_PATH_MAX);
state.savePathFull = malloc(LOVR_PATH_MAX);
}
// Set new write directory
#ifdef __APPLE__
const char* userDir = PHYSFS_getUserDir();
PHYSFS_setWriteDir(userDir);
snprintf(state.savePathRelative, LOVR_PATH_MAX, "Library/Application Support/LOVR/%s", identity);
PHYSFS_mkdir(state.savePathRelative);
snprintf(state.savePathFull, LOVR_PATH_MAX, "%s%s", userDir, state.savePathRelative);
if (PHYSFS_setWriteDir(state.savePathFull)) {
PHYSFS_mount(state.savePathFull, NULL, 0);
return 0;
}
2016-11-14 22:16:16 +00:00
#elif _WIN32
2016-11-12 09:19:47 +00:00
PWSTR appData = NULL;
SHGetKnownFolderPath(&FOLDERID_RoamingAppData, 0, NULL, &appData);
snprintf(state.savePathRelative, LOVR_PATH_MAX, "LOVR/%s", identity);
CoTaskMemFree(appData);
2016-11-14 22:16:16 +00:00
#else
#error "This platform is missing an implementation of lovrFilesystemSetIdentity"
2016-11-07 22:30:32 +00:00
#endif
return 1;
}
2016-11-01 00:14:31 +00:00
int lovrFilesystemSetSource(const char* source) {
2016-11-07 22:30:32 +00:00
if (state.gameSource) {
return 1;
}
if (PHYSFS_mount(source, NULL, 0)) {
state.gameSource = source;
return 0;
}
return 1;
2016-11-01 00:14:31 +00:00
}
2016-11-07 22:31:02 +00:00
int lovrFilesystemWrite(const char* path, const char* content, int size) {
if (!PHYSFS_isInit() || !state.identity) {
error("Can not write files until lovr.filesystem.setIdentity is called");
}
// Open file
PHYSFS_file* handle = PHYSFS_openWrite(path);
if (!handle) {
return 0;
}
// Perform write
int bytesWritten = PHYSFS_write(handle, content, 1, size);
PHYSFS_close(handle);
return bytesWritten;
}