From 250152580c31628eb5a57be1d0c7eba8feb7150d Mon Sep 17 00:00:00 2001
From: EyeGuy <vanya619@list.ru>
Date: Sat, 1 Feb 2025 23:49:22 +0300
Subject: [PATCH] Update fs

---
 source/core/FileSystem.cpp | 592 ++++++++++++++++++-------------------
 source/core/FileSystem.h   |   4 +-
 2 files changed, 284 insertions(+), 312 deletions(-)

diff --git a/source/core/FileSystem.cpp b/source/core/FileSystem.cpp
index a55a92411..d66a395f2 100644
--- a/source/core/FileSystem.cpp
+++ b/source/core/FileSystem.cpp
@@ -12,7 +12,7 @@ IFileIterator *CFileSystem::getListIterator(const char *szPath, const char **szE
 	Array<String> paths;
 	String basePath(szPath);
 
-	if (!isAbsolutePath(szPath))
+	if(!isAbsolutePath(szPath))
 	{
 		getAllvariantsCanonizePath(szPath, paths);
 	}
@@ -26,47 +26,46 @@ IFileIterator *CFileSystem::getListIterator(const char *szPath, const char **szE
 
 void CFileSystem::addPathInPriorityArray(int id, int iPriority)
 {
-	Pair newElement{ iPriority, id };
+	Pair newElement{iPriority, id};
 
 	//Если приоритет по умолчанию и нет элементов - задаем значение 0 (потому что первый)
 	//Если элементов больше чем 0 то тогда ставим самый большой приоритет из возможных
-	if (iPriority == -1)
+	if(iPriority == -1)
 	{
 		UINT size = m_priorityArray.size();
 		newElement.priority = size > 0 ? m_priorityArray[0].priority + 1 : 0;
 	}
 
-	m_priorityArray.insert(newElement, [](const Pair &obj, const Pair &obj2) -> bool {return obj.priority <= obj2.priority; });
+	m_priorityArray.insert(newElement, [](const Pair &obj, const Pair &obj2) -> bool { return obj.priority <= obj2.priority; });
 }
 
 bool CFileSystem::isFileOrDirectory(const char *szPath, bool isFile)
 {
-    char path[SIZE_PATH];
-    getAbsoluteCanonizePath(szPath, path, SIZE_PATH);
+	char path[SIZE_PATH];
+	getAbsoluteCanonizePath(szPath, path, SIZE_PATH);
 
-    if (CHECK_CORRECT_PATH(path))
-    {
-        return false;
-    }
+	if(CHECK_CORRECT_PATH(path))
+	{
+		return false;
+	}
 
-    DWORD flag = GetFileAttributesW(CMB2WC(path));
+	DWORD flag = GetFileAttributesW(CMB2WC(path));
 
-    //Проверка на то куда имено ведет путь - к файлу или папке
-    return (flag != INVALID_FILE_ATTRIBUTES) && (isFile ? !(flag & FILE_ATTRIBUTE_DIRECTORY) : (flag & FILE_ATTRIBUTE_DIRECTORY));
+	//Проверка на то куда имено ведет путь - к файлу или папке
+	return (flag != INVALID_FILE_ATTRIBUTES) && (isFile ? !(flag & FILE_ATTRIBUTE_DIRECTORY) : (flag & FILE_ATTRIBUTE_DIRECTORY));
 }
 
 void CFileSystem::getAllvariantsCanonizePath(const char *szPath, Array<String> &container)
 {
-	for (int i = 0, I = m_filePaths.size(); i < I; ++i)
+	char szBuff[SIZE_PATH];
+
+	for(int i = 0, I = m_filePaths.size(); i < I; ++i)
 	{
-		String buff = m_filePaths[i];
-		buff += '/';
-		buff += szPath;
-		buff += '/'; // <- оптимизация buffObj
+		sprintf(szBuff, "%s/%s/", m_filePaths[i].c_str(), szPath);
 
-		if (isDirectory(buff.c_str()))
+		if(isDirectory(szBuff))
 		{
-			container.push_back(buff);
+			container.push_back(szBuff);
 		}
 	}
 }
@@ -75,86 +74,85 @@ void CFileSystem::getNormalPath(const char *szPath, char *outBuff, int iOutMax)
 {
 	if(szPath != outBuff)
 	{
-    size_t len = strlen(szPath) + 1;
-
-		if(iOutMax < len)
-    {
-        MEMCCPY_ERROR(outBuff);
-        return;
-    }
+		if(iOutMax < strlen(szPath) + 1)
+		{
+			MEMCCPY_ERROR(outBuff);
+			return;
+		}
 
-    memcpy(outBuff, szPath, len);
+		strcpy(outBuff, szPath);
 	}
 
-    do
-    {
-        *outBuff = *outBuff == '/' ? '\\' : *outBuff;
-    } while (*outBuff++ != '\0');
+	do
+	{
+		*outBuff = *outBuff == '/' ? '\\' : *outBuff;
+	}
+	while(*outBuff++ != '\0');
 }
 
 bool CFileSystem::isAbsolutePathInRoot(const char *szPath)
 {
-    if (!isAbsolutePath(szPath))
-    {
-        return false;
-    }
+	if(!isAbsolutePath(szPath))
+	{
+		return false;
+	}
 
-    char rootPath[SIZE_PATH];
-    getFullPathToBuild(rootPath, SIZE_PATH);
-    const char *pos = strstr(szPath, rootPath);
+	char rootPath[SIZE_PATH];
+	getFullPathToBuild(rootPath, SIZE_PATH);
+	const char *pos = strstr(szPath, rootPath);
 
-    return pos != nullptr;
+	return pos != nullptr;
 }
 
 void CFileSystem::getAbsoluteCanonizePath(const char *szPath, char *outPath, int iOutMax)
 {
-    bool absolute = isAbsolutePath(szPath);
-    bool correctPath = true;
-
-    size_t len = absolute ? strlen(szPath) + 1 : SIZE_PATH;
-
-    if (absolute) 
-    {
-        memcpy(outPath, szPath, len);
-    }
-    else
-    { 
-        correctPath = resolvePath(szPath, outPath, len);
-    }
-
-    //Во время поиска пути могут произойти ошибки - путь может быть не найден, или слишком маленький буфер для записи
-    if (correctPath)
-    {
-        //Если все корректно прошло, то путь можно канонизировать
-        canonize_path(outPath);
-    }
-    else
-    {
-        //Если что то пошло не так записываем '\0' в память, потом это значение можно проверить
-        MEMCCPY_ERROR(outPath);
-    }
+	bool absolute = isAbsolutePath(szPath);
+	bool correctPath = true;
+
+	size_t len = absolute ? strlen(szPath) + 1 : SIZE_PATH;
+
+	if(absolute)
+	{
+		memcpy(outPath, szPath, len);
+	}
+	else
+	{
+		correctPath = resolvePath(szPath, outPath, len);
+	}
+
+	//Во время поиска пути могут произойти ошибки - путь может быть не найден, или слишком маленький буфер для записи
+	if(correctPath)
+	{
+		//Если все корректно прошло, то путь можно канонизировать
+		canonize_path(outPath);
+	}
+	else
+	{
+		//Если что то пошло не так записываем '\0' в память, потом это значение можно проверить
+		MEMCCPY_ERROR(outPath);
+	}
 }
 
 void CFileSystem::getFullPathToBuild(char *buff, int iSize)
 {
-    GetModuleFileName(nullptr, buff, iSize);
-    dirname(buff);
-    dirname(buff);
-    canonize_path(buff);
+	GetModuleFileName(nullptr, buff, iSize);
+	dirname(buff);
+	dirname(buff);
+	canonize_path(buff);
 }
 
 void CFileSystem::getFileName(const char *name, char *outName, int iOutBuff)
 {
-    WIN32_FIND_DATAW wfd;
+	WIN32_FIND_DATAW wfd;
 	HANDLE hFind = FindFirstFileW(CMB2WC(name), &wfd);
 
-    if (hFind != INVALID_HANDLE_VALUE)
-    {
-        FIND_CLOSE(hFind);
+	if(hFind != INVALID_HANDLE_VALUE)
+	{
+		FIND_CLOSE(hFind);
 
-        //Если размера буфера хватает - то записываем имя файла, если нет то записываем в [0] '\0'
+		//Если размера буфера хватает - то записываем имя файла, если нет то записываем в [0] '\0'
 		iOutBuff > MAX_PATH ? memcpy(outName, CWC2MB(wfd.cFileName), MAX_PATH) : MEMCCPY_ERROR(outName);
-    }
+	}
 }
 
 time_t CFileSystem::filetimeToTime_t(const FILETIME& ft)
@@ -163,7 +161,7 @@ time_t CFileSystem::filetimeToTime_t(const FILETIME& ft)
 	ull.LowPart = ft.dwLowDateTime;
 	ull.HighPart = ft.dwHighDateTime;
 
-    return ull.QuadPart / 10000000ULL - 11644473600ULL;
+	return ull.QuadPart / 10000000ULL - 11644473600ULL;
 }
 
 HANDLE CFileSystem::getFileHandle(const char *szPath)
@@ -179,135 +177,134 @@ HANDLE CFileSystem::getFileHandle(const char *szPath)
 
 bool CFileSystem::isAbsolutePath(const char *szPath)
 {
-    while (*szPath != '\0')
-    {
-        //Для корректности нужна проверка на разные слеши, ведь на вход может прийти путь не с /
-        if (*szPath == ':' && (*(szPath + 1) == '/' || *(szPath + 1) == '\\'))
-        {
-            return true;
-        }
-        ++szPath;
-    }
-    return false;
+	while(*szPath != '\0')
+	{
+		//Для корректности нужна проверка на разные слеши, ведь на вход может прийти путь не с /
+		if(*szPath == ':' && (*(szPath + 1) == '/' || *(szPath + 1) == '\\'))
+		{
+			return true;
+		}
+		++szPath;
+	}
+	return false;
 }
 
-String *CFileSystem::copyFile(const char* szPath)
+void CFileSystem::copyFile(const char* szPath, char *szOut)
 {
-    createDirectory(m_filePaths[m_writableRoot].c_str());
+	createDirectory(m_filePaths[m_writableRoot].c_str());
 
-    char fn[MAX_PATH];
-    getFileName(szPath, fn, MAX_PATH);
-    String *newFilePath = new String(m_filePaths[m_writableRoot] + '/' + fn);
-	CopyFileW(CMB2WC(szPath), CMB2WC(newFilePath->c_str()), false);
-
-    return newFilePath;
+	char fn[SIZE_PATH];
+	getFileName(szPath, fn, SIZE_PATH);
+	sprintf(szOut, "%s/%s", m_filePaths[m_writableRoot].c_str(), fn);
+	CopyFileW(CMB2WC(szPath), CMB2WC(szOut), false);
 }
 
 CFileSystem::CFileSystem()
 {
-    getFullPathToBuild(m_pathToBuild, SIZE_PATH);
+	getFullPathToBuild(m_pathToBuild, SIZE_PATH);
 }
 
 UINT CFileSystem::addRoot(const char *szPath, int iPriority)
 {
-    String str;
-
-    //Если путь не абсолютный - то прибавляем к нему часть пути к папке build
-    if (!isAbsolutePath(szPath))
-    {
-        str += m_pathToBuild;
-    }
+	char szBuff[SIZE_PATH];
 
-    str += szPath; // <--- Оптимизация для того что бы не создавать временных объектов
+	//Если путь не абсолютный - то прибавляем к нему часть пути к папке build
+	if(!isAbsolutePath(szPath))
+	{
+		sprintf(szBuff, "%s%s", m_pathToBuild, szPath);
+	}
+	else
+	{
+		sprintf(szBuff, "%s", szPath);
+	}
 
-    m_filePaths.push_back(str);
-    addPathInPriorityArray(m_filePaths.size() - 1, iPriority);
+	m_filePaths.push_back(szBuff);
+	addPathInPriorityArray(m_filePaths.size() - 1, iPriority);
 
-    //Если у нас некорректный путь для записи и путь не является архивным
-    if (m_writableRoot == -1 && *szPath != '@')
-    {
-        m_writableRoot = m_filePaths.size() - 1;
-    }
+	//Если у нас некорректный путь для записи и путь не является архивным
+	if(m_writableRoot == -1 && *szPath != '@')
+	{
+		m_writableRoot = m_filePaths.size() - 1;
+	}
 
-    return m_filePaths.size() - 1;
+	return m_filePaths.size() - 1;
 }
 
-UINT CFileSystem::getRootCount() const 
+UINT CFileSystem::getRootCount() const
 {
-    return m_filePaths.size();
+	return m_filePaths.size();
 }
 
 const char *CFileSystem::getRoot(UINT id) const
 {
-    FILEID_CHECKED(m_filePaths.size());
+	FILEID_CHECKED(m_filePaths.size());
 
-    return m_filePaths[id].c_str();
+	return m_filePaths[id].c_str();
 }
 
 void CFileSystem::setWritableRoot(UINT id)
 {
-    FILEID_CHECKED(m_filePaths.size());
+	FILEID_CHECKED(m_filePaths.size());
 
-    m_writableRoot = id;
+	m_writableRoot = id;
 }
 
 bool CFileSystem::resolvePath(const char *szPath, char *szOut, size_t iOutMax)
 {
-    size_t len = 0;
+	size_t len = 0;
 
-    if (isAbsolutePath(szPath))
-    {
-        len = strlen(szPath) + 1;
+	if(isAbsolutePath(szPath))
+	{
+		len = strlen(szPath) + 1;
+
+		CHECK_SIZE(len, iOutMax);
 
-        CHECK_SIZE(len, iOutMax);
+		memcpy(szOut, szPath, len);
+		return true;
+	}
 
-        memcpy(szOut, szPath, len);
-        return true;
-    }
-    
-    String buff;
+	char szBuff[SIZE_PATH];
 
-    for (UINT i = 0, l = m_priorityArray.size(); i < l; ++i)
-    {
-        int id = m_priorityArray[i].pathId;
-        buff = (m_filePaths[id] + '/' + szPath);
+	for(UINT i = 0, l = m_priorityArray.size(); i < l; ++i)
+	{
+		int id = m_priorityArray[i].pathId;
+		len = sprintf(szBuff, "%s/%s", m_filePaths[id].c_str(), szPath) + 1;
 
-        if (fileExists(buff.c_str())/* && isFile(buff.c_str())*/)
-        {
-            CHECK_SIZE(len, iOutMax);
+		if(fileExists(szBuff)/* && isFile(buff.c_str())*/)
+		{
+			CHECK_SIZE(len, iOutMax);
 
-            len = buff.length() + 1;
-            memcpy(szOut, buff.c_str(), len);
-            return true;
-        }
-    }
+			strcpy(szOut, szBuff);
+			return true;
+		}
+	}
 
-    return false;
+	return false;
 }
 
 bool CFileSystem::fileExists(const char *szPath)
 {
-    char path[SIZE_PATH];
-    getAbsoluteCanonizePath(szPath, path, SIZE_PATH);
+	char path[SIZE_PATH];
+	getAbsoluteCanonizePath(szPath, path, SIZE_PATH);
 
-    if (CHECK_CORRECT_PATH(path))
-    {
-        //Если не удалось найти полный путь - на выход
-        return false;
-    }
+	if(CHECK_CORRECT_PATH(path))
+	{
+		//Если не удалось найти полный путь - на выход
+		return false;
+	}
 
-    return fileGetSize(path) != FILE_NOT_FOUND;
+	return fileGetSize(path) != FILE_NOT_FOUND;
 }
 
 size_t CFileSystem::fileGetSize(const char *szPath)
 {
-    char path[SIZE_PATH];
-    getAbsoluteCanonizePath(szPath, path, SIZE_PATH);
+	char path[SIZE_PATH];
+	getAbsoluteCanonizePath(szPath, path, SIZE_PATH);
 
-    if (CHECK_CORRECT_PATH(path))
-    {
-        return FILE_NOT_FOUND;
-    }
+	if(CHECK_CORRECT_PATH(path))
+	{
+		return FILE_NOT_FOUND;
+	}
 
 	WIN32_FILE_ATTRIBUTE_DATA lpFileInformation;
 
@@ -315,7 +312,7 @@ size_t CFileSystem::fileGetSize(const char *szPath)
 
 	//Преобразование размера из старших и младших бит
 	ULONGLONG FileSize = (static_cast<ULONGLONG>(lpFileInformation.nFileSizeHigh) <<
-        sizeof(lpFileInformation.nFileSizeLow) * NUM_BITS_IN_BYTE) |
+		sizeof(lpFileInformation.nFileSizeLow) * NUM_BITS_IN_BYTE) |
 		lpFileInformation.nFileSizeLow;
 
 	//Если result != 0 то все хорошо, если 0 то файл не найден
@@ -324,25 +321,25 @@ size_t CFileSystem::fileGetSize(const char *szPath)
 
 bool CFileSystem::isFile(const char *szPath)
 {
-    return isFileOrDirectory(szPath, true);
+	return isFileOrDirectory(szPath, true);
 }
 
 bool CFileSystem::isDirectory(const char *szPath)
 {
-    return isFileOrDirectory(szPath, false);
+	return isFileOrDirectory(szPath, false);
 }
 
 time_t CFileSystem::getFileModifyTime(const char *szPath)
 {
-    char path[SIZE_PATH];
-    getAbsoluteCanonizePath(szPath, path, SIZE_PATH);
+	char path[SIZE_PATH];
+	getAbsoluteCanonizePath(szPath, path, SIZE_PATH);
 
-    if (CHECK_CORRECT_PATH(path))
-    {
-        return 0;
-    }
+	if(CHECK_CORRECT_PATH(path))
+	{
+		return 0;
+	}
 
-    WIN32_FILE_ATTRIBUTE_DATA lpFileInformation;
+	WIN32_FILE_ATTRIBUTE_DATA lpFileInformation;
 
 	GetFileAttributesExW(CMB2WC(path), GetFileExInfoStandard, &lpFileInformation);
 
@@ -354,10 +351,10 @@ IFileIterator *CFileSystem::getFolderList(const char *szPath)
 	Array<String> paths;
 	String basePath(szPath);
 
-	if (!isAbsolutePath(szPath)) 
+	if(!isAbsolutePath(szPath))
 	{
 		getAllvariantsCanonizePath(szPath, paths);
-	} 
+	}
 	else
 	{
 		paths.push_back(szPath);
@@ -368,7 +365,7 @@ IFileIterator *CFileSystem::getFolderList(const char *szPath)
 
 IFileIterator *CFileSystem::getFileList(const char *szPath, const char *szExt)
 {
-	const char *exts[] = { szExt };
+	const char *exts[] = {szExt};
 	return getFileList(szPath, exts, 1);
 }
 
@@ -379,7 +376,7 @@ IFileIterator *CFileSystem::getFileList(const char *szPath, const char **szExts,
 
 IFileIterator *CFileSystem::getFileListRecursive(const char *szPath, const char *szExt)
 {
-	const char *exts[] = { szExt };
+	const char *exts[] = {szExt};
 	return getFileListRecursive(szPath, exts, 1);
 }
 
@@ -390,159 +387,134 @@ IFileIterator *CFileSystem::getFileListRecursive(const char *szPath, const char
 
 bool CFileSystem::createDirectory(const char *szPath)
 {
-    char path[SIZE_PATH];
-    getNormalPath(szPath, path, SIZE_PATH);
-    if(!isAbsolutePath(path))
-    {
-        char szBuf[MAX_PATH];
-        szBuf[0] = 0;
-        strcat(szBuf, m_filePaths[m_writableRoot].c_str());
-        strcat(szBuf, "/");
-        strcat(szBuf, szPath);
-        char *tmp = szBuf;
-        while(*tmp)
-        {
-            if(*tmp == '/')
-            {
-                *tmp = '\\';
-            }
-            ++tmp;
-        }
-        return(SHCreateDirectoryExW(nullptr, CMB2WC(szBuf), nullptr) == NO_ERROR);
-    }
+	char path[SIZE_PATH];
+	getNormalPath(szPath, path, SIZE_PATH);
+	if(!isAbsolutePath(path))
+	{
+		char szBuf[SIZE_PATH];
+		sprintf(szBuf, "%s/%s", m_filePaths[m_writableRoot].c_str(), szPath);
+		char *tmp = szBuf;
+		while(*tmp)
+		{
+			if(*tmp == '/')
+			{
+				*tmp = '\\';
+			}
+			++tmp;
+		}
+		return(SHCreateDirectoryExW(nullptr, CMB2WC(szBuf), nullptr) == NO_ERROR);
+	}
 
 	return(SHCreateDirectoryExW(nullptr, CMB2WC(path), nullptr) == NO_ERROR);
 }
 
 bool CFileSystem::deleteDirectory(const char *szPath)
 {
-    char path[SIZE_PATH];
+	char path[SIZE_PATH];
 	getAbsoluteCanonizePath(szPath, path, SIZE_PATH);
 	getNormalPath(path, path, SIZE_PATH);
 
-    CMB2WC wszPath(path);
-    size_t len = wcslen(wszPath);
-    wchar_t *pBuf = (wchar_t*)alloca(sizeof(wchar_t) * (len + 2));
-    memcpy(pBuf, wszPath, sizeof(wchar_t) * (len + 1));
-    pBuf[len + 1] = 0;
-
-    SHFILEOPSTRUCTW file_op = {
-        NULL,
-        FO_DELETE,
-        pBuf,
-        L"",
-        FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT,
-        false,
-        0,
-        L"" 
-    };
-
-    // Если вернуло не 0, то все плохо
-    return(SHFileOperationW(&file_op) == NO_ERROR);
+	CMB2WC wszPath(path);
+	size_t len = wcslen(wszPath);
+	wchar_t *pBuf = (wchar_t*)alloca(sizeof(wchar_t) * (len + 2));
+	memcpy(pBuf, wszPath, sizeof(wchar_t) * (len + 1));
+	pBuf[len + 1] = 0;
+
+	SHFILEOPSTRUCTW file_op = {
+		NULL,
+		FO_DELETE,
+		pBuf,
+		L"",
+		FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT,
+		false,
+		0,
+		L""
+	};
+
+	// Если вернуло не 0, то все плохо
+	return(SHFileOperationW(&file_op) == NO_ERROR);
 }
 
 IFile *CFileSystem::openFile(const char *szPath, FILE_OPEN_MODE mode = FILE_MODE_READ)
 {
-    //Выходим если режим открытия - не для чтения и нет пути для записи
-    if (m_writableRoot == -1 && mode != FILE_MODE_READ)
-    {
-        return nullptr;
-    }
-
-    //Зарезервированная строка, если вдруг не хватит SIZE_PATH
-    char reserveStr[SIZE_PATH * 2];
-    bool useReserveStr = false;
-
-    char fullPath[SIZE_PATH];
-    getAbsoluteCanonizePath(szPath, fullPath, SIZE_PATH);
-
-    //Если по каким либо причинам нельзя вернуть полный путь - на выход
-    if (CHECK_CORRECT_PATH(fullPath) && mode == FILE_MODE_READ)
-    {
-        return nullptr;
-    }
-
-    IFile *file = new CFile;
-
-    if (mode == FILE_MODE_READ)
-    {
-        //Если открываем только на чтение - то копирование не нужно (следовательно и выделение памяти тоже лишняя операция)
-        if (file->open(fullPath, CORE_FILE_BIN) != 0)
-        {
-            mem_delete(file);
-        }
-        return file;
-    }
-
-    String *newFileName;
-
-    if (CHECK_CORRECT_PATH(fullPath))
-    {
-        newFileName = new String(m_filePaths[m_writableRoot].c_str());
-        *newFileName += '/';
-        *newFileName += szPath;
-
-        getAbsoluteCanonizePath(newFileName->c_str(), fullPath, SIZE_PATH);
-
-        mem_delete(newFileName);
-    }
-
-    bool inRoot = isAbsolutePathInRoot(fullPath);
-
-    //Если путь в корне, и файла не существует - создаем его
-    if (inRoot && !fileExists(fullPath))
-    {
-        size_t len = strlen(fullPath) + 1;
-        char dirName[SIZE_PATH];
-
-        memcpy(dirName, fullPath, len);
-        dirname(dirName);
-        len = strlen(dirName);
-        dirName[len - 1] = '\0';
-        createDirectory(dirName);
-    }
-    //Если путь не в корне и его не существует - на выход
-    else if (!fileExists(fullPath))
-    {
-        mem_delete(file);
-        return nullptr;
-    }
-    //Если путь вне корня - тогда копируем в корень
-    else if (!inRoot)
-    {
-        newFileName = copyFile(fullPath);
-        size_t lenPath = strlen(fullPath) + 1;
-        
-        if (lenPath < newFileName->length())
-        {
-            memcpy(reserveStr, newFileName->c_str(), newFileName->length() + 1);
-            useReserveStr = true;
-        }
-
-        memcpy(fullPath, newFileName->c_str(), newFileName->length() + 1);
-        mem_delete(newFileName);
-    }
-
-    int res = 0;
-
-    //Определяем использован ли дополнительный путь для записи в файловой системе
-    char* correctPath = useReserveStr ? reserveStr : fullPath;
-
-    switch (mode)
-    {
-    case FILE_MODE_WRITE:
-        res = file->create(correctPath, CORE_FILE_BIN);
-        break;
-
-    case FILE_MODE_APPEND:
-        res = file->add(correctPath, CORE_FILE_BIN);
-        break;
-    }
-
-    if (res != 0)
-    {
-        mem_delete(file);
-    }
-
-    return file;
+	//Выходим если режим открытия - не для чтения и нет пути для записи
+	if(m_writableRoot == -1 && mode != FILE_MODE_READ)
+	{
+		return nullptr;
+	}
+
+	char fullPath[SIZE_PATH];
+	getAbsoluteCanonizePath(szPath, fullPath, SIZE_PATH);
+
+	//Если по каким либо причинам нельзя вернуть полный путь - на выход
+	if(CHECK_CORRECT_PATH(fullPath) && mode == FILE_MODE_READ)
+	{
+		return nullptr;
+	}
+
+	IFile *file = new CFile;
+
+	if(mode == FILE_MODE_READ)
+	{
+		//Если открываем только на чтение - то копирование не нужно (следовательно и выделение памяти тоже лишняя операция)
+		if(file->open(fullPath, CORE_FILE_BIN) != 0)
+		{
+			mem_delete(file);
+		}
+		return file;
+	}
+
+	char szNewFileName[SIZE_PATH];
+
+	if(CHECK_CORRECT_PATH(fullPath))
+	{
+		sprintf(szNewFileName, "%s/%s", m_filePaths[m_writableRoot].c_str(), szPath);
+
+		getAbsoluteCanonizePath(szNewFileName, fullPath, SIZE_PATH);
+	}
+
+	bool inRoot = isAbsolutePathInRoot(fullPath);
+
+	//Если путь в корне, и файла не существует - создаем его
+	if(inRoot && !fileExists(fullPath))
+	{
+		char dirName[SIZE_PATH];
+
+		strcpy(dirName, fullPath);
+		dirname(dirName);
+		createDirectory(dirName);
+	}
+	//Если путь не в корне и его не существует - на выход
+	else if(!fileExists(fullPath))
+	{
+		mem_delete(file);
+		return nullptr;
+	}
+	//Если путь вне корня - тогда копируем в корень
+	else if(!inRoot)
+	{
+		copyFile(fullPath, szNewFileName);
+
+		strcpy(fullPath, szNewFileName);
+	}
+
+	int res = 0;
+
+	switch(mode)
+	{
+	case FILE_MODE_WRITE:
+		res = file->create(fullPath, CORE_FILE_BIN);
+		break;
+
+	case FILE_MODE_APPEND:
+		res = file->add(fullPath, CORE_FILE_BIN);
+		break;
+	}
+
+	if(res != 0)
+	{
+		mem_delete(file);
+	}
+
+	return file;
 }
\ No newline at end of file
diff --git a/source/core/FileSystem.h b/source/core/FileSystem.h
index 5bcfcb453..72cece8e5 100644
--- a/source/core/FileSystem.h
+++ b/source/core/FileSystem.h
@@ -43,7 +43,7 @@ See the license in LICENSE
 
 #define MEMCCPY_ERROR(buff) memcpy(buff, "\0", 1);
 
-#define SIZE_PATH 4096
+#define SIZE_PATH 2048
 
 #define INVALID_OR_NULL(handle) ((handle) == NULL || (handle) == INVALID_HANDLE_VALUE)
 
@@ -128,7 +128,7 @@ private:
 
 	bool isAbsolutePath(const char* szPath);
 
-	String *copyFile(const char* szPath);
+	void copyFile(const char* szPath, char *szOut);
 
 	//!корневые пути и приоритет
 	Array<String> m_filePaths;
-- 
GitLab