use std::filesystem in more places

This commit is contained in:
Tim Felgentreff 2021-06-14 23:23:40 +02:00
parent 00d7531730
commit e053a7e53a
2 changed files with 50 additions and 148 deletions

View file

@ -268,19 +268,15 @@ int check_version(char* tool_path, char* data_path) {
}
static void ExtractData(char* extractor_tool, char* destination, char* scripts_path, int force=0) {
struct stat st;
int canJustReextract;
#ifdef EXTRACTION_FILES
if (force == 0) {
canJustReextract = 1;
char* extraction_files[] = { EXTRACTION_FILES, NULL };
char* efile = extraction_files[0];
char efile_path[PATH_MAX] = {'\0'};
for (int i = 0; efile != NULL; i++) {
strcpy(efile_path, destination);
strcat(efile_path, SLASH);
strcat(efile_path, efile);
if (stat(efile_path, &st) != 0) {
std::filesystem::path efile_path = std::filesystem::path(destination) / efile;
if (!std::filesystem::exists(efile_path)) {
// file to extract not found
canJustReextract = 0;
}
@ -311,17 +307,16 @@ static void ExtractData(char* extractor_tool, char* destination, char* scripts_p
int patterncount = 0;
while (filepatterns[patterncount++] != NULL);
#endif
char srcfolder[1024] = {'\0'};
std::filesystem::path srcfolder;
if (!canJustReextract) {
const char* datafile = tinyfd_openFileDialog(GAME_CD " location", "",
patterncount - 1, filepatterns, NULL, 0);
if (datafile == NULL) {
exit(-1);
}
strcpy(srcfolder, datafile);
parentdir(srcfolder);
srcfolder = std::filesystem::path(datafile).parent_path();
} else {
strcpy(srcfolder, destination);
srcfolder = std::filesystem::path(destination);
}
#ifdef WIN32
@ -337,34 +332,32 @@ static void ExtractData(char* extractor_tool, char* destination, char* scripts_p
#else
char* sourcepath = strdup(scripts_path);
#endif
mkdir_p(destination);
if (stat(sourcepath, &st) != 0) {
std::filesystem::create_directories(std::filesystem::path(destination));
if (!std::filesystem::exists(sourcepath)) {
// deployment time path not found, try compile time path
strcpy(sourcepath, SRC_PATH());
parentdir(sourcepath);
strcpy(sourcepath, std::filesystem::path(SRC_PATH()).parent_path().string().c_str());
}
#ifndef WIN32
if (stat(sourcepath, &st) != 0) {
if (!std::filesystem::exists(sourcepath)) {
// deployment time path might be same as extractor
strcpy(sourcepath, extractor_tool);
parentdir(sourcepath);
strcpy(sourcepath, std::filesystem::path(extractor_tool).parent_path().string().c_str());
}
#endif
if (stat(sourcepath, &st) != 0) {
if (!std::filesystem::exists(sourcepath)) {
// scripts not found, abort!
char msg[BUFF_SIZE * 2];
strcpy(msg, "There was an error copying the data, could not discover scripts path: ");
strcat(msg, sourcepath);
tinyfd_messageBox("Error", msg, "ok", "error", 1);
std::string msg("There was an error copying the data, could not discover scripts path: ");
msg += sourcepath;
tinyfd_messageBox("Error", msg.c_str(), "ok", "error", 1);
return;
}
if (force != 2) {
char contrib_src_path[BUFF_SIZE];
char contrib_dest_path[BUFF_SIZE];
std::filesystem::path contrib_src_path;
std::filesystem::path contrib_dest_path(destination);
int i = 0;
int optional = 0;
char* contrib_directories[] = CONTRIB_DIRECTORIES;
@ -375,27 +368,22 @@ static void ExtractData(char* extractor_tool, char* destination, char* scripts_p
} else {
if (contrib_directories[i][0] != '/') {
// absolute Unix paths are not appended to the source path
strcpy(contrib_src_path, sourcepath);
strcat(contrib_src_path, SLASH);
strcat(contrib_src_path, contrib_directories[i]);
contrib_src_path = std::filesystem::path(sourcepath);
contrib_src_path /= contrib_directories[i];
} else {
strcpy(contrib_src_path, contrib_directories[i]);
contrib_src_path = std::filesystem::path(contrib_directories[i]);
}
if (stat(contrib_src_path, &st) != 0) {
if (!std::filesystem::exists(contrib_src_path)) {
// contrib dir not found, abort!
if (!optional) {
char msg[BUFF_SIZE * 2];
strcpy(msg, "There was an error copying the data, could not discover contributed directory path: ");
strcat(msg, contrib_src_path);
tinyfd_messageBox("Error", msg, "ok", "error", 1);
std::string msg("There was an error copying the data, could not discover contributed directory path: ");
msg += contrib_src_path.string();
error("Error", msg.c_str());
return;
}
} else {
strcpy(contrib_dest_path, destination);
strcat(contrib_dest_path, SLASH);
strcat(contrib_dest_path, contrib_directories[i + 1]);
copy_dir(contrib_src_path, contrib_dest_path);
copy_dir(contrib_src_path, contrib_dest_path / contrib_directories[i + 1]);
}
i += 2;
}
@ -416,7 +404,13 @@ static void ExtractData(char* extractor_tool, char* destination, char* scripts_p
#endif
strcat(cmdbuf, extractor_tool);
strcat(cmdbuf, " " QUOTE);
strcat(cmdbuf, srcfolder);
strcat(cmdbuf, srcfolder.string().c_str());
#ifdef WIN32
// a trailing backslash will break the extractor because of quoting
if (cmdbuf[strlen(cmdbuf) - 1] == '\\') {
cmdbuf[strlen(cmdbuf) - 1] = '\0';
}
#endif
strcat(cmdbuf, QUOTE " " QUOTE);
strcat(cmdbuf, destination);
strcat(cmdbuf, QUOTE);
@ -647,10 +641,9 @@ int main(int argc, char * argv[]) {
ExtractData(extractor_path, data_path, scripts_path);
}
if ( stat(title_path, &st) != 0 ) {
char msg[BUFF_SIZE * 2];
strcat(msg, DATA_NOT_EXTRACTED);
strcat(msg, " (extraction was attempted, but it seems an error occurred)");
error(TITLE, msg);
std::string msg(DATA_NOT_EXTRACTED);
msg += " (extraction was attempted, but it seems an error occurred)";
error(TITLE, msg.c_str());
}
}
@ -728,7 +721,6 @@ int main(int argc, char * argv[]) {
strcpy(msg, "Execution failed for: ");
strcat(msg, stratagus_bin);
strcat(msg, " ");
char *subargv;
for (int i = 1; stratagus_argv[i] != NULL; i++) {
if (strlen(msg) + strlen(stratagus_argv[i]) > BUFF_SIZE * 8) {
break;

View file

@ -95,6 +95,9 @@ void copy_dir(const char* source_folder, const char* target_folder);
#include <sys/stat.h>
#include <sys/types.h>
#include <string>
#include <filesystem>
#include "stratagus-tinyfiledialogs.h"
#ifdef WIN32
@ -102,8 +105,6 @@ void copy_dir(const char* source_folder, const char* target_folder);
#else
#define BUFF_SIZE 4096
#endif
char dst_root[BUFF_SIZE];
char src_root[BUFF_SIZE];
void error(const char* title, const char* text) {
tinyfd_messageBox(title, text, "ok", "error", 1);
@ -111,114 +112,23 @@ void error(const char* title, const char* text) {
}
void mkdir_p(const char* path) {
int error = 0;
printf("mkdir %s\n", path);
if (mkdir(path, 0777)) {
error = errno;
if (error == ENOENT) {
char *sep = strrchr((char*)path, '/');
if (sep == NULL) {
sep = strrchr((char*)path, SLASH[0]);
}
if (sep != NULL) {
*sep = '\0';
if (strlen(path) > 0) {
// will be null if the we reach the first /
mkdir_p(path);
}
*sep = '/';
mkdir(path, 0777);
}
} else if (error != EEXIST) {
if (mkdir(path, 0777)) {
printf("Error while trying to create '%s'\n", path);
}
}
}
std::filesystem::create_directories(path);
}
#ifdef WIN32
#include <wchar.h>
#include <string>
#include <filesystem>
void copy_dir(const char* source_folder, const char* target_folder)
{
if (std::filesystem::equivalent(source_folder, target_folder)) {
return;
void copy_dir(std::filesystem::path source_folder, std::filesystem::path target_folder) {
if (std::filesystem::exists(target_folder)) {
if (std::filesystem::equivalent(source_folder, target_folder)) {
return;
}
// first delete the target_folder, if it exists, to ensure clean slate
std::filesystem::remove_all(target_folder);
} else {
// make the parentdir of the target folder
std::filesystem::create_directories(target_folder.parent_path());
}
// make the parentdir of the target folder
char* ptarget = _strdup(target_folder);
parentdir(ptarget);
mkdir_p(ptarget);
// convert source and target folder strings to windows wide strings
wchar_t *wsource_folder = new wchar_t[strlen(source_folder) + 1];
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, wsource_folder, strlen(source_folder) + 1, source_folder, _TRUNCATE);
wchar_t *wtarget_folder = new wchar_t[strlen(target_folder) + 1];
mbstowcs_s(&convertedChars, wtarget_folder, strlen(target_folder) + 1, target_folder, _TRUNCATE);
WCHAR sf[MAX_PATH + 1];
WCHAR tf[MAX_PATH + 1];
wcscpy_s(sf, MAX_PATH, wsource_folder);
wcscpy_s(tf, MAX_PATH, wtarget_folder);
// ensure we have double-null terminated strings like Windows docs demand
sf[lstrlenW(sf) + 1] = 0;
tf[lstrlenW(tf) + 1] = 0;
// first delete the target_folder, if it exists
SHFILEOPSTRUCTW deleteS = { 0 };
deleteS.wFunc = FO_DELETE;
deleteS.pTo = tf;
deleteS.pFrom = tf;
deleteS.fFlags = FOF_SILENT | FOF_NOCONFIRMMKDIR | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NO_UI;
SHFileOperationW(&deleteS);
// now copy the new folder in its place
SHFILEOPSTRUCTW s = { 0 };
s.wFunc = FO_COPY;
s.pTo = tf;
s.pFrom = sf;
s.fFlags = FOF_SILENT | FOF_NOCONFIRMMKDIR | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NO_UI;
SHFileOperationW(&s);
std::filesystem::copy(source_folder, target_folder, std::filesystem::copy_options::recursive | std::filesystem::copy_options::overwrite_existing);
}
#else
int copy_file(const char* src_path, const struct stat* sb, int typeflag) {
char dst_path[BUFF_SIZE];
printf("%s to %s\n", src_path, dst_root);
strcpy(dst_path, dst_root);
strcat(dst_path, src_path + strlen(src_root));
switch(typeflag) {
case FTW_D:
mkdir_p(dst_path);
break;
case FTW_F:
mkdir_p(parentdir(strdup(dst_path)));
FILE* in = fopen(src_path, "rb");
FILE* out = fopen(dst_path, "wb");
char buf[4096];
int c = 0;
if (!in) {
error("Extraction error", "Could not open source folder for reading.");
}
if (!out) {
error("Extraction error", "Could not open data folder for writing.");
}
while ((c = fread(buf, sizeof(char), 4096, in))) {
fwrite(buf, sizeof(char), c, out);
}
fclose(in);
fclose(out);
break;
}
return 0;
}
void copy_dir(const char* src_path, const char* dst_path) {
printf("Copying %s to %s\n", src_path, dst_path);
mkdir_p(parentdir(strdup(dst_path)));
strcpy(dst_root, dst_path);
strcpy(src_root, src_path);
ftw(src_path, copy_file, 20);
}
#endif
#ifdef WIN32
char* GetExtractionLogPath(const char* game_name, char* data_path) {