forked from mirrors/principia
New storage directory and structure, migration of old storage dir
Closes #188
This commit is contained in:
parent
365856fffc
commit
cffeaf50d3
3 changed files with 172 additions and 27 deletions
|
|
@ -92,7 +92,7 @@ init_curl()
|
|||
exit(1);
|
||||
}
|
||||
|
||||
snprintf(cookie_file, 1024, "%s/c", tms_storage_path());
|
||||
snprintf(cookie_file, 1024, "%s/cookie_jar", tms_storage_path());
|
||||
|
||||
lock_curl("initial_loader-curl_init");
|
||||
P.curl = curl_easy_init();
|
||||
|
|
|
|||
|
|
@ -675,7 +675,7 @@ pkgman::get_pkg_path(int type)
|
|||
else if (type == LEVEL_DB)
|
||||
snprintf(_pkg_path[type], 1023, "%s/pkg/db", tms_storage_cache_path());
|
||||
else
|
||||
snprintf(_pkg_path[type], 1023, "%s/pkg/local", tms_storage_path());
|
||||
snprintf(_pkg_path[type], 1023, "%s/packages", tms_storage_path());
|
||||
}
|
||||
|
||||
return _pkg_path[type];
|
||||
|
|
@ -696,7 +696,7 @@ pkgman::get_level_path(int level_type)
|
|||
|
||||
if (level_type >= LEVEL_LOCAL_STATE) {
|
||||
if (!_state_path[0])
|
||||
snprintf(_state_path, 1023, "%s/sav", tms_storage_path());
|
||||
snprintf(_state_path, 1023, "%s/saves", tms_storage_path());
|
||||
|
||||
return _state_path;
|
||||
}
|
||||
|
|
@ -715,7 +715,7 @@ pkgman::get_level_path(int level_type)
|
|||
else if (level_type == LEVEL_DB)
|
||||
snprintf(_level_path[level_type], 1023, "%s/lvl/db", tms_storage_cache_path());
|
||||
else
|
||||
snprintf(_level_path[level_type], 1023, "%s/lvl/local", tms_storage_path());
|
||||
snprintf(_level_path[level_type], 1023, "%s/levels", tms_storage_path());
|
||||
}
|
||||
|
||||
return _level_path[level_type];
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
|
@ -13,11 +13,12 @@
|
|||
|
||||
#ifdef TMS_BACKEND_WINDOWS
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#define mkdir(dirname, ...) _mkdir(dirname)
|
||||
#define create_dir(dirname, ...) _create_dir(dirname, 0)
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/stat.h>
|
||||
#define create_dir _create_dir
|
||||
#endif
|
||||
|
||||
|
|
@ -81,12 +82,13 @@ const char *tms_storage_path(void)
|
|||
strcat(path, "userdata");
|
||||
} else { // System
|
||||
#ifdef TMS_BACKEND_WINDOWS
|
||||
strcpy(path, getenv("USERPROFILE"));
|
||||
strcat(path, "\\Principia");
|
||||
snprintf(path, 1024, "%s\\Principia", getenv("APPDATA"));
|
||||
#else
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
strcpy(path, pw->pw_dir);
|
||||
strcat(path, "/.principia");
|
||||
const char *xdg = getenv("XDG_DATA_HOME");
|
||||
if (!xdg)
|
||||
snprintf(path, 1024, "%s/.local/share/principia", getenv("HOME"));
|
||||
else
|
||||
snprintf(path, 1024, "%s/principia", xdg);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -114,22 +116,16 @@ const char *tms_storage_cache_path(void)
|
|||
char *path = (char *)malloc(1024);
|
||||
|
||||
if (_storage_portable) { // Portable
|
||||
char* exedir = SDL_GetBasePath();
|
||||
strcpy(path, exedir);
|
||||
strcat(path, "cache");
|
||||
snprintf(path, 1024, "%s/cache", SDL_GetBasePath());
|
||||
} else { // System
|
||||
#ifdef TMS_BACKEND_WINDOWS
|
||||
strcpy(path, getenv("LOCALAPPDATA"));
|
||||
strcat(path, "\\Principia");
|
||||
snprintf(path, 1024, "%s\\Principia", getenv("LOCALAPPDATA"));
|
||||
#else
|
||||
const char* xdg_cache_home = getenv("XDG_CACHE_HOME");
|
||||
if (!xdg_cache_home) {
|
||||
strcpy(path, getenv("HOME"));
|
||||
strcat(path, "/.cache/principia");
|
||||
} else {
|
||||
strcpy(path, xdg_cache_home);
|
||||
strcat(path, "/principia");
|
||||
}
|
||||
const char *xdg = getenv("XDG_CACHE_HOME");
|
||||
if (!xdg)
|
||||
snprintf(path, 1024, "%s/.cache/principia", getenv("HOME"));
|
||||
else
|
||||
snprintf(path, 1024, "%s/principia", xdg);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -138,14 +134,17 @@ const char *tms_storage_cache_path(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void migrate_principia_data();
|
||||
|
||||
void tms_storage_create_dirs(void)
|
||||
{
|
||||
migrate_principia_data();
|
||||
|
||||
char tmp[1024];
|
||||
static const char *s_dirs[]={
|
||||
"",
|
||||
"/lvl", "/lvl/local",
|
||||
"/pkg", "/pkg/local",
|
||||
"/sav"
|
||||
"/levels",
|
||||
"/saves"
|
||||
};
|
||||
|
||||
for (int x=0; x<sizeof(s_dirs)/sizeof(const char*); x++) {
|
||||
|
|
@ -164,3 +163,149 @@ void tms_storage_create_dirs(void)
|
|||
create_dir(tmp, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
}
|
||||
}
|
||||
|
||||
// Storage migration code
|
||||
|
||||
static int file_exists(const char *path) {
|
||||
struct stat st;
|
||||
return stat(path, &st) == 0;
|
||||
}
|
||||
|
||||
static int dir_exists(const char *path) {
|
||||
struct stat st;
|
||||
return stat(path, &st) == 0 && S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
static void move_matching_files(const char *srcdir, const char *dstdir, const char *ext) {
|
||||
#ifdef TMS_BACKEND_WINDOWS
|
||||
char pattern[MAX_PATH];
|
||||
snprintf(pattern, sizeof(pattern), "%s\\*.%s", srcdir, ext);
|
||||
|
||||
WIN32_FIND_DATA ffd;
|
||||
HANDLE hFind = FindFirstFile(pattern, &ffd);
|
||||
if (hFind == INVALID_HANDLE_VALUE) return;
|
||||
|
||||
do {
|
||||
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
|
||||
|
||||
char src[MAX_PATH], dst[MAX_PATH];
|
||||
snprintf(src, sizeof(src), "%s\\%s", srcdir, ffd.cFileName);
|
||||
snprintf(dst, sizeof(dst), "%s\\%s", dstdir, ffd.cFileName);
|
||||
|
||||
rename(src, dst);
|
||||
} while (FindNextFile(hFind, &ffd) != 0);
|
||||
|
||||
FindClose(hFind);
|
||||
#else
|
||||
DIR *dir = opendir(srcdir);
|
||||
if (!dir) return;
|
||||
|
||||
struct dirent *ent;
|
||||
while ((ent = readdir(dir))) {
|
||||
if (ent->d_type == DT_DIR) continue;
|
||||
|
||||
const char *fname = ent->d_name;
|
||||
const char *dot = strrchr(fname, '.');
|
||||
if (!dot || strcmp(dot + 1, ext) != 0) continue;
|
||||
|
||||
char src[1024], dst[1024];
|
||||
snprintf(src, sizeof(src), "%s/%s", srcdir, fname);
|
||||
snprintf(dst, sizeof(dst), "%s/%s", dstdir, fname);
|
||||
|
||||
rename(src, dst);
|
||||
}
|
||||
closedir(dir);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void migrate_principia_data() {
|
||||
char oldpath[1024], newpath[1024], oldpath_old[1024],
|
||||
old_levels[1024], new_levels[1024], old_saves[1024], new_saves[1024];
|
||||
|
||||
if (_storage_portable) {
|
||||
snprintf(oldpath, sizeof(oldpath), "userdata");
|
||||
snprintf(newpath, sizeof(newpath), "userdata");
|
||||
} else {
|
||||
#ifdef TMS_BACKEND_WINDOWS
|
||||
// Old: %USERPROFILE%/Principia
|
||||
snprintf(oldpath, sizeof(oldpath), "%s\\Principia", getenv("USERPROFILE"));
|
||||
// New: %APPDATA%/Principia
|
||||
snprintf(newpath, sizeof(newpath), "%s\\Principia", getenv("APPDATA"));
|
||||
|
||||
#elif defined(TMS_BACKEND_LINUX) && !defined(SCREENSHOT_BUILD)
|
||||
// Old: ~/.principia
|
||||
snprintf(oldpath, sizeof(oldpath), "%s/.principia", getenv("HOME"));
|
||||
// New: $XDG_DATA_HOME/principia or ~/.local/share/principia
|
||||
const char *xdg = getenv("XDG_DATA_HOME");
|
||||
if (!xdg)
|
||||
snprintf(newpath, sizeof(newpath), "%s/.local/share/principia", getenv("HOME"));
|
||||
else
|
||||
snprintf(newpath, sizeof(newpath), "%s/principia", xdg);
|
||||
|
||||
#elif defined(TMS_BACKEND_ANDROID)
|
||||
snprintf(oldpath, sizeof(oldpath), "%s", SDL_AndroidGetExternalStoragePath());
|
||||
snprintf(newpath, sizeof(newpath), "%s", SDL_AndroidGetExternalStoragePath());
|
||||
#else
|
||||
// No migration for this platform
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
snprintf(old_levels, sizeof(old_levels), "%s/levels", oldpath);
|
||||
|
||||
// Return if old path does not exist and new path already exists (unless both paths are the same)
|
||||
if (!dir_exists(oldpath) && dir_exists(newpath))
|
||||
return;
|
||||
|
||||
if (strcmp(oldpath, newpath) == 0 && dir_exists(old_levels))
|
||||
return;
|
||||
|
||||
// We should migrate now
|
||||
printf("Migrating Principia data from %s -> %s\n", oldpath, newpath);
|
||||
|
||||
// Rename old directory to [...]_old
|
||||
snprintf(oldpath_old, sizeof(oldpath_old), "%s_old", oldpath);
|
||||
rename(oldpath, oldpath_old);
|
||||
strncat(oldpath, "_old", sizeof(oldpath)-1);
|
||||
|
||||
snprintf(old_levels, sizeof(old_levels), "%s/lvl/local", oldpath);
|
||||
snprintf(new_levels, sizeof(new_levels), "%s/levels", newpath);
|
||||
|
||||
snprintf(old_saves, sizeof(old_saves), "%s/sav", oldpath);
|
||||
snprintf(new_saves, sizeof(new_saves), "%s/saves", newpath);
|
||||
|
||||
// Create dirs for new location
|
||||
create_dir(newpath, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
create_dir(new_levels, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
create_dir(new_saves, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
|
||||
// Move individual files
|
||||
struct {
|
||||
const char *src;
|
||||
const char *dst;
|
||||
} files[] = {
|
||||
{"c", "cookie_jar"},
|
||||
{"community_host.txt", "community_host.txt"},
|
||||
{"data.bin", "data.bin"},
|
||||
{"run.log", "run.log"},
|
||||
{"settings.ini", "settings.ini"},
|
||||
{"lvl/local/.autosave", "levels/.autosave"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
for (int i = 0; files[i].src; i++) {
|
||||
char src[1024], dst[1024];
|
||||
snprintf(src, sizeof(src), "%s/%s", oldpath, files[i].src);
|
||||
snprintf(dst, sizeof(dst), "%s/%s", newpath, files[i].dst);
|
||||
|
||||
// Only move if source exists and there is nothing in the new location
|
||||
if (file_exists(src) && !file_exists(dst))
|
||||
rename(src, dst);
|
||||
}
|
||||
|
||||
// Move levels, multi-select objects and puzzle solutions
|
||||
move_matching_files(old_levels, new_levels, "plvl");
|
||||
move_matching_files(old_levels, new_levels, "pobj");
|
||||
move_matching_files(old_levels, new_levels, "psol");
|
||||
|
||||
move_matching_files(old_saves, new_saves, "psav");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue