Skip to content

Commit af38f62

Browse files
author
Oleh Kulykov
committed
1734082768
1 parent f3b8d6c commit af38f62

File tree

6 files changed

+172
-45
lines changed

6 files changed

+172
-45
lines changed

src/CPP/7zip/Archive/XzHandler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,3 +1438,9 @@ REGISTER_ARC_IO(
14381438
, NULL)
14391439

14401440
}}
1441+
1442+
#if defined(LIBPLZMA_USING_REGISTRATORS)
1443+
uint64_t plzma_registrator_16(void) {
1444+
return NArchive::NXz::g_ArcInfo.Flags;
1445+
}
1446+
#endif

src/CPP/Windows/FileDir.cpp

Lines changed: 112 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
#include <sys/stat.h>
1616
#include <sys/types.h>
1717

18-
#include "../Common/StringConvert.h"
1918
// Empty header
2019
#if !defined(LIBPLZMA)
2120
#include "../Common/C_FileIO.h"
2221
#endif // LIBPLZMA
22+
#include "../Common/MyBuffer2.h"
23+
#include "../Common/StringConvert.h"
2324
#endif
2425

2526
#include "FileDir.h"
@@ -225,6 +226,8 @@ bool RemoveDir(CFSTR path)
225226
}
226227

227228

229+
// When moving a directory, oldFile and newFile must be on the same drive.
230+
228231
bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
229232
{
230233
#ifndef _UNICODE
@@ -253,6 +256,59 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
253256
return false;
254257
}
255258

259+
#if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500
260+
static DWORD WINAPI CopyProgressRoutine_to_ICopyFileProgress(
261+
LARGE_INTEGER TotalFileSize, // file size
262+
LARGE_INTEGER TotalBytesTransferred, // bytes transferred
263+
LARGE_INTEGER /* StreamSize */, // bytes in stream
264+
LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream
265+
DWORD /* dwStreamNumber */, // current stream
266+
DWORD /* dwCallbackReason */, // callback reason
267+
HANDLE /* hSourceFile */, // handle to source file
268+
HANDLE /* hDestinationFile */, // handle to destination file
269+
LPVOID lpData // from CopyFileEx
270+
)
271+
{
272+
return ((ICopyFileProgress *)lpData)->CopyFileProgress(
273+
(UInt64)TotalFileSize.QuadPart,
274+
(UInt64)TotalBytesTransferred.QuadPart);
275+
}
276+
#endif
277+
278+
bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile,
279+
ICopyFileProgress *progress)
280+
{
281+
#if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500
282+
#ifndef _UNICODE
283+
if (g_IsNT)
284+
#endif
285+
if (progress)
286+
{
287+
IF_USE_MAIN_PATH_2(oldFile, newFile)
288+
{
289+
if (::MoveFileWithProgressW(fs2us(oldFile), fs2us(newFile),
290+
CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED))
291+
return true;
292+
if (::GetLastError() == ERROR_REQUEST_ABORTED)
293+
return false;
294+
}
295+
#ifdef Z7_LONG_PATH
296+
if (USE_SUPER_PATH_2)
297+
{
298+
UString d1, d2;
299+
if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2))
300+
return BOOLToBool(::MoveFileWithProgressW(d1, d2,
301+
CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED));
302+
}
303+
#endif
304+
return false;
305+
}
306+
#else
307+
UNUSED_VAR(progress)
308+
#endif
309+
return MyMoveFile(oldFile, newFile);
310+
}
311+
256312
#ifndef UNDER_CE
257313
#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // Win2000
258314
#define Z7_USE_DYN_CreateHardLink
@@ -881,9 +937,9 @@ bool CTempFile::Remove()
881937
return !_mustBeDeleted;
882938
}
883939

