From 5d9a6f72dca3efd9468ce1f2dee1c55ca0fc92f7 Mon Sep 17 00:00:00 2001 From: nakst <> Date: Tue, 31 Aug 2021 21:01:04 +0100 Subject: [PATCH] introduce ES_PATH_MOVE_ALLOW_COPY_AND_DELETE --- apps/test.cpp | 4 ++++ apps/test.ini | 1 + desktop/desktop.cpp | 2 +- desktop/os.header | 6 ++++-- desktop/syscall.cpp | 11 ++++++++++- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/apps/test.cpp b/apps/test.cpp index 2205491..a74d6ad 100644 --- a/apps/test.cpp +++ b/apps/test.cpp @@ -172,6 +172,10 @@ void InitialiseInstance(EsInstance *instance) { EsMemoryCopy(nullptr, nullptr, 1); }); + EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Move file"), [] (EsInstance *, EsElement *, EsCommand *) { + EsPathMove("0:/A Study in Scarlet.txt", -1, "0:/moved.txt", -1, ES_PATH_MOVE_ALLOW_COPY_AND_DELETE); + }); + EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Announcement 1"), [] (EsInstance *, EsElement *element, EsCommand *) { EsRectangle bounds = EsElementGetWindowBounds(element); EsAnnouncementShow(element->window, ES_FLAGS_DEFAULT, (bounds.l + bounds.r) / 2, (bounds.t + bounds.b) / 2, "Hello, world!", -1); diff --git a/apps/test.ini b/apps/test.ini index cb68016..d72fd7e 100644 --- a/apps/test.ini +++ b/apps/test.ini @@ -2,6 +2,7 @@ name=Test icon=icon_system_software_install use_single_process=1 +permission_all_files=1 [build] source=apps/test.cpp diff --git a/desktop/desktop.cpp b/desktop/desktop.cpp index 155a130..c1879cc 100644 --- a/desktop/desktop.cpp +++ b/desktop/desktop.cpp @@ -1455,7 +1455,7 @@ void ApplicationInstanceCompleteSave(ApplicationInstance *fromInstance) { // TODO What should happen if the old file is deleted, but the new file isn't moved? EsPathDelete(document->path, document->pathBytes); - EsPathMove(document->temporarySavePath, document->temporarySavePathBytes, document->path, document->pathBytes); + EsPathMove(document->temporarySavePath, document->temporarySavePathBytes, document->path, document->pathBytes, ES_PATH_MOVE_ALLOW_COPY_AND_DELETE); // Re-open the read handle. diff --git a/desktop/os.header b/desktop/os.header index 961dd59..be97751 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -727,6 +727,8 @@ define ES_DRAW_BITMAP_BLEND (0) define ES_VOLUME_READ_ONLY (1 << 0) +define ES_PATH_MOVE_ALLOW_COPY_AND_DELETE (1 << 0) // Copy and delete the file if a direct move is not possible. + include desktop/icons.header enum EsFatalError { @@ -1928,7 +1930,7 @@ function EsError EsFileWriteAllFromHandle(EsHandle handle, const void *data, siz function EsError EsFileWriteAllGather(STRING filePath, const void **data, size_t *fileSize, size_t gatherCount); function EsError EsFileWriteAllGatherFromHandle(EsHandle handle, const void **data, size_t *fileSize, size_t gatherCount); function void *EsFileMap(STRING filePath, size_t *fileSize, uint32_t flags); -function EsError EsFileCopy(STRING source, STRING destination, void **copyBuffer); // If you are copying lots of files, you can reuse the temporary copy buffer by storing the output copyBuffer; call EsHeapFree on it after the last copy. +function EsError EsFileCopy(STRING source, STRING destination, void **copyBuffer = nullptr); // If you are copying lots of files, you can reuse the temporary copy buffer by storing the output copyBuffer; call EsHeapFree on it after the last copy. function EsError EsFileControl(EsHandle file, uint32_t flags); function EsFileInformation EsFileOpen(STRING path, uint32_t flags); @@ -1940,7 +1942,7 @@ function EsError EsFileDelete(EsHandle file); function EsError EsPathDelete(STRING path); function size_t EsPathFindUniqueName(char *buffer, size_t originalBytes, size_t bufferBytes); -function EsError EsPathMove(STRING oldPath, STRING newPath); +function EsError EsPathMove(STRING oldPath, STRING newPath, uint32_t flags = ES_FLAGS_DEFAULT); function bool EsPathExists(STRING filePath, EsNodeType *type = ES_NULL); // Returns true if the file/directory exists. function EsError EsPathCreate(STRING filePath, EsNodeType type, bool createLeadingDirectories); function bool EsPathQueryInformation(STRING filePath, EsDirectoryChild *information); diff --git a/desktop/syscall.cpp b/desktop/syscall.cpp index 1137dde..82e1797 100644 --- a/desktop/syscall.cpp +++ b/desktop/syscall.cpp @@ -491,7 +491,7 @@ void *EsFileMap(const char *path, ptrdiff_t pathBytes, size_t *fileSize, uint32_ return base; } -EsError EsPathMove(const char *oldPath, ptrdiff_t oldPathBytes, const char *newPath, ptrdiff_t newPathBytes) { +EsError EsPathMove(const char *oldPath, ptrdiff_t oldPathBytes, const char *newPath, ptrdiff_t newPathBytes, uint32_t flags) { if (oldPathBytes == -1) oldPathBytes = EsCStringLength(oldPath); if (newPathBytes == -1) newPathBytes = EsCStringLength(newPath); @@ -508,6 +508,15 @@ EsError EsPathMove(const char *oldPath, ptrdiff_t oldPathBytes, const char *newP if (error != ES_SUCCESS) { EsHandleClose(node.handle); return error; } error = EsSyscall(ES_SYSCALL_NODE_MOVE, node.handle, directory.handle, (uintptr_t) newPath + s, newPathBytes - s); + + if (error == ES_ERROR_VOLUME_MISMATCH && (flags & ES_PATH_MOVE_ALLOW_COPY_AND_DELETE) && (node.type == ES_NODE_FILE)) { + // The paths are on different file systems, so we cannot directly move the file. + // Instead we need to copy the file to the new path, and then delete the old file. + // TODO Does it matter that this isn't atomic? + error = EsFileCopy(oldPath, oldPathBytes, newPath, newPathBytes); + if (error == ES_SUCCESS) error = EsPathDelete(oldPath, oldPathBytes); + } + EsHandleClose(node.handle); EsHandleClose(directory.handle); return error;