mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge pull request #2648 from rubdos/POSIX_platform
Implement several POSIX methods.
This commit is contained in:
commit
6bdc5fc978
|
@ -7,6 +7,8 @@
|
||||||
- Feature: Allow enabling / disabling of different notifications.
|
- Feature: Allow enabling / disabling of different notifications.
|
||||||
- Feature: Improved tile inspector.
|
- Feature: Improved tile inspector.
|
||||||
- Feature: Integrate RCT1 style scenario select with optional unlock progression.
|
- Feature: Integrate RCT1 style scenario select with optional unlock progression.
|
||||||
|
- Fix: Dated autosave files are not created on OSX and Linux.
|
||||||
|
- Fix: Title sequence directories are not deleted when title sequence is deleted on OSX and Linux.
|
||||||
- Fix: [#1333] Rides never become safe again after a crash.
|
- Fix: [#1333] Rides never become safe again after a crash.
|
||||||
- Fix: [#2126] Ferris Wheels set to "backward rotation" stop working (original bug)
|
- Fix: [#2126] Ferris Wheels set to "backward rotation" stop working (original bug)
|
||||||
- Fix: [#2449] Turning off Day/Night Circle while it is night doesn't reset back to day
|
- Fix: [#2449] Turning off Day/Night Circle while it is night doesn't reset back to day
|
||||||
|
|
|
@ -37,9 +37,18 @@
|
||||||
#include "../openrct2.h"
|
#include "../openrct2.h"
|
||||||
#include "../util/util.h"
|
#include "../util/util.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <fts.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
|
||||||
// The name of the mutex used to prevent multiple instances of the game from running
|
// The name of the mutex used to prevent multiple instances of the game from running
|
||||||
#define SINGLE_INSTANCE_MUTEX_NAME "RollerCoaster Tycoon 2_GSKMUTEX"
|
#define SINGLE_INSTANCE_MUTEX_NAME "openrct2.lock"
|
||||||
|
|
||||||
|
#define FILE_BUFFER_SIZE 4096
|
||||||
|
|
||||||
utf8 _userDataDirectoryPath[MAX_PATH] = { 0 };
|
utf8 _userDataDirectoryPath[MAX_PATH] = { 0 };
|
||||||
utf8 _openrctDataDirectoryPath[MAX_PATH] = { 0 };
|
utf8 _openrctDataDirectoryPath[MAX_PATH] = { 0 };
|
||||||
|
@ -165,13 +174,85 @@ bool platform_ensure_directory_exists(const utf8 *path)
|
||||||
|
|
||||||
bool platform_directory_delete(const utf8 *path)
|
bool platform_directory_delete(const utf8 *path)
|
||||||
{
|
{
|
||||||
STUB();
|
log_verbose("Recursively deleting directory %s", path);
|
||||||
|
|
||||||
|
FTS *ftsp;
|
||||||
|
FTSENT *p, *chp;
|
||||||
|
|
||||||
|
// fts_open only accepts non const paths, so we have to take a copy
|
||||||
|
char* ourPath = (char*)malloc(strlen(path) + 1);
|
||||||
|
strcpy(ourPath, path);
|
||||||
|
|
||||||
|
utf8* const patharray[2] = {ourPath, NULL};
|
||||||
|
if ((ftsp = fts_open(patharray, FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR, NULL)) == NULL) {
|
||||||
|
log_error("fts_open returned NULL");
|
||||||
|
free(ourPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
chp = fts_children(ftsp, 0);
|
||||||
|
if (chp == NULL) {
|
||||||
|
log_verbose("No files to traverse, deleting directory %s", path);
|
||||||
|
remove(path);
|
||||||
|
free(ourPath);
|
||||||
|
return true; // No files to traverse
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((p = fts_read(ftsp)) != NULL) {
|
||||||
|
switch (p->fts_info) {
|
||||||
|
case FTS_DP: // Directory postorder, which means
|
||||||
|
// the directory is empty
|
||||||
|
|
||||||
|
case FTS_F: // File
|
||||||
|
if(remove(p->fts_path)) {
|
||||||
|
log_error("Could not remove %s", p->fts_path);
|
||||||
|
fts_close(ftsp);
|
||||||
|
free(ourPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FTS_ERR:
|
||||||
|
log_error("Error traversing %s", path);
|
||||||
|
fts_close(ftsp);
|
||||||
|
free(ourPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ourPath);
|
||||||
|
fts_close(ftsp);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool platform_lock_single_instance()
|
bool platform_lock_single_instance()
|
||||||
{
|
{
|
||||||
STUB();
|
char pidFilePath[MAX_PATH];
|
||||||
|
char separator = platform_get_path_separator();
|
||||||
|
|
||||||
|
strncpy(pidFilePath, _userDataDirectoryPath, MAX_PATH);
|
||||||
|
strncat(pidFilePath, &separator, 1);
|
||||||
|
strncat(pidFilePath, SINGLE_INSTANCE_MUTEX_NAME,
|
||||||
|
MAX_PATH - strnlen(pidFilePath, MAX_PATH) - 1);
|
||||||
|
|
||||||
|
// We will never close this file manually. The operating system will
|
||||||
|
// take care of that, because flock keeps the lock as long as the
|
||||||
|
// file is open and closes it automatically on file close.
|
||||||
|
// This is intentional.
|
||||||
|
int pidFile = open(pidFilePath, O_CREAT | O_RDWR, 0666);
|
||||||
|
|
||||||
|
if (pidFile == -1) {
|
||||||
|
log_warning("Cannot open lock file for writing.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (flock(pidFile, LOCK_EX | LOCK_NB) == -1) {
|
||||||
|
if (errno == EWOULDBLOCK) {
|
||||||
|
log_warning("Another OpenRCT2 session has been found running.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
log_error("flock returned an uncatched errno: %d", errno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,23 +564,57 @@ void platform_enumerate_directories_end(int handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
int platform_get_drives(){
|
int platform_get_drives(){
|
||||||
/*
|
// POSIX systems do not know drives. Return 0.
|
||||||
return GetLogicalDrives();
|
|
||||||
*/
|
|
||||||
STUB();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool platform_file_copy(const utf8 *srcPath, const utf8 *dstPath, bool overwrite)
|
bool platform_file_copy(const utf8 *srcPath, const utf8 *dstPath, bool overwrite)
|
||||||
{
|
{
|
||||||
STUB();
|
log_verbose("Copying %s to %s", srcPath, dstPath);
|
||||||
|
|
||||||
|
FILE *dstFile;
|
||||||
|
|
||||||
|
if (overwrite) {
|
||||||
|
dstFile = fopen(dstPath, "wb");
|
||||||
|
} else {
|
||||||
|
dstFile = fopen(dstPath, "wbx");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dstFile != NULL) {
|
||||||
|
if (errno == EEXIST) {
|
||||||
|
log_warning("platform_file_copy: Not overwriting %s, because overwrite flag == false", dstPath);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error("Could not open destination file %s for copying", dstPath);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open both files and check whether they are opened correctly
|
||||||
|
FILE *srcFile = fopen(srcPath, "rb");
|
||||||
|
if (!srcFile) {
|
||||||
|
fclose(dstFile);
|
||||||
|
log_error("Could not open source file %s for copying", srcPath);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t amount_read = 0;
|
||||||
|
|
||||||
|
char* buffer = (char*) malloc(FILE_BUFFER_SIZE);
|
||||||
|
while ((amount_read = fread(buffer, FILE_BUFFER_SIZE, 1, srcFile))) {
|
||||||
|
fwrite(buffer, amount_read, 1, dstFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(srcFile);
|
||||||
|
fclose(dstFile);
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool platform_file_move(const utf8 *srcPath, const utf8 *dstPath)
|
bool platform_file_move(const utf8 *srcPath, const utf8 *dstPath)
|
||||||
{
|
{
|
||||||
STUB();
|
return rename(srcPath, dstPath) == 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool platform_file_delete(const utf8 *path)
|
bool platform_file_delete(const utf8 *path)
|
||||||
|
|
Loading…
Reference in New Issue