884-
bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore)
940+
bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore,
941+
ICopyFileProgress *progress)
885942
{
886-
// DWORD attrib = 0;
887943
if (deleteDestBefore)
888944
{
889945
if (NFind::DoesFileExist_Raw(name))
@@ -894,8 +950,8 @@ bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore)
894950
}
895951
}
896952
DisableDeleting();
897-
return MyMoveFile(_path, name);
898-
953+
// if (!progress) return MyMoveFile(_path, name);
954+
return MyMoveFile_with_Progress(_path, name, progress);
899955
/*
900956
if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))
901957
{
@@ -944,42 +1000,67 @@ bool RemoveDir(CFSTR path)
9441000
}
9451001

9461002

947-
static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile)
1003+
static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile, ICopyFileProgress *progress)
9481004
{
949-
NWindows::NFile::NIO::COutFile outFile;
950-
if (!outFile.Create_NEW(newFile))
951-
return FALSE;
952-
953-
NWindows::NFile::NIO::CInFile inFile;
954-
if (!inFile.Open(oldFile))
955-
return FALSE;
956-
957-
char buf[1 << 14];
958-
959-
for (;;)
9601005
{
961-
const ssize_t num = inFile.read_part(buf, sizeof(buf));
962-
if (num == 0)
963-
return TRUE;
964-
if (num < 0)
1006+
NIO::COutFile outFile;
1007+
if (!outFile.Create_NEW(newFile))
9651008
return FALSE;
966-
size_t processed;
967-
const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed);
968-
if (num2 != num || processed != (size_t)num)
1009+
NIO::CInFile inFile;
1010+
if (!inFile.Open(oldFile))
9691011
return FALSE;
1012+
1013+
const size_t k_BufSize = 1 << 16;
1014+
CAlignedBuffer1 buf(k_BufSize);
1015+
1016+
UInt64 length = 0;
1017+
if (progress && !inFile.GetLength(length))
1018+
length = 0;
1019+
UInt64 prev = 0;
1020+
UInt64 cur = 0;
1021+
for (;;)
1022+
{
1023+
const ssize_t num = inFile.read_part(buf, k_BufSize);
1024+
if (num == 0)
1025+
return TRUE;
1026+
if (num < 0)
1027+
break;
1028+
size_t processed;
1029+
const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed);
1030+
if (num2 != num || processed != (size_t)num)
1031+
break;
1032+
cur += (size_t)num2;
1033+
if (progress && cur - prev >= (1u << 20))
1034+
{
1035+
prev = cur;
1036+
if (progress->CopyFileProgress(length, cur) != PROGRESS_CONTINUE)
1037+
{
1038+
errno = EINTR; // instead of WIN32::ERROR_REQUEST_ABORTED
1039+
break;
1040+
}
1041+
}
1042+
}
9701043
}
1044+
// There is file IO error or process was interrupted by user.
1045+
// We close output file and delete it.
1046+
// DeleteFileAlways doesn't change errno (if successed), but we restore errno.
1047+
const int errno_save = errno;
1048+
DeleteFileAlways(newFile);
1049+
errno = errno_save;
1050+
return FALSE;
9711051
}
9721052

9731053

974-
bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
1054+
bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile,
1055+
ICopyFileProgress *progress)
9751056
{
9761057
int res = rename(oldFile, newFile);
9771058
if (res == 0)
9781059
return true;
9791060
if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem)
9801061
return false;
9811062

982-
if (My_CopyFile(oldFile, newFile) == FALSE)
1063+
if (My_CopyFile(oldFile, newFile, progress) == FALSE)
9831064
return false;
9841065

9851066
struct stat info_file;
@@ -993,6 +1074,11 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
9931074
return (unlink(oldFile) == 0);
9941075
}
9951076

1077+
bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
1078+
{
1079+
return MyMoveFile_with_Progress(oldFile, newFile, NULL);
1080+
}
1081+
9961082

9971083
bool CreateDir(CFSTR path)
9981084
{

src/CPP/Windows/FileDir.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,26 @@ int my_chown(CFSTR path, uid_t owner, gid_t group);
4242
bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib);
4343
#endif // !LIBPLZMA
4444

45+
#ifndef _WIN32
46+
#define PROGRESS_CONTINUE 0
47+
#define PROGRESS_CANCEL 1
48+
// #define PROGRESS_STOP 2
49+
// #define PROGRESS_QUIET 3
50+
#endif
51+
Z7_PURE_INTERFACES_BEGIN
52+
DECLARE_INTERFACE(ICopyFileProgress)
53+
{
54+
// in: total, current: include all/processed alt streams.
55+
// it returns PROGRESS_CONTINUE or PROGRESS_CANCEL.
56+
virtual DWORD CopyFileProgress(UInt64 total, UInt64 current) = 0;
57+
};
58+
Z7_PURE_INTERFACES_END
4559

4660
bool MyMoveFile(CFSTR existFileName, CFSTR newFileName);
61+
// (progress == NULL) is allowed
62+
bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile,
63+
ICopyFileProgress *progress);
64+
4765

4866
#ifndef UNDER_CE
4967
#if !defined(LIBPLZMA)
@@ -91,7 +109,9 @@ class CTempFile Z7_final MY_UNCOPYABLE
91109
bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix
92110
bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile);
93111
bool Remove();
94-
bool MoveTo(CFSTR name, bool deleteDestBefore);
112+
// bool MoveTo(CFSTR name, bool deleteDestBefore);
113+
bool MoveTo(CFSTR name, bool deleteDestBefore,
114+
ICopyFileProgress *progress);
95115
};
96116

97117

src/CPP/Windows/FileName.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,12 +278,14 @@ bool IsAbsolutePath(const wchar_t *s) throw()
278278
int FindAltStreamColon(CFSTR path) throw()
279279
{
280280
unsigned i = 0;
281-
if (IsDrivePath2(path))
282-
i = 2;
281+
if (IsSuperPath(path))
282+
i = kSuperPathPrefixSize;
283+
if (IsDrivePath2(path + i))
284+
i += 2;
283285
int colonPos = -1;
284286
for (;; i++)
285287
{
286-
FChar c = path[i];
288+
const FChar c = path[i];
287289
if (c == 0)
288290
return colonPos;
289291
if (c == ':')

src/CPP/Windows/System.cpp

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ typedef BOOL (WINAPI *Func_GlobalMemoryStatusEx)(MY_LPMEMORYSTATUSEX lpBuffer);
142142
#endif // !UNDER_CE
143143

144144

145-
bool GetRamSize(UInt64 &size)
145+
bool GetRamSize(size_t &size)
146146
{
147-
size = (UInt64)(sizeof(size_t)) << 29;
147+
size = (size_t)sizeof(size_t) << 29;
148148

149149
#ifndef UNDER_CE
150150
MY_MEMORYSTATUSEX stat;
@@ -167,11 +167,23 @@ bool GetRamSize(UInt64 &size)
167167
"GlobalMemoryStatusEx");
168168
if (fn && fn(&stat))
169169
{
170-
size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);
170+
// (MY_MEMORYSTATUSEX::ullTotalVirtual) < 4 GiB in 32-bit mode
171+
size_t size2 = (size_t)0 - 1;
172+
if (size2 > stat.ullTotalPhys)
173+
size2 = (size_t)stat.ullTotalPhys;
174+
if (size2 > stat.ullTotalVirtual)
175+
size2 = (size_t)stat.ullTotalVirtual;
176+
size = size2;
171177
return true;
172178
}
173179
#endif
174180

181+
// On computers with more than 4 GB of memory:
182+
// new docs : GlobalMemoryStatus can report (-1) value to indicate an overflow.
183+
// some old docs : GlobalMemoryStatus can report (modulo 4 GiB) value.
184+
// (for example, if 5 GB total memory, it could report 1 GB).
185+
// We don't want to get (modulo 4 GiB) value.
186+
// So we use GlobalMemoryStatusEx() instead.
175187
{
176188
MEMORYSTATUS stat2;
177189
stat2.dwLength = sizeof(stat2);
@@ -187,9 +199,11 @@ bool GetRamSize(UInt64 &size)
187199
// POSIX
188200
// #include <stdio.h>
189201

190-
bool GetRamSize(UInt64 &size)
202+
bool GetRamSize(size_t &size)
191203
{
192-
size = (UInt64)(sizeof(size_t)) << 29;
204+
UInt64 size64;
205+
size = (size_t)sizeof(size_t) << 29;
206+
size64 = size;
193207

194208
#if defined(__APPLE__) || defined(__DragonFly__) || \
195209
defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
@@ -215,20 +229,20 @@ bool GetRamSize(UInt64 &size)
215229
// we use strict check (size_sys == sizeof(val)) for returned value
216230
// because big-endian encoding is possible:
217231
if (res == 0 && size_sys == sizeof(val) && val)
218-
size = val;
232+
size64 = val;
219233
else
220234
{
221235
uint32_t val32 = 0;
222236
size_sys = sizeof(val32);
223237
res = sysctl(mib, 2, &val32, &size_sys, NULL, 0);
224238
// printf("\n sysctl res=%d val=%llx size_sys = %d, %d\n", res, (long long int)val32, (int)size_sys, errno);
225239
if (res == 0 && size_sys == sizeof(val32) && val32)
226-
size = val32;
240+
size64 = val32;
227241
}
228242

229243
#elif defined(_AIX)
230244
#if defined(_SC_AIX_REALMEM) // AIX
231-
size = (UInt64)sysconf(_SC_AIX_REALMEM) * 1024;
245+
size64 = (UInt64)sysconf(_SC_AIX_REALMEM) * 1024;
232246
#endif
233247
#elif 0 || defined(__sun)
234248
#if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
@@ -240,7 +254,7 @@ bool GetRamSize(UInt64 &size)
240254
// printf("\n_SC_PHYS_PAGES (hex) = %lx", (unsigned long)phys_pages);
241255
// printf("\n_SC_PAGESIZE = %lu\n", (unsigned long)page_size);
242256
if (phys_pages != -1 && page_size != -1)
243-
size = (UInt64)(Int64)phys_pages * (UInt64)(Int64)page_size;
257+
size64 = (UInt64)(Int64)phys_pages * (UInt64)(Int64)page_size;
244258
}
245259
#endif
246260
#elif defined(__gnu_hurd__)
@@ -253,7 +267,7 @@ bool GetRamSize(UInt64 &size)
253267
struct sysinfo info;
254268
if (::sysinfo(&info) != 0)
255269
return false;
256-
size = (UInt64)info.mem_unit * info.totalram;
270+
size64 = (UInt64)info.mem_unit * info.totalram;
257271
/*
258272
printf("\n mem_unit = %lld", (UInt64)info.mem_unit);
259273
printf("\n totalram = %lld", (UInt64)info.totalram);
@@ -262,10 +276,9 @@ bool GetRamSize(UInt64 &size)
262276

263277
#endif
264278

265-
const UInt64 kLimit = (UInt64)1 << (sizeof(size_t) * 8 - 1);
266-
if (size > kLimit)
267-
size = kLimit;
268-
279+
size = (size_t)1 << (sizeof(size_t) * 8 - 1);
280+
if (size > size64)
281+
size = (size_t)size64;
269282
return true;
270283
}
271284

src/CPP/Windows/System.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ struct CProcessAffinity Z7_final
122122

123123
UInt32 GetNumberOfProcessors();
124124

125-
bool GetRamSize(UInt64 &size); // returns false, if unknown ram size
125+
bool GetRamSize(size_t &size); // returns false, if unknown ram size
126126

127127
unsigned long Get_File_OPEN_MAX();
128128
unsigned Get_File_OPEN_MAX_Reduced_for_3_tasks();

0 commit comments

Comments
 (0)