diff options
Diffstat (limited to 'CPP/Windows/FileDir.cpp')
-rw-r--r-- | CPP/Windows/FileDir.cpp | 138 |
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 | |||
225 | bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | 228 | bool 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 | ||
257 | static 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 | |||
275 | bool 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 | ||
881 | bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) | 937 | bool 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 | ||
944 | static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile) | 1000 | static 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 | ||
971 | bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | 1051 | bool 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 | ||
1074 | bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | ||
1075 | { | ||
1076 | return MyMoveFile_with_Progress(oldFile, newFile, NULL); | ||
1077 | } | ||
1078 | |||
993 | 1079 | ||
994 | bool CreateDir(CFSTR path) | 1080 | bool CreateDir(CFSTR path) |
995 | { | 1081 | { |