diff options
| author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2024-11-29 00:00:00 +0000 |
|---|---|---|
| committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2024-11-30 15:27:15 +0500 |
| commit | e5431fa6f5505e385c6f9367260717e9c47dc2ee (patch) | |
| tree | 4cd2c2c3b225b48c8e7053432c41d7b6b6a3d5f8 /CPP/Windows/FileDir.cpp | |
| parent | e008ce3976c087bfd21344af8f00a23cf69d4174 (diff) | |
| download | 7zip-e5431fa6f5505e385c6f9367260717e9c47dc2ee.tar.gz 7zip-e5431fa6f5505e385c6f9367260717e9c47dc2ee.tar.bz2 7zip-e5431fa6f5505e385c6f9367260717e9c47dc2ee.zip | |
24.0924.09
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 | { |
