From e5431fa6f5505e385c6f9367260717e9c47dc2ee Mon Sep 17 00:00:00 2001 From: Igor Pavlov <87184205+ip7z@users.noreply.github.com> Date: Fri, 29 Nov 2024 00:00:00 +0000 Subject: 24.09 --- CPP/Windows/FileDir.cpp | 138 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 112 insertions(+), 26 deletions(-) (limited to 'CPP/Windows/FileDir.cpp') diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp index dfeed82..2cb83b2 100644 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp @@ -15,8 +15,9 @@ #include #include -#include "../Common/StringConvert.h" #include "../Common/C_FileIO.h" +#include "../Common/MyBuffer2.h" +#include "../Common/StringConvert.h" #endif #include "FileDir.h" @@ -222,6 +223,8 @@ bool RemoveDir(CFSTR path) } +// When moving a directory, oldFile and newFile must be on the same drive. + bool MyMoveFile(CFSTR oldFile, CFSTR newFile) { #ifndef _UNICODE @@ -250,6 +253,59 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile) return false; } +#if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500 +static DWORD WINAPI CopyProgressRoutine_to_ICopyFileProgress( + LARGE_INTEGER TotalFileSize, // file size + LARGE_INTEGER TotalBytesTransferred, // bytes transferred + LARGE_INTEGER /* StreamSize */, // bytes in stream + LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream + DWORD /* dwStreamNumber */, // current stream + DWORD /* dwCallbackReason */, // callback reason + HANDLE /* hSourceFile */, // handle to source file + HANDLE /* hDestinationFile */, // handle to destination file + LPVOID lpData // from CopyFileEx +) +{ + return ((ICopyFileProgress *)lpData)->CopyFileProgress( + (UInt64)TotalFileSize.QuadPart, + (UInt64)TotalBytesTransferred.QuadPart); +} +#endif + +bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile, + ICopyFileProgress *progress) +{ +#if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500 +#ifndef _UNICODE + if (g_IsNT) +#endif + if (progress) + { + IF_USE_MAIN_PATH_2(oldFile, newFile) + { + if (::MoveFileWithProgressW(fs2us(oldFile), fs2us(newFile), + CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED)) + return true; + if (::GetLastError() == ERROR_REQUEST_ABORTED) + return false; + } + #ifdef Z7_LONG_PATH + if (USE_SUPER_PATH_2) + { + UString d1, d2; + if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2)) + return BOOLToBool(::MoveFileWithProgressW(d1, d2, + CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED)); + } + #endif + return false; + } +#else + UNUSED_VAR(progress) +#endif + return MyMoveFile(oldFile, newFile); +} + #ifndef UNDER_CE #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // Win2000 #define Z7_USE_DYN_CreateHardLink @@ -878,9 +934,9 @@ bool CTempFile::Remove() return !_mustBeDeleted; } -bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) +bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore, + ICopyFileProgress *progress) { - // DWORD attrib = 0; if (deleteDestBefore) { if (NFind::DoesFileExist_Raw(name)) @@ -891,8 +947,8 @@ bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) } } DisableDeleting(); - return MyMoveFile(_path, name); - + // if (!progress) return MyMoveFile(_path, name); + return MyMoveFile_with_Progress(_path, name, progress); /* if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) { @@ -941,34 +997,59 @@ bool RemoveDir(CFSTR path) } -static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile) +static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile, ICopyFileProgress *progress) { - NWindows::NFile::NIO::COutFile outFile; - if (!outFile.Create_NEW(newFile)) - return FALSE; - - NWindows::NFile::NIO::CInFile inFile; - if (!inFile.Open(oldFile)) - return FALSE; - - char buf[1 << 14]; - - for (;;) { - const ssize_t num = inFile.read_part(buf, sizeof(buf)); - if (num == 0) - return TRUE; - if (num < 0) + NIO::COutFile outFile; + if (!outFile.Create_NEW(newFile)) return FALSE; - size_t processed; - const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed); - if (num2 != num || processed != (size_t)num) + NIO::CInFile inFile; + if (!inFile.Open(oldFile)) return FALSE; + + const size_t k_BufSize = 1 << 16; + CAlignedBuffer1 buf(k_BufSize); + + UInt64 length = 0; + if (progress && !inFile.GetLength(length)) + length = 0; + UInt64 prev = 0; + UInt64 cur = 0; + for (;;) + { + const ssize_t num = inFile.read_part(buf, k_BufSize); + if (num == 0) + return TRUE; + if (num < 0) + break; + size_t processed; + const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed); + if (num2 != num || processed != (size_t)num) + break; + cur += (size_t)num2; + if (progress && cur - prev >= (1u << 20)) + { + prev = cur; + if (progress->CopyFileProgress(length, cur) != PROGRESS_CONTINUE) + { + errno = EINTR; // instead of WIN32::ERROR_REQUEST_ABORTED + break; + } + } + } } + // There is file IO error or process was interrupted by user. + // We close output file and delete it. + // DeleteFileAlways doesn't change errno (if successed), but we restore errno. + const int errno_save = errno; + DeleteFileAlways(newFile); + errno = errno_save; + return FALSE; } -bool MyMoveFile(CFSTR oldFile, CFSTR newFile) +bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile, + ICopyFileProgress *progress) { int res = rename(oldFile, newFile); if (res == 0) @@ -976,7 +1057,7 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile) if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem) return false; - if (My_CopyFile(oldFile, newFile) == FALSE) + if (My_CopyFile(oldFile, newFile, progress) == FALSE) return false; struct stat info_file; @@ -990,6 +1071,11 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile) return (unlink(oldFile) == 0); } +bool MyMoveFile(CFSTR oldFile, CFSTR newFile) +{ + return MyMoveFile_with_Progress(oldFile, newFile, NULL); +} + bool CreateDir(CFSTR path) { -- cgit v1.2.3-55-g6feb