aboutsummaryrefslogtreecommitdiff
path: root/CPP/Windows/FileDir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/Windows/FileDir.cpp')
-rw-r--r--CPP/Windows/FileDir.cpp138
1 files changed, 112 insertions, 26 deletions
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 @@
15#include <sys/stat.h> 15#include <sys/stat.h>
16#include <sys/types.h> 16#include <sys/types.h>
17 17
18#include "../Common/StringConvert.h"
19#include "../Common/C_FileIO.h" 18#include "../Common/C_FileIO.h"
19#include "../Common/MyBuffer2.h"
20#include "../Common/StringConvert.h"
20#endif 21#endif
21 22
22#include "FileDir.h" 23#include "FileDir.h"
@@ -222,6 +223,8 @@ bool RemoveDir(CFSTR path)
222} 223}
223 224
224 225
226// When moving a directory, oldFile and newFile must be on the same drive.
227
225bool MyMoveFile(CFSTR oldFile, CFSTR newFile) 228bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
226{ 229{
227 #ifndef _UNICODE 230 #ifndef _UNICODE
@@ -250,6 +253,59 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
250 return false; 253 return false;
251} 254}
252 255
256#if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500
257static DWORD WINAPI CopyProgressRoutine_to_ICopyFileProgress(
258 LARGE_INTEGER TotalFileSize, // file size
259 LARGE_INTEGER TotalBytesTransferred, // bytes transferred
260 LARGE_INTEGER /* StreamSize */, // bytes in stream
261 LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream
262 DWORD /* dwStreamNumber */, // current stream
263 DWORD /* dwCallbackReason */, // callback reason
264 HANDLE /* hSourceFile */, // handle to source file
265 HANDLE /* hDestinationFile */, // handle to destination file
266 LPVOID lpData // from CopyFileEx
267)
268{
269 return ((ICopyFileProgress *)lpData)->CopyFileProgress(
270 (UInt64)TotalFileSize.QuadPart,
271 (UInt64)TotalBytesTransferred.QuadPart);
272}
273#endif
274
275bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile,
276 ICopyFileProgress *progress)
277{
278#if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500
279#ifndef _UNICODE
280 if (g_IsNT)
281#endif
282 if (progress)
283 {
284 IF_USE_MAIN_PATH_2(oldFile, newFile)
285 {
286 if (::MoveFileWithProgressW(fs2us(oldFile), fs2us(newFile),
287 CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED))
288 return true;
289 if (::GetLastError() == ERROR_REQUEST_ABORTED)
290 return false;
291 }
292 #ifdef Z7_LONG_PATH
293 if (USE_SUPER_PATH_2)
294 {
295 UString d1, d2;
296 if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2))
297 return BOOLToBool(::MoveFileWithProgressW(d1, d2,
298 CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED));
299 }
300 #endif
301 return false;
302 }
303#else
304 UNUSED_VAR(progress)
305#endif
306 return MyMoveFile(oldFile, newFile);
307}
308
253#ifndef UNDER_CE 309#ifndef UNDER_CE
254#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // Win2000 310#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // Win2000
255#define Z7_USE_DYN_CreateHardLink 311#define Z7_USE_DYN_CreateHardLink
@@ -878,9 +934,9 @@ bool CTempFile::Remove()
878 return !_mustBeDeleted; 934 return !_mustBeDeleted;
879} 935}
880 936
881bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) 937bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore,
938 ICopyFileProgress *progress)
882{ 939{
883 // DWORD attrib = 0;
884 if (deleteDestBefore) 940 if (deleteDestBefore)
885 { 941 {
886 if (NFind::DoesFileExist_Raw(name)) 942 if (NFind::DoesFileExist_Raw(name))
@@ -891,8 +947,8 @@ bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore)
891 } 947 }
892 } 948 }
893 DisableDeleting(); 949 DisableDeleting();
894 return MyMoveFile(_path, name); 950 // if (!progress) return MyMoveFile(_path, name);
895 951 return MyMoveFile_with_Progress(_path, name, progress);
896 /* 952 /*
897 if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) 953 if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))
898 { 954 {
@@ -941,34 +997,59 @@ bool RemoveDir(CFSTR path)
941} 997}
942 998
943 999
944static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile) 1000static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile, ICopyFileProgress *progress)
945{ 1001{
946 NWindows::NFile::NIO::COutFile outFile;
947 if (!outFile.Create_NEW(newFile))
948 return FALSE;
949
950 NWindows::NFile::NIO::CInFile inFile;
951 if (!inFile.Open(oldFile))
952 return FALSE;
953
954 char buf[1 << 14];
955
956 for (;;)
957 { 1002 {
958 const ssize_t num = inFile.read_part(buf, sizeof(buf)); 1003 NIO::COutFile outFile;
959 if (num == 0) 1004 if (!outFile.Create_NEW(newFile))
960 return TRUE;
961 if (num < 0)
962 return FALSE; 1005 return FALSE;
963 size_t processed; 1006 NIO::CInFile inFile;
964 const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed); 1007 if (!inFile.Open(oldFile))
965 if (num2 != num || processed != (size_t)num)
966 return FALSE; 1008 return FALSE;
1009
1010 const size_t k_BufSize = 1 << 16;
1011 CAlignedBuffer1 buf(k_BufSize);
1012
1013 UInt64 length = 0;
1014 if (progress && !inFile.GetLength(length))
1015 length = 0;
1016 UInt64 prev = 0;
1017 UInt64 cur = 0;
1018 for (;;)
1019 {
1020 const ssize_t num = inFile.read_part(buf, k_BufSize);
1021 if (num == 0)
1022 return TRUE;
1023 if (num < 0)
1024 break;
1025 size_t processed;
1026 const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed);
1027 if (num2 != num || processed != (size_t)num)
1028 break;
1029 cur += (size_t)num2;
1030 if (progress && cur - prev >= (1u << 20))
1031 {
1032 prev = cur;
1033 if (progress->CopyFileProgress(length, cur) != PROGRESS_CONTINUE)
1034 {
1035 errno = EINTR; // instead of WIN32::ERROR_REQUEST_ABORTED
1036 break;
1037 }
1038 }
1039 }
967 } 1040 }
1041 // There is file IO error or process was interrupted by user.
1042 // We close output file and delete it.
1043 // DeleteFileAlways doesn't change errno (if successed), but we restore errno.
1044 const int errno_save = errno;
1045 DeleteFileAlways(newFile);
1046 errno = errno_save;
1047 return FALSE;
968} 1048}
969 1049
970 1050
971bool MyMoveFile(CFSTR oldFile, CFSTR newFile) 1051bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile,
1052 ICopyFileProgress *progress)
972{ 1053{
973 int res = rename(oldFile, newFile); 1054 int res = rename(oldFile, newFile);
974 if (res == 0) 1055 if (res == 0)
@@ -976,7 +1057,7 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
976 if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem) 1057 if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem)
977 return false; 1058 return false;
978 1059
979 if (My_CopyFile(oldFile, newFile) == FALSE) 1060 if (My_CopyFile(oldFile, newFile, progress) == FALSE)
980 return false; 1061 return false;
981 1062
982 struct stat info_file; 1063 struct stat info_file;
@@ -990,6 +1071,11 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
990 return (unlink(oldFile) == 0); 1071 return (unlink(oldFile) == 0);
991} 1072}
992 1073
1074bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
1075{
1076 return MyMoveFile_with_Progress(oldFile, newFile, NULL);
1077}
1078
993 1079
994bool CreateDir(CFSTR path) 1080bool CreateDir(CFSTR path)
995{ 1081{