xref: /aosp_15_r20/external/lzma/CPP/Windows/FileDir.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Windows/FileDir.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker 
6*f6dc9357SAndroid Build Coastguard Worker #ifndef _WIN32
7*f6dc9357SAndroid Build Coastguard Worker #include <stdio.h>
8*f6dc9357SAndroid Build Coastguard Worker #include <stdlib.h>
9*f6dc9357SAndroid Build Coastguard Worker #include <errno.h>
10*f6dc9357SAndroid Build Coastguard Worker #include <limits.h>
11*f6dc9357SAndroid Build Coastguard Worker #include <unistd.h>
12*f6dc9357SAndroid Build Coastguard Worker #include <time.h>
13*f6dc9357SAndroid Build Coastguard Worker #include <utime.h>
14*f6dc9357SAndroid Build Coastguard Worker #include <fcntl.h>
15*f6dc9357SAndroid Build Coastguard Worker #include <sys/stat.h>
16*f6dc9357SAndroid Build Coastguard Worker #include <sys/types.h>
17*f6dc9357SAndroid Build Coastguard Worker 
18*f6dc9357SAndroid Build Coastguard Worker #include "../Common/C_FileIO.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../Common/MyBuffer2.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StringConvert.h"
21*f6dc9357SAndroid Build Coastguard Worker #endif
22*f6dc9357SAndroid Build Coastguard Worker 
23*f6dc9357SAndroid Build Coastguard Worker #include "FileDir.h"
24*f6dc9357SAndroid Build Coastguard Worker #include "FileFind.h"
25*f6dc9357SAndroid Build Coastguard Worker #include "FileName.h"
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
28*f6dc9357SAndroid Build Coastguard Worker extern bool g_IsNT;
29*f6dc9357SAndroid Build Coastguard Worker #endif
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
32*f6dc9357SAndroid Build Coastguard Worker using namespace NFile;
33*f6dc9357SAndroid Build Coastguard Worker using namespace NName;
34*f6dc9357SAndroid Build Coastguard Worker 
35*f6dc9357SAndroid Build Coastguard Worker #ifndef _WIN32
36*f6dc9357SAndroid Build Coastguard Worker 
FiTime_To_timespec(const CFiTime * ft,timespec & ts)37*f6dc9357SAndroid Build Coastguard Worker static bool FiTime_To_timespec(const CFiTime *ft, timespec &ts)
38*f6dc9357SAndroid Build Coastguard Worker {
39*f6dc9357SAndroid Build Coastguard Worker   if (ft)
40*f6dc9357SAndroid Build Coastguard Worker   {
41*f6dc9357SAndroid Build Coastguard Worker #if defined(_AIX)
42*f6dc9357SAndroid Build Coastguard Worker     ts.tv_sec  = ft->tv_sec;
43*f6dc9357SAndroid Build Coastguard Worker     ts.tv_nsec = ft->tv_nsec;
44*f6dc9357SAndroid Build Coastguard Worker #else
45*f6dc9357SAndroid Build Coastguard Worker     ts = *ft;
46*f6dc9357SAndroid Build Coastguard Worker #endif
47*f6dc9357SAndroid Build Coastguard Worker     return true;
48*f6dc9357SAndroid Build Coastguard Worker   }
49*f6dc9357SAndroid Build Coastguard Worker   // else
50*f6dc9357SAndroid Build Coastguard Worker   {
51*f6dc9357SAndroid Build Coastguard Worker     ts.tv_sec = 0;
52*f6dc9357SAndroid Build Coastguard Worker     ts.tv_nsec =
53*f6dc9357SAndroid Build Coastguard Worker     #ifdef UTIME_OMIT
54*f6dc9357SAndroid Build Coastguard Worker       UTIME_OMIT; // -2 keep old timesptamp
55*f6dc9357SAndroid Build Coastguard Worker     #else
56*f6dc9357SAndroid Build Coastguard Worker       // UTIME_NOW; -1 // set to the current time
57*f6dc9357SAndroid Build Coastguard Worker       0;
58*f6dc9357SAndroid Build Coastguard Worker     #endif
59*f6dc9357SAndroid Build Coastguard Worker     return false;
60*f6dc9357SAndroid Build Coastguard Worker   }
61*f6dc9357SAndroid Build Coastguard Worker }
62*f6dc9357SAndroid Build Coastguard Worker #endif
63*f6dc9357SAndroid Build Coastguard Worker 
64*f6dc9357SAndroid Build Coastguard Worker namespace NWindows {
65*f6dc9357SAndroid Build Coastguard Worker namespace NFile {
66*f6dc9357SAndroid Build Coastguard Worker namespace NDir {
67*f6dc9357SAndroid Build Coastguard Worker 
68*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
69*f6dc9357SAndroid Build Coastguard Worker 
70*f6dc9357SAndroid Build Coastguard Worker #ifndef UNDER_CE
71*f6dc9357SAndroid Build Coastguard Worker 
GetWindowsDir(FString & path)72*f6dc9357SAndroid Build Coastguard Worker bool GetWindowsDir(FString &path)
73*f6dc9357SAndroid Build Coastguard Worker {
74*f6dc9357SAndroid Build Coastguard Worker   const unsigned kBufSize = MAX_PATH + 16;
75*f6dc9357SAndroid Build Coastguard Worker   UINT len;
76*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
77*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
78*f6dc9357SAndroid Build Coastguard Worker   {
79*f6dc9357SAndroid Build Coastguard Worker     TCHAR s[kBufSize + 1];
80*f6dc9357SAndroid Build Coastguard Worker     s[0] = 0;
81*f6dc9357SAndroid Build Coastguard Worker     len = ::GetWindowsDirectory(s, kBufSize);
82*f6dc9357SAndroid Build Coastguard Worker     path = fas2fs(s);
83*f6dc9357SAndroid Build Coastguard Worker   }
84*f6dc9357SAndroid Build Coastguard Worker   else
85*f6dc9357SAndroid Build Coastguard Worker   #endif
86*f6dc9357SAndroid Build Coastguard Worker   {
87*f6dc9357SAndroid Build Coastguard Worker     WCHAR s[kBufSize + 1];
88*f6dc9357SAndroid Build Coastguard Worker     s[0] = 0;
89*f6dc9357SAndroid Build Coastguard Worker     len = ::GetWindowsDirectoryW(s, kBufSize);
90*f6dc9357SAndroid Build Coastguard Worker     path = us2fs(s);
91*f6dc9357SAndroid Build Coastguard Worker   }
92*f6dc9357SAndroid Build Coastguard Worker   return (len != 0 && len < kBufSize);
93*f6dc9357SAndroid Build Coastguard Worker }
94*f6dc9357SAndroid Build Coastguard Worker 
95*f6dc9357SAndroid Build Coastguard Worker 
96*f6dc9357SAndroid Build Coastguard Worker /*
97*f6dc9357SAndroid Build Coastguard Worker new DOCs for GetSystemDirectory:
98*f6dc9357SAndroid Build Coastguard Worker   returned path does not end with a backslash unless the
99*f6dc9357SAndroid Build Coastguard Worker   system directory is the root directory.
100*f6dc9357SAndroid Build Coastguard Worker */
101*f6dc9357SAndroid Build Coastguard Worker 
GetSystemDir(FString & path)102*f6dc9357SAndroid Build Coastguard Worker bool GetSystemDir(FString &path)
103*f6dc9357SAndroid Build Coastguard Worker {
104*f6dc9357SAndroid Build Coastguard Worker   const unsigned kBufSize = MAX_PATH + 16;
105*f6dc9357SAndroid Build Coastguard Worker   UINT len;
106*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
107*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
108*f6dc9357SAndroid Build Coastguard Worker   {
109*f6dc9357SAndroid Build Coastguard Worker     TCHAR s[kBufSize + 1];
110*f6dc9357SAndroid Build Coastguard Worker     s[0] = 0;
111*f6dc9357SAndroid Build Coastguard Worker     len = ::GetSystemDirectory(s, kBufSize);
112*f6dc9357SAndroid Build Coastguard Worker     path = fas2fs(s);
113*f6dc9357SAndroid Build Coastguard Worker   }
114*f6dc9357SAndroid Build Coastguard Worker   else
115*f6dc9357SAndroid Build Coastguard Worker   #endif
116*f6dc9357SAndroid Build Coastguard Worker   {
117*f6dc9357SAndroid Build Coastguard Worker     WCHAR s[kBufSize + 1];
118*f6dc9357SAndroid Build Coastguard Worker     s[0] = 0;
119*f6dc9357SAndroid Build Coastguard Worker     len = ::GetSystemDirectoryW(s, kBufSize);
120*f6dc9357SAndroid Build Coastguard Worker     path = us2fs(s);
121*f6dc9357SAndroid Build Coastguard Worker   }
122*f6dc9357SAndroid Build Coastguard Worker   return (len != 0 && len < kBufSize);
123*f6dc9357SAndroid Build Coastguard Worker }
124*f6dc9357SAndroid Build Coastguard Worker #endif // UNDER_CE
125*f6dc9357SAndroid Build Coastguard Worker 
126*f6dc9357SAndroid Build Coastguard Worker 
SetDirTime(CFSTR path,const CFiTime * cTime,const CFiTime * aTime,const CFiTime * mTime)127*f6dc9357SAndroid Build Coastguard Worker bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)
128*f6dc9357SAndroid Build Coastguard Worker {
129*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
130*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
131*f6dc9357SAndroid Build Coastguard Worker   {
132*f6dc9357SAndroid Build Coastguard Worker     ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
133*f6dc9357SAndroid Build Coastguard Worker     return false;
134*f6dc9357SAndroid Build Coastguard Worker   }
135*f6dc9357SAndroid Build Coastguard Worker   #endif
136*f6dc9357SAndroid Build Coastguard Worker 
137*f6dc9357SAndroid Build Coastguard Worker   HANDLE hDir = INVALID_HANDLE_VALUE;
138*f6dc9357SAndroid Build Coastguard Worker   IF_USE_MAIN_PATH
139*f6dc9357SAndroid Build Coastguard Worker     hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
140*f6dc9357SAndroid Build Coastguard Worker         NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
141*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_LONG_PATH
142*f6dc9357SAndroid Build Coastguard Worker   if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
143*f6dc9357SAndroid Build Coastguard Worker   {
144*f6dc9357SAndroid Build Coastguard Worker     UString superPath;
145*f6dc9357SAndroid Build Coastguard Worker     if (GetSuperPath(path, superPath, USE_MAIN_PATH))
146*f6dc9357SAndroid Build Coastguard Worker       hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
147*f6dc9357SAndroid Build Coastguard Worker           NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
148*f6dc9357SAndroid Build Coastguard Worker   }
149*f6dc9357SAndroid Build Coastguard Worker   #endif
150*f6dc9357SAndroid Build Coastguard Worker 
151*f6dc9357SAndroid Build Coastguard Worker   bool res = false;
152*f6dc9357SAndroid Build Coastguard Worker   if (hDir != INVALID_HANDLE_VALUE)
153*f6dc9357SAndroid Build Coastguard Worker   {
154*f6dc9357SAndroid Build Coastguard Worker     res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime));
155*f6dc9357SAndroid Build Coastguard Worker     ::CloseHandle(hDir);
156*f6dc9357SAndroid Build Coastguard Worker   }
157*f6dc9357SAndroid Build Coastguard Worker   return res;
158*f6dc9357SAndroid Build Coastguard Worker }
159*f6dc9357SAndroid Build Coastguard Worker 
160*f6dc9357SAndroid Build Coastguard Worker 
161*f6dc9357SAndroid Build Coastguard Worker 
SetFileAttrib(CFSTR path,DWORD attrib)162*f6dc9357SAndroid Build Coastguard Worker bool SetFileAttrib(CFSTR path, DWORD attrib)
163*f6dc9357SAndroid Build Coastguard Worker {
164*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
165*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
166*f6dc9357SAndroid Build Coastguard Worker   {
167*f6dc9357SAndroid Build Coastguard Worker     if (::SetFileAttributes(fs2fas(path), attrib))
168*f6dc9357SAndroid Build Coastguard Worker       return true;
169*f6dc9357SAndroid Build Coastguard Worker   }
170*f6dc9357SAndroid Build Coastguard Worker   else
171*f6dc9357SAndroid Build Coastguard Worker   #endif
172*f6dc9357SAndroid Build Coastguard Worker   {
173*f6dc9357SAndroid Build Coastguard Worker     IF_USE_MAIN_PATH
174*f6dc9357SAndroid Build Coastguard Worker       if (::SetFileAttributesW(fs2us(path), attrib))
175*f6dc9357SAndroid Build Coastguard Worker         return true;
176*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_LONG_PATH
177*f6dc9357SAndroid Build Coastguard Worker     if (USE_SUPER_PATH)
178*f6dc9357SAndroid Build Coastguard Worker     {
179*f6dc9357SAndroid Build Coastguard Worker       UString superPath;
180*f6dc9357SAndroid Build Coastguard Worker       if (GetSuperPath(path, superPath, USE_MAIN_PATH))
181*f6dc9357SAndroid Build Coastguard Worker         return BOOLToBool(::SetFileAttributesW(superPath, attrib));
182*f6dc9357SAndroid Build Coastguard Worker     }
183*f6dc9357SAndroid Build Coastguard Worker     #endif
184*f6dc9357SAndroid Build Coastguard Worker   }
185*f6dc9357SAndroid Build Coastguard Worker   return false;
186*f6dc9357SAndroid Build Coastguard Worker }
187*f6dc9357SAndroid Build Coastguard Worker 
188*f6dc9357SAndroid Build Coastguard Worker 
SetFileAttrib_PosixHighDetect(CFSTR path,DWORD attrib)189*f6dc9357SAndroid Build Coastguard Worker bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
190*f6dc9357SAndroid Build Coastguard Worker {
191*f6dc9357SAndroid Build Coastguard Worker   #ifdef _WIN32
192*f6dc9357SAndroid Build Coastguard Worker   if ((attrib & 0xF0000000) != 0)
193*f6dc9357SAndroid Build Coastguard Worker     attrib &= 0x3FFF;
194*f6dc9357SAndroid Build Coastguard Worker   #endif
195*f6dc9357SAndroid Build Coastguard Worker   return SetFileAttrib(path, attrib);
196*f6dc9357SAndroid Build Coastguard Worker }
197*f6dc9357SAndroid Build Coastguard Worker 
198*f6dc9357SAndroid Build Coastguard Worker 
RemoveDir(CFSTR path)199*f6dc9357SAndroid Build Coastguard Worker bool RemoveDir(CFSTR path)
200*f6dc9357SAndroid Build Coastguard Worker {
201*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
202*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
203*f6dc9357SAndroid Build Coastguard Worker   {
204*f6dc9357SAndroid Build Coastguard Worker     if (::RemoveDirectory(fs2fas(path)))
205*f6dc9357SAndroid Build Coastguard Worker       return true;
206*f6dc9357SAndroid Build Coastguard Worker   }
207*f6dc9357SAndroid Build Coastguard Worker   else
208*f6dc9357SAndroid Build Coastguard Worker   #endif
209*f6dc9357SAndroid Build Coastguard Worker   {
210*f6dc9357SAndroid Build Coastguard Worker     IF_USE_MAIN_PATH
211*f6dc9357SAndroid Build Coastguard Worker       if (::RemoveDirectoryW(fs2us(path)))
212*f6dc9357SAndroid Build Coastguard Worker         return true;
213*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_LONG_PATH
214*f6dc9357SAndroid Build Coastguard Worker     if (USE_SUPER_PATH)
215*f6dc9357SAndroid Build Coastguard Worker     {
216*f6dc9357SAndroid Build Coastguard Worker       UString superPath;
217*f6dc9357SAndroid Build Coastguard Worker       if (GetSuperPath(path, superPath, USE_MAIN_PATH))
218*f6dc9357SAndroid Build Coastguard Worker         return BOOLToBool(::RemoveDirectoryW(superPath));
219*f6dc9357SAndroid Build Coastguard Worker     }
220*f6dc9357SAndroid Build Coastguard Worker     #endif
221*f6dc9357SAndroid Build Coastguard Worker   }
222*f6dc9357SAndroid Build Coastguard Worker   return false;
223*f6dc9357SAndroid Build Coastguard Worker }
224*f6dc9357SAndroid Build Coastguard Worker 
225*f6dc9357SAndroid Build Coastguard Worker 
226*f6dc9357SAndroid Build Coastguard Worker // When moving a directory, oldFile and newFile must be on the same drive.
227*f6dc9357SAndroid Build Coastguard Worker 
MyMoveFile(CFSTR oldFile,CFSTR newFile)228*f6dc9357SAndroid Build Coastguard Worker bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
229*f6dc9357SAndroid Build Coastguard Worker {
230*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
231*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
232*f6dc9357SAndroid Build Coastguard Worker   {
233*f6dc9357SAndroid Build Coastguard Worker     if (::MoveFile(fs2fas(oldFile), fs2fas(newFile)))
234*f6dc9357SAndroid Build Coastguard Worker       return true;
235*f6dc9357SAndroid Build Coastguard Worker   }
236*f6dc9357SAndroid Build Coastguard Worker   else
237*f6dc9357SAndroid Build Coastguard Worker   #endif
238*f6dc9357SAndroid Build Coastguard Worker   {
239*f6dc9357SAndroid Build Coastguard Worker     IF_USE_MAIN_PATH_2(oldFile, newFile)
240*f6dc9357SAndroid Build Coastguard Worker     {
241*f6dc9357SAndroid Build Coastguard Worker       if (::MoveFileW(fs2us(oldFile), fs2us(newFile)))
242*f6dc9357SAndroid Build Coastguard Worker         return true;
243*f6dc9357SAndroid Build Coastguard Worker     }
244*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_LONG_PATH
245*f6dc9357SAndroid Build Coastguard Worker     if (USE_SUPER_PATH_2)
246*f6dc9357SAndroid Build Coastguard Worker     {
247*f6dc9357SAndroid Build Coastguard Worker       UString d1, d2;
248*f6dc9357SAndroid Build Coastguard Worker       if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2))
249*f6dc9357SAndroid Build Coastguard Worker         return BOOLToBool(::MoveFileW(d1, d2));
250*f6dc9357SAndroid Build Coastguard Worker     }
251*f6dc9357SAndroid Build Coastguard Worker     #endif
252*f6dc9357SAndroid Build Coastguard Worker   }
253*f6dc9357SAndroid Build Coastguard Worker   return false;
254*f6dc9357SAndroid Build Coastguard Worker }
255*f6dc9357SAndroid Build Coastguard Worker 
256*f6dc9357SAndroid Build Coastguard Worker #if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500
CopyProgressRoutine_to_ICopyFileProgress(LARGE_INTEGER TotalFileSize,LARGE_INTEGER TotalBytesTransferred,LARGE_INTEGER,LARGE_INTEGER,DWORD,DWORD,HANDLE,HANDLE,LPVOID lpData)257*f6dc9357SAndroid Build Coastguard Worker static DWORD WINAPI CopyProgressRoutine_to_ICopyFileProgress(
258*f6dc9357SAndroid Build Coastguard Worker   LARGE_INTEGER TotalFileSize,          // file size
259*f6dc9357SAndroid Build Coastguard Worker   LARGE_INTEGER TotalBytesTransferred,  // bytes transferred
260*f6dc9357SAndroid Build Coastguard Worker   LARGE_INTEGER /* StreamSize */,             // bytes in stream
261*f6dc9357SAndroid Build Coastguard Worker   LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream
262*f6dc9357SAndroid Build Coastguard Worker   DWORD /* dwStreamNumber */,                 // current stream
263*f6dc9357SAndroid Build Coastguard Worker   DWORD /* dwCallbackReason */,               // callback reason
264*f6dc9357SAndroid Build Coastguard Worker   HANDLE /* hSourceFile */,                   // handle to source file
265*f6dc9357SAndroid Build Coastguard Worker   HANDLE /* hDestinationFile */,              // handle to destination file
266*f6dc9357SAndroid Build Coastguard Worker   LPVOID lpData                         // from CopyFileEx
267*f6dc9357SAndroid Build Coastguard Worker )
268*f6dc9357SAndroid Build Coastguard Worker {
269*f6dc9357SAndroid Build Coastguard Worker   return ((ICopyFileProgress *)lpData)->CopyFileProgress(
270*f6dc9357SAndroid Build Coastguard Worker       (UInt64)TotalFileSize.QuadPart,
271*f6dc9357SAndroid Build Coastguard Worker       (UInt64)TotalBytesTransferred.QuadPart);
272*f6dc9357SAndroid Build Coastguard Worker }
273*f6dc9357SAndroid Build Coastguard Worker #endif
274*f6dc9357SAndroid Build Coastguard Worker 
MyMoveFile_with_Progress(CFSTR oldFile,CFSTR newFile,ICopyFileProgress * progress)275*f6dc9357SAndroid Build Coastguard Worker bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile,
276*f6dc9357SAndroid Build Coastguard Worker     ICopyFileProgress *progress)
277*f6dc9357SAndroid Build Coastguard Worker {
278*f6dc9357SAndroid Build Coastguard Worker #if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500
279*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
280*f6dc9357SAndroid Build Coastguard Worker   if (g_IsNT)
281*f6dc9357SAndroid Build Coastguard Worker #endif
282*f6dc9357SAndroid Build Coastguard Worker   if (progress)
283*f6dc9357SAndroid Build Coastguard Worker   {
284*f6dc9357SAndroid Build Coastguard Worker     IF_USE_MAIN_PATH_2(oldFile, newFile)
285*f6dc9357SAndroid Build Coastguard Worker     {
286*f6dc9357SAndroid Build Coastguard Worker       if (::MoveFileWithProgressW(fs2us(oldFile), fs2us(newFile),
287*f6dc9357SAndroid Build Coastguard Worker           CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED))
288*f6dc9357SAndroid Build Coastguard Worker         return true;
289*f6dc9357SAndroid Build Coastguard Worker       if (::GetLastError() == ERROR_REQUEST_ABORTED)
290*f6dc9357SAndroid Build Coastguard Worker         return false;
291*f6dc9357SAndroid Build Coastguard Worker     }
292*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_LONG_PATH
293*f6dc9357SAndroid Build Coastguard Worker     if (USE_SUPER_PATH_2)
294*f6dc9357SAndroid Build Coastguard Worker     {
295*f6dc9357SAndroid Build Coastguard Worker       UString d1, d2;
296*f6dc9357SAndroid Build Coastguard Worker       if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2))
297*f6dc9357SAndroid Build Coastguard Worker         return BOOLToBool(::MoveFileWithProgressW(d1, d2,
298*f6dc9357SAndroid Build Coastguard Worker             CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED));
299*f6dc9357SAndroid Build Coastguard Worker     }
300*f6dc9357SAndroid Build Coastguard Worker     #endif
301*f6dc9357SAndroid Build Coastguard Worker     return false;
302*f6dc9357SAndroid Build Coastguard Worker   }
303*f6dc9357SAndroid Build Coastguard Worker #else
304*f6dc9357SAndroid Build Coastguard Worker   UNUSED_VAR(progress)
305*f6dc9357SAndroid Build Coastguard Worker #endif
306*f6dc9357SAndroid Build Coastguard Worker   return MyMoveFile(oldFile, newFile);
307*f6dc9357SAndroid Build Coastguard Worker }
308*f6dc9357SAndroid Build Coastguard Worker 
309*f6dc9357SAndroid Build Coastguard Worker #ifndef UNDER_CE
310*f6dc9357SAndroid Build Coastguard Worker #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500  // Win2000
311*f6dc9357SAndroid Build Coastguard Worker #define Z7_USE_DYN_CreateHardLink
312*f6dc9357SAndroid Build Coastguard Worker #endif
313*f6dc9357SAndroid Build Coastguard Worker 
314*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_CreateHardLink
315*f6dc9357SAndroid Build Coastguard Worker EXTERN_C_BEGIN
316*f6dc9357SAndroid Build Coastguard Worker typedef BOOL (WINAPI *Func_CreateHardLinkW)(
317*f6dc9357SAndroid Build Coastguard Worker     LPCWSTR lpFileName,
318*f6dc9357SAndroid Build Coastguard Worker     LPCWSTR lpExistingFileName,
319*f6dc9357SAndroid Build Coastguard Worker     LPSECURITY_ATTRIBUTES lpSecurityAttributes
320*f6dc9357SAndroid Build Coastguard Worker     );
321*f6dc9357SAndroid Build Coastguard Worker EXTERN_C_END
322*f6dc9357SAndroid Build Coastguard Worker #endif
323*f6dc9357SAndroid Build Coastguard Worker #endif // UNDER_CE
324*f6dc9357SAndroid Build Coastguard Worker 
MyCreateHardLink(CFSTR newFileName,CFSTR existFileName)325*f6dc9357SAndroid Build Coastguard Worker bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
326*f6dc9357SAndroid Build Coastguard Worker {
327*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
328*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
329*f6dc9357SAndroid Build Coastguard Worker   {
330*f6dc9357SAndroid Build Coastguard Worker     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
331*f6dc9357SAndroid Build Coastguard Worker     return false;
332*f6dc9357SAndroid Build Coastguard Worker     /*
333*f6dc9357SAndroid Build Coastguard Worker     if (::CreateHardLink(fs2fas(newFileName), fs2fas(existFileName), NULL))
334*f6dc9357SAndroid Build Coastguard Worker       return true;
335*f6dc9357SAndroid Build Coastguard Worker     */
336*f6dc9357SAndroid Build Coastguard Worker   }
337*f6dc9357SAndroid Build Coastguard Worker   else
338*f6dc9357SAndroid Build Coastguard Worker   #endif
339*f6dc9357SAndroid Build Coastguard Worker   {
340*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_CreateHardLink
341*f6dc9357SAndroid Build Coastguard Worker     const
342*f6dc9357SAndroid Build Coastguard Worker     Func_CreateHardLinkW
343*f6dc9357SAndroid Build Coastguard Worker       my_CreateHardLinkW = Z7_GET_PROC_ADDRESS(
344*f6dc9357SAndroid Build Coastguard Worker     Func_CreateHardLinkW, ::GetModuleHandleW(L"kernel32.dll"),
345*f6dc9357SAndroid Build Coastguard Worker         "CreateHardLinkW");
346*f6dc9357SAndroid Build Coastguard Worker     if (!my_CreateHardLinkW)
347*f6dc9357SAndroid Build Coastguard Worker       return false;
348*f6dc9357SAndroid Build Coastguard Worker     #define MY_CreateHardLinkW  my_CreateHardLinkW
349*f6dc9357SAndroid Build Coastguard Worker #else
350*f6dc9357SAndroid Build Coastguard Worker     #define MY_CreateHardLinkW  CreateHardLinkW
351*f6dc9357SAndroid Build Coastguard Worker #endif
352*f6dc9357SAndroid Build Coastguard Worker     IF_USE_MAIN_PATH_2(newFileName, existFileName)
353*f6dc9357SAndroid Build Coastguard Worker     {
354*f6dc9357SAndroid Build Coastguard Worker       if (MY_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL))
355*f6dc9357SAndroid Build Coastguard Worker         return true;
356*f6dc9357SAndroid Build Coastguard Worker     }
357*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_LONG_PATH
358*f6dc9357SAndroid Build Coastguard Worker     if (USE_SUPER_PATH_2)
359*f6dc9357SAndroid Build Coastguard Worker     {
360*f6dc9357SAndroid Build Coastguard Worker       UString d1, d2;
361*f6dc9357SAndroid Build Coastguard Worker       if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2))
362*f6dc9357SAndroid Build Coastguard Worker         return BOOLToBool(MY_CreateHardLinkW(d1, d2, NULL));
363*f6dc9357SAndroid Build Coastguard Worker     }
364*f6dc9357SAndroid Build Coastguard Worker     #endif
365*f6dc9357SAndroid Build Coastguard Worker   }
366*f6dc9357SAndroid Build Coastguard Worker   return false;
367*f6dc9357SAndroid Build Coastguard Worker }
368*f6dc9357SAndroid Build Coastguard Worker 
369*f6dc9357SAndroid Build Coastguard Worker 
370*f6dc9357SAndroid Build Coastguard Worker /*
371*f6dc9357SAndroid Build Coastguard Worker WinXP-64 CreateDir():
372*f6dc9357SAndroid Build Coastguard Worker   ""                  - ERROR_PATH_NOT_FOUND
373*f6dc9357SAndroid Build Coastguard Worker   \                   - ERROR_ACCESS_DENIED
374*f6dc9357SAndroid Build Coastguard Worker   C:\                 - ERROR_ACCESS_DENIED, if there is such drive,
375*f6dc9357SAndroid Build Coastguard Worker 
376*f6dc9357SAndroid Build Coastguard Worker   D:\folder             - ERROR_PATH_NOT_FOUND, if there is no such drive,
377*f6dc9357SAndroid Build Coastguard Worker   C:\nonExistent\folder - ERROR_PATH_NOT_FOUND
378*f6dc9357SAndroid Build Coastguard Worker 
379*f6dc9357SAndroid Build Coastguard Worker   C:\existFolder      - ERROR_ALREADY_EXISTS
380*f6dc9357SAndroid Build Coastguard Worker   C:\existFolder\     - ERROR_ALREADY_EXISTS
381*f6dc9357SAndroid Build Coastguard Worker 
382*f6dc9357SAndroid Build Coastguard Worker   C:\folder   - OK
383*f6dc9357SAndroid Build Coastguard Worker   C:\folder\  - OK
384*f6dc9357SAndroid Build Coastguard Worker 
385*f6dc9357SAndroid Build Coastguard Worker   \\Server\nonExistent    - ERROR_BAD_NETPATH
386*f6dc9357SAndroid Build Coastguard Worker   \\Server\Share_Readonly - ERROR_ACCESS_DENIED
387*f6dc9357SAndroid Build Coastguard Worker   \\Server\Share          - ERROR_ALREADY_EXISTS
388*f6dc9357SAndroid Build Coastguard Worker 
389*f6dc9357SAndroid Build Coastguard Worker   \\Server\Share_NTFS_drive - ERROR_ACCESS_DENIED
390*f6dc9357SAndroid Build Coastguard Worker   \\Server\Share_FAT_drive  - ERROR_ALREADY_EXISTS
391*f6dc9357SAndroid Build Coastguard Worker */
392*f6dc9357SAndroid Build Coastguard Worker 
CreateDir(CFSTR path)393*f6dc9357SAndroid Build Coastguard Worker bool CreateDir(CFSTR path)
394*f6dc9357SAndroid Build Coastguard Worker {
395*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
396*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
397*f6dc9357SAndroid Build Coastguard Worker   {
398*f6dc9357SAndroid Build Coastguard Worker     if (::CreateDirectory(fs2fas(path), NULL))
399*f6dc9357SAndroid Build Coastguard Worker       return true;
400*f6dc9357SAndroid Build Coastguard Worker   }
401*f6dc9357SAndroid Build Coastguard Worker   else
402*f6dc9357SAndroid Build Coastguard Worker   #endif
403*f6dc9357SAndroid Build Coastguard Worker   {
404*f6dc9357SAndroid Build Coastguard Worker     IF_USE_MAIN_PATH
405*f6dc9357SAndroid Build Coastguard Worker       if (::CreateDirectoryW(fs2us(path), NULL))
406*f6dc9357SAndroid Build Coastguard Worker         return true;
407*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_LONG_PATH
408*f6dc9357SAndroid Build Coastguard Worker     if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)
409*f6dc9357SAndroid Build Coastguard Worker     {
410*f6dc9357SAndroid Build Coastguard Worker       UString superPath;
411*f6dc9357SAndroid Build Coastguard Worker       if (GetSuperPath(path, superPath, USE_MAIN_PATH))
412*f6dc9357SAndroid Build Coastguard Worker         return BOOLToBool(::CreateDirectoryW(superPath, NULL));
413*f6dc9357SAndroid Build Coastguard Worker     }
414*f6dc9357SAndroid Build Coastguard Worker     #endif
415*f6dc9357SAndroid Build Coastguard Worker   }
416*f6dc9357SAndroid Build Coastguard Worker   return false;
417*f6dc9357SAndroid Build Coastguard Worker }
418*f6dc9357SAndroid Build Coastguard Worker 
419*f6dc9357SAndroid Build Coastguard Worker /*
420*f6dc9357SAndroid Build Coastguard Worker   CreateDir2 returns true, if directory can contain files after the call (two cases):
421*f6dc9357SAndroid Build Coastguard Worker     1) the directory already exists
422*f6dc9357SAndroid Build Coastguard Worker     2) the directory was created
423*f6dc9357SAndroid Build Coastguard Worker   path must be WITHOUT trailing path separator.
424*f6dc9357SAndroid Build Coastguard Worker 
425*f6dc9357SAndroid Build Coastguard Worker   We need CreateDir2, since fileInfo.Find() for reserved names like "com8"
426*f6dc9357SAndroid Build Coastguard Worker    returns FILE instead of DIRECTORY. And we need to use SuperPath */
427*f6dc9357SAndroid Build Coastguard Worker 
CreateDir2(CFSTR path)428*f6dc9357SAndroid Build Coastguard Worker static bool CreateDir2(CFSTR path)
429*f6dc9357SAndroid Build Coastguard Worker {
430*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
431*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
432*f6dc9357SAndroid Build Coastguard Worker   {
433*f6dc9357SAndroid Build Coastguard Worker     if (::CreateDirectory(fs2fas(path), NULL))
434*f6dc9357SAndroid Build Coastguard Worker       return true;
435*f6dc9357SAndroid Build Coastguard Worker   }
436*f6dc9357SAndroid Build Coastguard Worker   else
437*f6dc9357SAndroid Build Coastguard Worker   #endif
438*f6dc9357SAndroid Build Coastguard Worker   {
439*f6dc9357SAndroid Build Coastguard Worker     IF_USE_MAIN_PATH
440*f6dc9357SAndroid Build Coastguard Worker       if (::CreateDirectoryW(fs2us(path), NULL))
441*f6dc9357SAndroid Build Coastguard Worker         return true;
442*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_LONG_PATH
443*f6dc9357SAndroid Build Coastguard Worker     if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)
444*f6dc9357SAndroid Build Coastguard Worker     {
445*f6dc9357SAndroid Build Coastguard Worker       UString superPath;
446*f6dc9357SAndroid Build Coastguard Worker       if (GetSuperPath(path, superPath, USE_MAIN_PATH))
447*f6dc9357SAndroid Build Coastguard Worker       {
448*f6dc9357SAndroid Build Coastguard Worker         if (::CreateDirectoryW(superPath, NULL))
449*f6dc9357SAndroid Build Coastguard Worker           return true;
450*f6dc9357SAndroid Build Coastguard Worker         if (::GetLastError() != ERROR_ALREADY_EXISTS)
451*f6dc9357SAndroid Build Coastguard Worker           return false;
452*f6dc9357SAndroid Build Coastguard Worker         NFind::CFileInfo fi;
453*f6dc9357SAndroid Build Coastguard Worker         if (!fi.Find(us2fs(superPath)))
454*f6dc9357SAndroid Build Coastguard Worker           return false;
455*f6dc9357SAndroid Build Coastguard Worker         return fi.IsDir();
456*f6dc9357SAndroid Build Coastguard Worker       }
457*f6dc9357SAndroid Build Coastguard Worker     }
458*f6dc9357SAndroid Build Coastguard Worker     #endif
459*f6dc9357SAndroid Build Coastguard Worker   }
460*f6dc9357SAndroid Build Coastguard Worker   if (::GetLastError() != ERROR_ALREADY_EXISTS)
461*f6dc9357SAndroid Build Coastguard Worker     return false;
462*f6dc9357SAndroid Build Coastguard Worker   NFind::CFileInfo fi;
463*f6dc9357SAndroid Build Coastguard Worker   if (!fi.Find(path))
464*f6dc9357SAndroid Build Coastguard Worker     return false;
465*f6dc9357SAndroid Build Coastguard Worker   return fi.IsDir();
466*f6dc9357SAndroid Build Coastguard Worker }
467*f6dc9357SAndroid Build Coastguard Worker 
468*f6dc9357SAndroid Build Coastguard Worker #endif // _WIN32
469*f6dc9357SAndroid Build Coastguard Worker 
470*f6dc9357SAndroid Build Coastguard Worker static bool CreateDir2(CFSTR path);
471*f6dc9357SAndroid Build Coastguard Worker 
CreateComplexDir(CFSTR _path)472*f6dc9357SAndroid Build Coastguard Worker bool CreateComplexDir(CFSTR _path)
473*f6dc9357SAndroid Build Coastguard Worker {
474*f6dc9357SAndroid Build Coastguard Worker   #ifdef _WIN32
475*f6dc9357SAndroid Build Coastguard Worker 
476*f6dc9357SAndroid Build Coastguard Worker   {
477*f6dc9357SAndroid Build Coastguard Worker     const DWORD attrib = NFind::GetFileAttrib(_path);
478*f6dc9357SAndroid Build Coastguard Worker     if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
479*f6dc9357SAndroid Build Coastguard Worker       return true;
480*f6dc9357SAndroid Build Coastguard Worker   }
481*f6dc9357SAndroid Build Coastguard Worker 
482*f6dc9357SAndroid Build Coastguard Worker   #ifndef UNDER_CE
483*f6dc9357SAndroid Build Coastguard Worker 
484*f6dc9357SAndroid Build Coastguard Worker   if (IsDriveRootPath_SuperAllowed(_path))
485*f6dc9357SAndroid Build Coastguard Worker     return false;
486*f6dc9357SAndroid Build Coastguard Worker 
487*f6dc9357SAndroid Build Coastguard Worker   const unsigned prefixSize = GetRootPrefixSize(_path);
488*f6dc9357SAndroid Build Coastguard Worker 
489*f6dc9357SAndroid Build Coastguard Worker   #endif // UNDER_CE
490*f6dc9357SAndroid Build Coastguard Worker 
491*f6dc9357SAndroid Build Coastguard Worker   #else // _WIN32
492*f6dc9357SAndroid Build Coastguard Worker 
493*f6dc9357SAndroid Build Coastguard Worker   // Posix
494*f6dc9357SAndroid Build Coastguard Worker   NFind::CFileInfo fi;
495*f6dc9357SAndroid Build Coastguard Worker   if (fi.Find(_path))
496*f6dc9357SAndroid Build Coastguard Worker   {
497*f6dc9357SAndroid Build Coastguard Worker     if (fi.IsDir())
498*f6dc9357SAndroid Build Coastguard Worker       return true;
499*f6dc9357SAndroid Build Coastguard Worker   }
500*f6dc9357SAndroid Build Coastguard Worker 
501*f6dc9357SAndroid Build Coastguard Worker   #endif // _WIN32
502*f6dc9357SAndroid Build Coastguard Worker 
503*f6dc9357SAndroid Build Coastguard Worker   FString path (_path);
504*f6dc9357SAndroid Build Coastguard Worker 
505*f6dc9357SAndroid Build Coastguard Worker   int pos = path.ReverseFind_PathSepar();
506*f6dc9357SAndroid Build Coastguard Worker   if (pos >= 0 && (unsigned)pos == path.Len() - 1)
507*f6dc9357SAndroid Build Coastguard Worker   {
508*f6dc9357SAndroid Build Coastguard Worker     if (path.Len() == 1)
509*f6dc9357SAndroid Build Coastguard Worker       return true;
510*f6dc9357SAndroid Build Coastguard Worker     path.DeleteBack();
511*f6dc9357SAndroid Build Coastguard Worker   }
512*f6dc9357SAndroid Build Coastguard Worker 
513*f6dc9357SAndroid Build Coastguard Worker   const FString path2 (path);
514*f6dc9357SAndroid Build Coastguard Worker   pos = (int)path.Len();
515*f6dc9357SAndroid Build Coastguard Worker 
516*f6dc9357SAndroid Build Coastguard Worker   for (;;)
517*f6dc9357SAndroid Build Coastguard Worker   {
518*f6dc9357SAndroid Build Coastguard Worker     if (CreateDir2(path))
519*f6dc9357SAndroid Build Coastguard Worker       break;
520*f6dc9357SAndroid Build Coastguard Worker     if (::GetLastError() == ERROR_ALREADY_EXISTS)
521*f6dc9357SAndroid Build Coastguard Worker       return false;
522*f6dc9357SAndroid Build Coastguard Worker     pos = path.ReverseFind_PathSepar();
523*f6dc9357SAndroid Build Coastguard Worker     if (pos < 0 || pos == 0)
524*f6dc9357SAndroid Build Coastguard Worker       return false;
525*f6dc9357SAndroid Build Coastguard Worker 
526*f6dc9357SAndroid Build Coastguard Worker     #if defined(_WIN32) && !defined(UNDER_CE)
527*f6dc9357SAndroid Build Coastguard Worker     if (pos == 1 && IS_PATH_SEPAR(path[0]))
528*f6dc9357SAndroid Build Coastguard Worker       return false;
529*f6dc9357SAndroid Build Coastguard Worker     if (prefixSize >= (unsigned)pos + 1)
530*f6dc9357SAndroid Build Coastguard Worker       return false;
531*f6dc9357SAndroid Build Coastguard Worker     #endif
532*f6dc9357SAndroid Build Coastguard Worker 
533*f6dc9357SAndroid Build Coastguard Worker     path.DeleteFrom((unsigned)pos);
534*f6dc9357SAndroid Build Coastguard Worker   }
535*f6dc9357SAndroid Build Coastguard Worker 
536*f6dc9357SAndroid Build Coastguard Worker   while (pos < (int)path2.Len())
537*f6dc9357SAndroid Build Coastguard Worker   {
538*f6dc9357SAndroid Build Coastguard Worker     int pos2 = NName::FindSepar(path2.Ptr((unsigned)pos + 1));
539*f6dc9357SAndroid Build Coastguard Worker     if (pos2 < 0)
540*f6dc9357SAndroid Build Coastguard Worker       pos = (int)path2.Len();
541*f6dc9357SAndroid Build Coastguard Worker     else
542*f6dc9357SAndroid Build Coastguard Worker       pos += 1 + pos2;
543*f6dc9357SAndroid Build Coastguard Worker     path.SetFrom(path2, (unsigned)pos);
544*f6dc9357SAndroid Build Coastguard Worker     if (!CreateDir(path))
545*f6dc9357SAndroid Build Coastguard Worker       return false;
546*f6dc9357SAndroid Build Coastguard Worker   }
547*f6dc9357SAndroid Build Coastguard Worker 
548*f6dc9357SAndroid Build Coastguard Worker   return true;
549*f6dc9357SAndroid Build Coastguard Worker }
550*f6dc9357SAndroid Build Coastguard Worker 
551*f6dc9357SAndroid Build Coastguard Worker 
552*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
553*f6dc9357SAndroid Build Coastguard Worker 
DeleteFileAlways(CFSTR path)554*f6dc9357SAndroid Build Coastguard Worker bool DeleteFileAlways(CFSTR path)
555*f6dc9357SAndroid Build Coastguard Worker {
556*f6dc9357SAndroid Build Coastguard Worker   /* If alt stream, we also need to clear READ-ONLY attribute of main file before delete.
557*f6dc9357SAndroid Build Coastguard Worker      SetFileAttrib("name:stream", ) changes attributes of main file. */
558*f6dc9357SAndroid Build Coastguard Worker   {
559*f6dc9357SAndroid Build Coastguard Worker     DWORD attrib = NFind::GetFileAttrib(path);
560*f6dc9357SAndroid Build Coastguard Worker     if (attrib != INVALID_FILE_ATTRIBUTES
561*f6dc9357SAndroid Build Coastguard Worker         && (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0
562*f6dc9357SAndroid Build Coastguard Worker         && (attrib & FILE_ATTRIBUTE_READONLY) != 0)
563*f6dc9357SAndroid Build Coastguard Worker     {
564*f6dc9357SAndroid Build Coastguard Worker       if (!SetFileAttrib(path, attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY))
565*f6dc9357SAndroid Build Coastguard Worker         return false;
566*f6dc9357SAndroid Build Coastguard Worker     }
567*f6dc9357SAndroid Build Coastguard Worker   }
568*f6dc9357SAndroid Build Coastguard Worker 
569*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
570*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
571*f6dc9357SAndroid Build Coastguard Worker   {
572*f6dc9357SAndroid Build Coastguard Worker     if (::DeleteFile(fs2fas(path)))
573*f6dc9357SAndroid Build Coastguard Worker       return true;
574*f6dc9357SAndroid Build Coastguard Worker   }
575*f6dc9357SAndroid Build Coastguard Worker   else
576*f6dc9357SAndroid Build Coastguard Worker   #endif
577*f6dc9357SAndroid Build Coastguard Worker   {
578*f6dc9357SAndroid Build Coastguard Worker     /* DeleteFile("name::$DATA") deletes all alt streams (same as delete DeleteFile("name")).
579*f6dc9357SAndroid Build Coastguard Worker        Maybe it's better to open "name::$DATA" and clear data for unnamed stream? */
580*f6dc9357SAndroid Build Coastguard Worker     IF_USE_MAIN_PATH
581*f6dc9357SAndroid Build Coastguard Worker       if (::DeleteFileW(fs2us(path)))
582*f6dc9357SAndroid Build Coastguard Worker         return true;
583*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_LONG_PATH
584*f6dc9357SAndroid Build Coastguard Worker     if (USE_SUPER_PATH)
585*f6dc9357SAndroid Build Coastguard Worker     {
586*f6dc9357SAndroid Build Coastguard Worker       UString superPath;
587*f6dc9357SAndroid Build Coastguard Worker       if (GetSuperPath(path, superPath, USE_MAIN_PATH))
588*f6dc9357SAndroid Build Coastguard Worker         return BOOLToBool(::DeleteFileW(superPath));
589*f6dc9357SAndroid Build Coastguard Worker     }
590*f6dc9357SAndroid Build Coastguard Worker     #endif
591*f6dc9357SAndroid Build Coastguard Worker   }
592*f6dc9357SAndroid Build Coastguard Worker   return false;
593*f6dc9357SAndroid Build Coastguard Worker }
594*f6dc9357SAndroid Build Coastguard Worker 
595*f6dc9357SAndroid Build Coastguard Worker 
596*f6dc9357SAndroid Build Coastguard Worker 
RemoveDirWithSubItems(const FString & path)597*f6dc9357SAndroid Build Coastguard Worker bool RemoveDirWithSubItems(const FString &path)
598*f6dc9357SAndroid Build Coastguard Worker {
599*f6dc9357SAndroid Build Coastguard Worker   bool needRemoveSubItems = true;
600*f6dc9357SAndroid Build Coastguard Worker   {
601*f6dc9357SAndroid Build Coastguard Worker     NFind::CFileInfo fi;
602*f6dc9357SAndroid Build Coastguard Worker     if (!fi.Find(path))
603*f6dc9357SAndroid Build Coastguard Worker       return false;
604*f6dc9357SAndroid Build Coastguard Worker     if (!fi.IsDir())
605*f6dc9357SAndroid Build Coastguard Worker     {
606*f6dc9357SAndroid Build Coastguard Worker       ::SetLastError(ERROR_DIRECTORY);
607*f6dc9357SAndroid Build Coastguard Worker       return false;
608*f6dc9357SAndroid Build Coastguard Worker     }
609*f6dc9357SAndroid Build Coastguard Worker     if (fi.HasReparsePoint())
610*f6dc9357SAndroid Build Coastguard Worker       needRemoveSubItems = false;
611*f6dc9357SAndroid Build Coastguard Worker   }
612*f6dc9357SAndroid Build Coastguard Worker 
613*f6dc9357SAndroid Build Coastguard Worker   if (needRemoveSubItems)
614*f6dc9357SAndroid Build Coastguard Worker   {
615*f6dc9357SAndroid Build Coastguard Worker     FString s (path);
616*f6dc9357SAndroid Build Coastguard Worker     s.Add_PathSepar();
617*f6dc9357SAndroid Build Coastguard Worker     const unsigned prefixSize = s.Len();
618*f6dc9357SAndroid Build Coastguard Worker     NFind::CEnumerator enumerator;
619*f6dc9357SAndroid Build Coastguard Worker     enumerator.SetDirPrefix(s);
620*f6dc9357SAndroid Build Coastguard Worker     NFind::CDirEntry fi;
621*f6dc9357SAndroid Build Coastguard Worker     bool isError = false;
622*f6dc9357SAndroid Build Coastguard Worker     DWORD lastError = 0;
623*f6dc9357SAndroid Build Coastguard Worker     while (enumerator.Next(fi))
624*f6dc9357SAndroid Build Coastguard Worker     {
625*f6dc9357SAndroid Build Coastguard Worker       s.DeleteFrom(prefixSize);
626*f6dc9357SAndroid Build Coastguard Worker       s += fi.Name;
627*f6dc9357SAndroid Build Coastguard Worker       if (fi.IsDir())
628*f6dc9357SAndroid Build Coastguard Worker       {
629*f6dc9357SAndroid Build Coastguard Worker         if (!RemoveDirWithSubItems(s))
630*f6dc9357SAndroid Build Coastguard Worker         {
631*f6dc9357SAndroid Build Coastguard Worker           lastError = GetLastError();
632*f6dc9357SAndroid Build Coastguard Worker           isError = true;
633*f6dc9357SAndroid Build Coastguard Worker         }
634*f6dc9357SAndroid Build Coastguard Worker       }
635*f6dc9357SAndroid Build Coastguard Worker       else if (!DeleteFileAlways(s))
636*f6dc9357SAndroid Build Coastguard Worker       {
637*f6dc9357SAndroid Build Coastguard Worker         lastError = GetLastError();
638*f6dc9357SAndroid Build Coastguard Worker         isError = false;
639*f6dc9357SAndroid Build Coastguard Worker       }
640*f6dc9357SAndroid Build Coastguard Worker     }
641*f6dc9357SAndroid Build Coastguard Worker     if (isError)
642*f6dc9357SAndroid Build Coastguard Worker     {
643*f6dc9357SAndroid Build Coastguard Worker       SetLastError(lastError);
644*f6dc9357SAndroid Build Coastguard Worker       return false;
645*f6dc9357SAndroid Build Coastguard Worker     }
646*f6dc9357SAndroid Build Coastguard Worker   }
647*f6dc9357SAndroid Build Coastguard Worker 
648*f6dc9357SAndroid Build Coastguard Worker   // we clear read-only attrib to remove read-only dir
649*f6dc9357SAndroid Build Coastguard Worker   if (!SetFileAttrib(path, 0))
650*f6dc9357SAndroid Build Coastguard Worker     return false;
651*f6dc9357SAndroid Build Coastguard Worker   return RemoveDir(path);
652*f6dc9357SAndroid Build Coastguard Worker }
653*f6dc9357SAndroid Build Coastguard Worker 
654*f6dc9357SAndroid Build Coastguard Worker #endif // _WIN32
655*f6dc9357SAndroid Build Coastguard Worker 
656*f6dc9357SAndroid Build Coastguard Worker #ifdef UNDER_CE
657*f6dc9357SAndroid Build Coastguard Worker 
MyGetFullPathName(CFSTR path,FString & resFullPath)658*f6dc9357SAndroid Build Coastguard Worker bool MyGetFullPathName(CFSTR path, FString &resFullPath)
659*f6dc9357SAndroid Build Coastguard Worker {
660*f6dc9357SAndroid Build Coastguard Worker   resFullPath = path;
661*f6dc9357SAndroid Build Coastguard Worker   return true;
662*f6dc9357SAndroid Build Coastguard Worker }
663*f6dc9357SAndroid Build Coastguard Worker 
664*f6dc9357SAndroid Build Coastguard Worker #else
665*f6dc9357SAndroid Build Coastguard Worker 
MyGetFullPathName(CFSTR path,FString & resFullPath)666*f6dc9357SAndroid Build Coastguard Worker bool MyGetFullPathName(CFSTR path, FString &resFullPath)
667*f6dc9357SAndroid Build Coastguard Worker {
668*f6dc9357SAndroid Build Coastguard Worker   return GetFullPath(path, resFullPath);
669*f6dc9357SAndroid Build Coastguard Worker }
670*f6dc9357SAndroid Build Coastguard Worker 
671*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
672*f6dc9357SAndroid Build Coastguard Worker 
673*f6dc9357SAndroid Build Coastguard Worker /* Win10: SetCurrentDirectory() doesn't support long paths and
674*f6dc9357SAndroid Build Coastguard Worker     doesn't support super prefix "\\?\", if long path behavior is not
675*f6dc9357SAndroid Build Coastguard Worker     enabled in registry (LongPathsEnabled) and in manifest (longPathAware). */
676*f6dc9357SAndroid Build Coastguard Worker 
SetCurrentDir(CFSTR path)677*f6dc9357SAndroid Build Coastguard Worker bool SetCurrentDir(CFSTR path)
678*f6dc9357SAndroid Build Coastguard Worker {
679*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
680*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
681*f6dc9357SAndroid Build Coastguard Worker   {
682*f6dc9357SAndroid Build Coastguard Worker     return BOOLToBool(::SetCurrentDirectory(fs2fas(path)));
683*f6dc9357SAndroid Build Coastguard Worker   }
684*f6dc9357SAndroid Build Coastguard Worker   else
685*f6dc9357SAndroid Build Coastguard Worker   #endif
686*f6dc9357SAndroid Build Coastguard Worker   {
687*f6dc9357SAndroid Build Coastguard Worker     return BOOLToBool(::SetCurrentDirectoryW(fs2us(path)));
688*f6dc9357SAndroid Build Coastguard Worker   }
689*f6dc9357SAndroid Build Coastguard Worker }
690*f6dc9357SAndroid Build Coastguard Worker 
691*f6dc9357SAndroid Build Coastguard Worker 
692*f6dc9357SAndroid Build Coastguard Worker /*
693*f6dc9357SAndroid Build Coastguard Worker we use system function GetCurrentDirectory()
694*f6dc9357SAndroid Build Coastguard Worker new GetCurrentDirectory() DOCs:
695*f6dc9357SAndroid Build Coastguard Worker   - If the function fails, the return value is zero.
696*f6dc9357SAndroid Build Coastguard Worker   - If the function succeeds, the return value specifies
697*f6dc9357SAndroid Build Coastguard Worker       the number of characters that are written to the buffer,
698*f6dc9357SAndroid Build Coastguard Worker       not including the terminating null character.
699*f6dc9357SAndroid Build Coastguard Worker   - If the buffer is not large enough, the return value specifies
700*f6dc9357SAndroid Build Coastguard Worker       the required size of the buffer, in characters,
701*f6dc9357SAndroid Build Coastguard Worker       including the null-terminating character.
702*f6dc9357SAndroid Build Coastguard Worker 
703*f6dc9357SAndroid Build Coastguard Worker GetCurrentDir() calls GetCurrentDirectory().
704*f6dc9357SAndroid Build Coastguard Worker GetCurrentDirectory() in win10 in tests:
705*f6dc9357SAndroid Build Coastguard Worker   the returned (path) does not end with a backslash, if
706*f6dc9357SAndroid Build Coastguard Worker   current directory is not root directory of drive.
707*f6dc9357SAndroid Build Coastguard Worker   But that behavior is not guarantied in specification docs.
708*f6dc9357SAndroid Build Coastguard Worker */
709*f6dc9357SAndroid Build Coastguard Worker 
GetCurrentDir(FString & path)710*f6dc9357SAndroid Build Coastguard Worker bool GetCurrentDir(FString &path)
711*f6dc9357SAndroid Build Coastguard Worker {
712*f6dc9357SAndroid Build Coastguard Worker   const unsigned kBufSize = MAX_PATH + 16;
713*f6dc9357SAndroid Build Coastguard Worker   path.Empty();
714*f6dc9357SAndroid Build Coastguard Worker 
715*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
716*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
717*f6dc9357SAndroid Build Coastguard Worker   {
718*f6dc9357SAndroid Build Coastguard Worker     TCHAR s[kBufSize + 1];
719*f6dc9357SAndroid Build Coastguard Worker     s[0] = 0;
720*f6dc9357SAndroid Build Coastguard Worker     const DWORD len = ::GetCurrentDirectory(kBufSize, s);
721*f6dc9357SAndroid Build Coastguard Worker     if (len == 0 || len >= kBufSize)
722*f6dc9357SAndroid Build Coastguard Worker       return false;
723*f6dc9357SAndroid Build Coastguard Worker     s[kBufSize] = 0;  // optional guard
724*f6dc9357SAndroid Build Coastguard Worker     path = fas2fs(s);
725*f6dc9357SAndroid Build Coastguard Worker     return true;
726*f6dc9357SAndroid Build Coastguard Worker   }
727*f6dc9357SAndroid Build Coastguard Worker   else
728*f6dc9357SAndroid Build Coastguard Worker   #endif
729*f6dc9357SAndroid Build Coastguard Worker   {
730*f6dc9357SAndroid Build Coastguard Worker     DWORD len;
731*f6dc9357SAndroid Build Coastguard Worker     {
732*f6dc9357SAndroid Build Coastguard Worker       WCHAR s[kBufSize + 1];
733*f6dc9357SAndroid Build Coastguard Worker       s[0] = 0;
734*f6dc9357SAndroid Build Coastguard Worker       len = ::GetCurrentDirectoryW(kBufSize, s);
735*f6dc9357SAndroid Build Coastguard Worker       if (len == 0)
736*f6dc9357SAndroid Build Coastguard Worker         return false;
737*f6dc9357SAndroid Build Coastguard Worker       if (len < kBufSize)
738*f6dc9357SAndroid Build Coastguard Worker       {
739*f6dc9357SAndroid Build Coastguard Worker         s[kBufSize] = 0;  // optional guard
740*f6dc9357SAndroid Build Coastguard Worker         path = us2fs(s);
741*f6dc9357SAndroid Build Coastguard Worker         return true;
742*f6dc9357SAndroid Build Coastguard Worker       }
743*f6dc9357SAndroid Build Coastguard Worker     }
744*f6dc9357SAndroid Build Coastguard Worker     UString temp;
745*f6dc9357SAndroid Build Coastguard Worker     const DWORD len2 = ::GetCurrentDirectoryW(len, temp.GetBuf(len));
746*f6dc9357SAndroid Build Coastguard Worker     if (len2 == 0)
747*f6dc9357SAndroid Build Coastguard Worker       return false;
748*f6dc9357SAndroid Build Coastguard Worker     temp.ReleaseBuf_CalcLen(len);
749*f6dc9357SAndroid Build Coastguard Worker     if (temp.Len() != len2 || len - 1 != len2)
750*f6dc9357SAndroid Build Coastguard Worker     {
751*f6dc9357SAndroid Build Coastguard Worker       /* it's unexpected case, if current dir of process
752*f6dc9357SAndroid Build Coastguard Worker          was changed between two function calls,
753*f6dc9357SAndroid Build Coastguard Worker          or some unexpected function implementation */
754*f6dc9357SAndroid Build Coastguard Worker       // SetLastError((DWORD)E_FAIL);  // we can set some error code
755*f6dc9357SAndroid Build Coastguard Worker       return false;
756*f6dc9357SAndroid Build Coastguard Worker     }
757*f6dc9357SAndroid Build Coastguard Worker     path = us2fs(temp);
758*f6dc9357SAndroid Build Coastguard Worker     return true;
759*f6dc9357SAndroid Build Coastguard Worker   }
760*f6dc9357SAndroid Build Coastguard Worker }
761*f6dc9357SAndroid Build Coastguard Worker 
762*f6dc9357SAndroid Build Coastguard Worker #endif // _WIN32
763*f6dc9357SAndroid Build Coastguard Worker #endif // UNDER_CE
764*f6dc9357SAndroid Build Coastguard Worker 
765*f6dc9357SAndroid Build Coastguard Worker 
GetFullPathAndSplit(CFSTR path,FString & resDirPrefix,FString & resFileName)766*f6dc9357SAndroid Build Coastguard Worker bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName)
767*f6dc9357SAndroid Build Coastguard Worker {
768*f6dc9357SAndroid Build Coastguard Worker   bool res = MyGetFullPathName(path, resDirPrefix);
769*f6dc9357SAndroid Build Coastguard Worker   if (!res)
770*f6dc9357SAndroid Build Coastguard Worker     resDirPrefix = path;
771*f6dc9357SAndroid Build Coastguard Worker   int pos = resDirPrefix.ReverseFind_PathSepar();
772*f6dc9357SAndroid Build Coastguard Worker   pos++;
773*f6dc9357SAndroid Build Coastguard Worker   resFileName = resDirPrefix.Ptr((unsigned)pos);
774*f6dc9357SAndroid Build Coastguard Worker   resDirPrefix.DeleteFrom((unsigned)pos);
775*f6dc9357SAndroid Build Coastguard Worker   return res;
776*f6dc9357SAndroid Build Coastguard Worker }
777*f6dc9357SAndroid Build Coastguard Worker 
GetOnlyDirPrefix(CFSTR path,FString & resDirPrefix)778*f6dc9357SAndroid Build Coastguard Worker bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix)
779*f6dc9357SAndroid Build Coastguard Worker {
780*f6dc9357SAndroid Build Coastguard Worker   FString resFileName;
781*f6dc9357SAndroid Build Coastguard Worker   return GetFullPathAndSplit(path, resDirPrefix, resFileName);
782*f6dc9357SAndroid Build Coastguard Worker }
783*f6dc9357SAndroid Build Coastguard Worker 
784*f6dc9357SAndroid Build Coastguard Worker 
785*f6dc9357SAndroid Build Coastguard Worker 
MyGetTempPath(FString & path)786*f6dc9357SAndroid Build Coastguard Worker bool MyGetTempPath(FString &path)
787*f6dc9357SAndroid Build Coastguard Worker {
788*f6dc9357SAndroid Build Coastguard Worker   #ifdef _WIN32
789*f6dc9357SAndroid Build Coastguard Worker 
790*f6dc9357SAndroid Build Coastguard Worker   /*
791*f6dc9357SAndroid Build Coastguard Worker   new DOCs for GetTempPathW():
792*f6dc9357SAndroid Build Coastguard Worker     - The returned string ends with a backslash.
793*f6dc9357SAndroid Build Coastguard Worker     - The maximum possible return value is MAX_PATH+1 (261).
794*f6dc9357SAndroid Build Coastguard Worker   */
795*f6dc9357SAndroid Build Coastguard Worker 
796*f6dc9357SAndroid Build Coastguard Worker   const unsigned kBufSize = MAX_PATH + 16;
797*f6dc9357SAndroid Build Coastguard Worker   DWORD len;
798*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
799*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
800*f6dc9357SAndroid Build Coastguard Worker   {
801*f6dc9357SAndroid Build Coastguard Worker     TCHAR s[kBufSize + 1];
802*f6dc9357SAndroid Build Coastguard Worker     s[0] = 0;
803*f6dc9357SAndroid Build Coastguard Worker     len = ::GetTempPath(kBufSize, s);
804*f6dc9357SAndroid Build Coastguard Worker     path = fas2fs(s);
805*f6dc9357SAndroid Build Coastguard Worker   }
806*f6dc9357SAndroid Build Coastguard Worker   else
807*f6dc9357SAndroid Build Coastguard Worker   #endif
808*f6dc9357SAndroid Build Coastguard Worker   {
809*f6dc9357SAndroid Build Coastguard Worker     WCHAR s[kBufSize + 1];
810*f6dc9357SAndroid Build Coastguard Worker     s[0] = 0;
811*f6dc9357SAndroid Build Coastguard Worker     len = ::GetTempPathW(kBufSize, s);
812*f6dc9357SAndroid Build Coastguard Worker     path = us2fs(s);
813*f6dc9357SAndroid Build Coastguard Worker   }
814*f6dc9357SAndroid Build Coastguard Worker   /* win10: GetTempPathW() doesn't set backslash at the end of path,
815*f6dc9357SAndroid Build Coastguard Worker        if (buffer_size == len_of(path_with_backslash)).
816*f6dc9357SAndroid Build Coastguard Worker      So we normalize path here: */
817*f6dc9357SAndroid Build Coastguard Worker   NormalizeDirPathPrefix(path);
818*f6dc9357SAndroid Build Coastguard Worker   return (len != 0 && len < kBufSize);
819*f6dc9357SAndroid Build Coastguard Worker 
820*f6dc9357SAndroid Build Coastguard Worker   #else  // !_WIN32
821*f6dc9357SAndroid Build Coastguard Worker 
822*f6dc9357SAndroid Build Coastguard Worker   // FIXME: improve that code
823*f6dc9357SAndroid Build Coastguard Worker   path = STRING_PATH_SEPARATOR "tmp";
824*f6dc9357SAndroid Build Coastguard Worker   const char *s;
825*f6dc9357SAndroid Build Coastguard Worker   if (NFind::DoesDirExist_FollowLink(path))
826*f6dc9357SAndroid Build Coastguard Worker     s = STRING_PATH_SEPARATOR "tmp" STRING_PATH_SEPARATOR;
827*f6dc9357SAndroid Build Coastguard Worker   else
828*f6dc9357SAndroid Build Coastguard Worker     s = "." STRING_PATH_SEPARATOR;
829*f6dc9357SAndroid Build Coastguard Worker   path = s;
830*f6dc9357SAndroid Build Coastguard Worker   return true;
831*f6dc9357SAndroid Build Coastguard Worker 
832*f6dc9357SAndroid Build Coastguard Worker   #endif
833*f6dc9357SAndroid Build Coastguard Worker }
834*f6dc9357SAndroid Build Coastguard Worker 
835*f6dc9357SAndroid Build Coastguard Worker 
CreateTempFile2(CFSTR prefix,bool addRandom,AString & postfix,NIO::COutFile * outFile)836*f6dc9357SAndroid Build Coastguard Worker bool CreateTempFile2(CFSTR prefix, bool addRandom, AString &postfix, NIO::COutFile *outFile)
837*f6dc9357SAndroid Build Coastguard Worker {
838*f6dc9357SAndroid Build Coastguard Worker   UInt32 d =
839*f6dc9357SAndroid Build Coastguard Worker     #ifdef _WIN32
840*f6dc9357SAndroid Build Coastguard Worker       (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();
841*f6dc9357SAndroid Build Coastguard Worker     #else
842*f6dc9357SAndroid Build Coastguard Worker       (UInt32)(time(NULL) << 12) ^  ((UInt32)getppid() << 14) ^ (UInt32)(getpid());
843*f6dc9357SAndroid Build Coastguard Worker     #endif
844*f6dc9357SAndroid Build Coastguard Worker 
845*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < 100; i++)
846*f6dc9357SAndroid Build Coastguard Worker   {
847*f6dc9357SAndroid Build Coastguard Worker     postfix.Empty();
848*f6dc9357SAndroid Build Coastguard Worker     if (addRandom)
849*f6dc9357SAndroid Build Coastguard Worker     {
850*f6dc9357SAndroid Build Coastguard Worker       char s[16];
851*f6dc9357SAndroid Build Coastguard Worker       UInt32 val = d;
852*f6dc9357SAndroid Build Coastguard Worker       unsigned k;
853*f6dc9357SAndroid Build Coastguard Worker       for (k = 0; k < 8; k++)
854*f6dc9357SAndroid Build Coastguard Worker       {
855*f6dc9357SAndroid Build Coastguard Worker         const unsigned t = (unsigned)val & 0xF;
856*f6dc9357SAndroid Build Coastguard Worker         val >>= 4;
857*f6dc9357SAndroid Build Coastguard Worker         s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
858*f6dc9357SAndroid Build Coastguard Worker       }
859*f6dc9357SAndroid Build Coastguard Worker       s[k] = '\0';
860*f6dc9357SAndroid Build Coastguard Worker       if (outFile)
861*f6dc9357SAndroid Build Coastguard Worker         postfix.Add_Dot();
862*f6dc9357SAndroid Build Coastguard Worker       postfix += s;
863*f6dc9357SAndroid Build Coastguard Worker       UInt32 step = GetTickCount() + 2;
864*f6dc9357SAndroid Build Coastguard Worker       if (step == 0)
865*f6dc9357SAndroid Build Coastguard Worker         step = 1;
866*f6dc9357SAndroid Build Coastguard Worker       d += step;
867*f6dc9357SAndroid Build Coastguard Worker     }
868*f6dc9357SAndroid Build Coastguard Worker     addRandom = true;
869*f6dc9357SAndroid Build Coastguard Worker     if (outFile)
870*f6dc9357SAndroid Build Coastguard Worker       postfix += ".tmp";
871*f6dc9357SAndroid Build Coastguard Worker     FString path (prefix);
872*f6dc9357SAndroid Build Coastguard Worker     path += postfix;
873*f6dc9357SAndroid Build Coastguard Worker     if (NFind::DoesFileOrDirExist(path))
874*f6dc9357SAndroid Build Coastguard Worker     {
875*f6dc9357SAndroid Build Coastguard Worker       SetLastError(ERROR_ALREADY_EXISTS);
876*f6dc9357SAndroid Build Coastguard Worker       continue;
877*f6dc9357SAndroid Build Coastguard Worker     }
878*f6dc9357SAndroid Build Coastguard Worker     if (outFile)
879*f6dc9357SAndroid Build Coastguard Worker     {
880*f6dc9357SAndroid Build Coastguard Worker       if (outFile->Create_NEW(path))
881*f6dc9357SAndroid Build Coastguard Worker         return true;
882*f6dc9357SAndroid Build Coastguard Worker     }
883*f6dc9357SAndroid Build Coastguard Worker     else
884*f6dc9357SAndroid Build Coastguard Worker     {
885*f6dc9357SAndroid Build Coastguard Worker       if (CreateDir(path))
886*f6dc9357SAndroid Build Coastguard Worker         return true;
887*f6dc9357SAndroid Build Coastguard Worker     }
888*f6dc9357SAndroid Build Coastguard Worker     const DWORD error = GetLastError();
889*f6dc9357SAndroid Build Coastguard Worker     if (error != ERROR_FILE_EXISTS &&
890*f6dc9357SAndroid Build Coastguard Worker         error != ERROR_ALREADY_EXISTS)
891*f6dc9357SAndroid Build Coastguard Worker       break;
892*f6dc9357SAndroid Build Coastguard Worker   }
893*f6dc9357SAndroid Build Coastguard Worker   postfix.Empty();
894*f6dc9357SAndroid Build Coastguard Worker   return false;
895*f6dc9357SAndroid Build Coastguard Worker }
896*f6dc9357SAndroid Build Coastguard Worker 
Create(CFSTR prefix,NIO::COutFile * outFile)897*f6dc9357SAndroid Build Coastguard Worker bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile)
898*f6dc9357SAndroid Build Coastguard Worker {
899*f6dc9357SAndroid Build Coastguard Worker   if (!Remove())
900*f6dc9357SAndroid Build Coastguard Worker     return false;
901*f6dc9357SAndroid Build Coastguard Worker   _path.Empty();
902*f6dc9357SAndroid Build Coastguard Worker   AString postfix;
903*f6dc9357SAndroid Build Coastguard Worker   if (!CreateTempFile2(prefix, false, postfix, outFile))
904*f6dc9357SAndroid Build Coastguard Worker     return false;
905*f6dc9357SAndroid Build Coastguard Worker   _path = prefix;
906*f6dc9357SAndroid Build Coastguard Worker   _path += postfix;
907*f6dc9357SAndroid Build Coastguard Worker   _mustBeDeleted = true;
908*f6dc9357SAndroid Build Coastguard Worker   return true;
909*f6dc9357SAndroid Build Coastguard Worker }
910*f6dc9357SAndroid Build Coastguard Worker 
CreateRandomInTempFolder(CFSTR namePrefix,NIO::COutFile * outFile)911*f6dc9357SAndroid Build Coastguard Worker bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile)
912*f6dc9357SAndroid Build Coastguard Worker {
913*f6dc9357SAndroid Build Coastguard Worker   if (!Remove())
914*f6dc9357SAndroid Build Coastguard Worker     return false;
915*f6dc9357SAndroid Build Coastguard Worker   _path.Empty();
916*f6dc9357SAndroid Build Coastguard Worker   FString tempPath;
917*f6dc9357SAndroid Build Coastguard Worker   if (!MyGetTempPath(tempPath))
918*f6dc9357SAndroid Build Coastguard Worker     return false;
919*f6dc9357SAndroid Build Coastguard Worker   AString postfix;
920*f6dc9357SAndroid Build Coastguard Worker   tempPath += namePrefix;
921*f6dc9357SAndroid Build Coastguard Worker   if (!CreateTempFile2(tempPath, true, postfix, outFile))
922*f6dc9357SAndroid Build Coastguard Worker     return false;
923*f6dc9357SAndroid Build Coastguard Worker   _path = tempPath;
924*f6dc9357SAndroid Build Coastguard Worker   _path += postfix;
925*f6dc9357SAndroid Build Coastguard Worker   _mustBeDeleted = true;
926*f6dc9357SAndroid Build Coastguard Worker   return true;
927*f6dc9357SAndroid Build Coastguard Worker }
928*f6dc9357SAndroid Build Coastguard Worker 
Remove()929*f6dc9357SAndroid Build Coastguard Worker bool CTempFile::Remove()
930*f6dc9357SAndroid Build Coastguard Worker {
931*f6dc9357SAndroid Build Coastguard Worker   if (!_mustBeDeleted)
932*f6dc9357SAndroid Build Coastguard Worker     return true;
933*f6dc9357SAndroid Build Coastguard Worker   _mustBeDeleted = !DeleteFileAlways(_path);
934*f6dc9357SAndroid Build Coastguard Worker   return !_mustBeDeleted;
935*f6dc9357SAndroid Build Coastguard Worker }
936*f6dc9357SAndroid Build Coastguard Worker 
MoveTo(CFSTR name,bool deleteDestBefore,ICopyFileProgress * progress)937*f6dc9357SAndroid Build Coastguard Worker bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore,
938*f6dc9357SAndroid Build Coastguard Worker     ICopyFileProgress *progress)
939*f6dc9357SAndroid Build Coastguard Worker {
940*f6dc9357SAndroid Build Coastguard Worker   if (deleteDestBefore)
941*f6dc9357SAndroid Build Coastguard Worker   {
942*f6dc9357SAndroid Build Coastguard Worker     if (NFind::DoesFileExist_Raw(name))
943*f6dc9357SAndroid Build Coastguard Worker     {
944*f6dc9357SAndroid Build Coastguard Worker       // attrib = NFind::GetFileAttrib(name);
945*f6dc9357SAndroid Build Coastguard Worker       if (!DeleteFileAlways(name))
946*f6dc9357SAndroid Build Coastguard Worker         return false;
947*f6dc9357SAndroid Build Coastguard Worker     }
948*f6dc9357SAndroid Build Coastguard Worker   }
949*f6dc9357SAndroid Build Coastguard Worker   DisableDeleting();
950*f6dc9357SAndroid Build Coastguard Worker   // if (!progress) return MyMoveFile(_path, name);
951*f6dc9357SAndroid Build Coastguard Worker   return MyMoveFile_with_Progress(_path, name, progress);
952*f6dc9357SAndroid Build Coastguard Worker   /*
953*f6dc9357SAndroid Build Coastguard Worker   if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))
954*f6dc9357SAndroid Build Coastguard Worker   {
955*f6dc9357SAndroid Build Coastguard Worker     DWORD attrib2 = NFind::GetFileAttrib(name);
956*f6dc9357SAndroid Build Coastguard Worker     if (attrib2 != INVALID_FILE_ATTRIBUTES)
957*f6dc9357SAndroid Build Coastguard Worker       SetFileAttrib(name, attrib2 | FILE_ATTRIBUTE_READONLY);
958*f6dc9357SAndroid Build Coastguard Worker   }
959*f6dc9357SAndroid Build Coastguard Worker   */
960*f6dc9357SAndroid Build Coastguard Worker }
961*f6dc9357SAndroid Build Coastguard Worker 
962*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
Create(CFSTR prefix)963*f6dc9357SAndroid Build Coastguard Worker bool CTempDir::Create(CFSTR prefix)
964*f6dc9357SAndroid Build Coastguard Worker {
965*f6dc9357SAndroid Build Coastguard Worker   if (!Remove())
966*f6dc9357SAndroid Build Coastguard Worker     return false;
967*f6dc9357SAndroid Build Coastguard Worker   _path.Empty();
968*f6dc9357SAndroid Build Coastguard Worker   FString tempPath;
969*f6dc9357SAndroid Build Coastguard Worker   if (!MyGetTempPath(tempPath))
970*f6dc9357SAndroid Build Coastguard Worker     return false;
971*f6dc9357SAndroid Build Coastguard Worker   tempPath += prefix;
972*f6dc9357SAndroid Build Coastguard Worker   AString postfix;
973*f6dc9357SAndroid Build Coastguard Worker   if (!CreateTempFile2(tempPath, true, postfix, NULL))
974*f6dc9357SAndroid Build Coastguard Worker     return false;
975*f6dc9357SAndroid Build Coastguard Worker   _path = tempPath;
976*f6dc9357SAndroid Build Coastguard Worker   _path += postfix;
977*f6dc9357SAndroid Build Coastguard Worker   _mustBeDeleted = true;
978*f6dc9357SAndroid Build Coastguard Worker   return true;
979*f6dc9357SAndroid Build Coastguard Worker }
980*f6dc9357SAndroid Build Coastguard Worker 
Remove()981*f6dc9357SAndroid Build Coastguard Worker bool CTempDir::Remove()
982*f6dc9357SAndroid Build Coastguard Worker {
983*f6dc9357SAndroid Build Coastguard Worker   if (!_mustBeDeleted)
984*f6dc9357SAndroid Build Coastguard Worker     return true;
985*f6dc9357SAndroid Build Coastguard Worker   _mustBeDeleted = !RemoveDirWithSubItems(_path);
986*f6dc9357SAndroid Build Coastguard Worker   return !_mustBeDeleted;
987*f6dc9357SAndroid Build Coastguard Worker }
988*f6dc9357SAndroid Build Coastguard Worker #endif
989*f6dc9357SAndroid Build Coastguard Worker 
990*f6dc9357SAndroid Build Coastguard Worker 
991*f6dc9357SAndroid Build Coastguard Worker 
992*f6dc9357SAndroid Build Coastguard Worker #ifndef _WIN32
993*f6dc9357SAndroid Build Coastguard Worker 
RemoveDir(CFSTR path)994*f6dc9357SAndroid Build Coastguard Worker bool RemoveDir(CFSTR path)
995*f6dc9357SAndroid Build Coastguard Worker {
996*f6dc9357SAndroid Build Coastguard Worker   return (rmdir(path) == 0);
997*f6dc9357SAndroid Build Coastguard Worker }
998*f6dc9357SAndroid Build Coastguard Worker 
999*f6dc9357SAndroid Build Coastguard Worker 
My_CopyFile(CFSTR oldFile,CFSTR newFile,ICopyFileProgress * progress)1000*f6dc9357SAndroid Build Coastguard Worker static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile, ICopyFileProgress *progress)
1001*f6dc9357SAndroid Build Coastguard Worker {
1002*f6dc9357SAndroid Build Coastguard Worker   {
1003*f6dc9357SAndroid Build Coastguard Worker     NIO::COutFile outFile;
1004*f6dc9357SAndroid Build Coastguard Worker     if (!outFile.Create_NEW(newFile))
1005*f6dc9357SAndroid Build Coastguard Worker       return FALSE;
1006*f6dc9357SAndroid Build Coastguard Worker     NIO::CInFile inFile;
1007*f6dc9357SAndroid Build Coastguard Worker     if (!inFile.Open(oldFile))
1008*f6dc9357SAndroid Build Coastguard Worker       return FALSE;
1009*f6dc9357SAndroid Build Coastguard Worker 
1010*f6dc9357SAndroid Build Coastguard Worker     const size_t k_BufSize = 1 << 16;
1011*f6dc9357SAndroid Build Coastguard Worker     CAlignedBuffer1 buf(k_BufSize);
1012*f6dc9357SAndroid Build Coastguard Worker 
1013*f6dc9357SAndroid Build Coastguard Worker     UInt64 length = 0;
1014*f6dc9357SAndroid Build Coastguard Worker     if (progress && !inFile.GetLength(length))
1015*f6dc9357SAndroid Build Coastguard Worker       length = 0;
1016*f6dc9357SAndroid Build Coastguard Worker     UInt64 prev = 0;
1017*f6dc9357SAndroid Build Coastguard Worker     UInt64 cur = 0;
1018*f6dc9357SAndroid Build Coastguard Worker     for (;;)
1019*f6dc9357SAndroid Build Coastguard Worker     {
1020*f6dc9357SAndroid Build Coastguard Worker       const ssize_t num = inFile.read_part(buf, k_BufSize);
1021*f6dc9357SAndroid Build Coastguard Worker       if (num == 0)
1022*f6dc9357SAndroid Build Coastguard Worker         return TRUE;
1023*f6dc9357SAndroid Build Coastguard Worker       if (num < 0)
1024*f6dc9357SAndroid Build Coastguard Worker         break;
1025*f6dc9357SAndroid Build Coastguard Worker       size_t processed;
1026*f6dc9357SAndroid Build Coastguard Worker       const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed);
1027*f6dc9357SAndroid Build Coastguard Worker       if (num2 != num || processed != (size_t)num)
1028*f6dc9357SAndroid Build Coastguard Worker         break;
1029*f6dc9357SAndroid Build Coastguard Worker       cur += (size_t)num2;
1030*f6dc9357SAndroid Build Coastguard Worker       if (progress && cur - prev >= (1u << 20))
1031*f6dc9357SAndroid Build Coastguard Worker       {
1032*f6dc9357SAndroid Build Coastguard Worker         prev = cur;
1033*f6dc9357SAndroid Build Coastguard Worker         if (progress->CopyFileProgress(length, cur) != PROGRESS_CONTINUE)
1034*f6dc9357SAndroid Build Coastguard Worker         {
1035*f6dc9357SAndroid Build Coastguard Worker           errno = EINTR; // instead of WIN32::ERROR_REQUEST_ABORTED
1036*f6dc9357SAndroid Build Coastguard Worker           break;
1037*f6dc9357SAndroid Build Coastguard Worker         }
1038*f6dc9357SAndroid Build Coastguard Worker       }
1039*f6dc9357SAndroid Build Coastguard Worker     }
1040*f6dc9357SAndroid Build Coastguard Worker   }
1041*f6dc9357SAndroid Build Coastguard Worker   // There is file IO error or process was interrupted by user.
1042*f6dc9357SAndroid Build Coastguard Worker   // We close output file and delete it.
1043*f6dc9357SAndroid Build Coastguard Worker   // DeleteFileAlways doesn't change errno (if successed), but we restore errno.
1044*f6dc9357SAndroid Build Coastguard Worker   const int errno_save = errno;
1045*f6dc9357SAndroid Build Coastguard Worker   DeleteFileAlways(newFile);
1046*f6dc9357SAndroid Build Coastguard Worker   errno = errno_save;
1047*f6dc9357SAndroid Build Coastguard Worker   return FALSE;
1048*f6dc9357SAndroid Build Coastguard Worker }
1049*f6dc9357SAndroid Build Coastguard Worker 
1050*f6dc9357SAndroid Build Coastguard Worker 
MyMoveFile_with_Progress(CFSTR oldFile,CFSTR newFile,ICopyFileProgress * progress)1051*f6dc9357SAndroid Build Coastguard Worker bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile,
1052*f6dc9357SAndroid Build Coastguard Worker     ICopyFileProgress *progress)
1053*f6dc9357SAndroid Build Coastguard Worker {
1054*f6dc9357SAndroid Build Coastguard Worker   int res = rename(oldFile, newFile);
1055*f6dc9357SAndroid Build Coastguard Worker   if (res == 0)
1056*f6dc9357SAndroid Build Coastguard Worker     return true;
1057*f6dc9357SAndroid Build Coastguard Worker   if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem)
1058*f6dc9357SAndroid Build Coastguard Worker     return false;
1059*f6dc9357SAndroid Build Coastguard Worker 
1060*f6dc9357SAndroid Build Coastguard Worker   if (My_CopyFile(oldFile, newFile, progress) == FALSE)
1061*f6dc9357SAndroid Build Coastguard Worker     return false;
1062*f6dc9357SAndroid Build Coastguard Worker 
1063*f6dc9357SAndroid Build Coastguard Worker   struct stat info_file;
1064*f6dc9357SAndroid Build Coastguard Worker   res = stat(oldFile, &info_file);
1065*f6dc9357SAndroid Build Coastguard Worker   if (res != 0)
1066*f6dc9357SAndroid Build Coastguard Worker     return false;
1067*f6dc9357SAndroid Build Coastguard Worker 
1068*f6dc9357SAndroid Build Coastguard Worker   /*
1069*f6dc9357SAndroid Build Coastguard Worker   ret = chmod(dst,info_file.st_mode & g_umask.mask);
1070*f6dc9357SAndroid Build Coastguard Worker   */
1071*f6dc9357SAndroid Build Coastguard Worker   return (unlink(oldFile) == 0);
1072*f6dc9357SAndroid Build Coastguard Worker }
1073*f6dc9357SAndroid Build Coastguard Worker 
MyMoveFile(CFSTR oldFile,CFSTR newFile)1074*f6dc9357SAndroid Build Coastguard Worker bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
1075*f6dc9357SAndroid Build Coastguard Worker {
1076*f6dc9357SAndroid Build Coastguard Worker   return MyMoveFile_with_Progress(oldFile, newFile, NULL);
1077*f6dc9357SAndroid Build Coastguard Worker }
1078*f6dc9357SAndroid Build Coastguard Worker 
1079*f6dc9357SAndroid Build Coastguard Worker 
CreateDir(CFSTR path)1080*f6dc9357SAndroid Build Coastguard Worker bool CreateDir(CFSTR path)
1081*f6dc9357SAndroid Build Coastguard Worker {
1082*f6dc9357SAndroid Build Coastguard Worker   return (mkdir(path, 0777) == 0); // change it
1083*f6dc9357SAndroid Build Coastguard Worker }
1084*f6dc9357SAndroid Build Coastguard Worker 
CreateDir2(CFSTR path)1085*f6dc9357SAndroid Build Coastguard Worker static bool CreateDir2(CFSTR path)
1086*f6dc9357SAndroid Build Coastguard Worker {
1087*f6dc9357SAndroid Build Coastguard Worker   return (mkdir(path, 0777) == 0); // change it
1088*f6dc9357SAndroid Build Coastguard Worker }
1089*f6dc9357SAndroid Build Coastguard Worker 
1090*f6dc9357SAndroid Build Coastguard Worker 
DeleteFileAlways(CFSTR path)1091*f6dc9357SAndroid Build Coastguard Worker bool DeleteFileAlways(CFSTR path)
1092*f6dc9357SAndroid Build Coastguard Worker {
1093*f6dc9357SAndroid Build Coastguard Worker   return (remove(path) == 0);
1094*f6dc9357SAndroid Build Coastguard Worker }
1095*f6dc9357SAndroid Build Coastguard Worker 
SetCurrentDir(CFSTR path)1096*f6dc9357SAndroid Build Coastguard Worker bool SetCurrentDir(CFSTR path)
1097*f6dc9357SAndroid Build Coastguard Worker {
1098*f6dc9357SAndroid Build Coastguard Worker   return (chdir(path) == 0);
1099*f6dc9357SAndroid Build Coastguard Worker }
1100*f6dc9357SAndroid Build Coastguard Worker 
1101*f6dc9357SAndroid Build Coastguard Worker 
GetCurrentDir(FString & path)1102*f6dc9357SAndroid Build Coastguard Worker bool GetCurrentDir(FString &path)
1103*f6dc9357SAndroid Build Coastguard Worker {
1104*f6dc9357SAndroid Build Coastguard Worker   path.Empty();
1105*f6dc9357SAndroid Build Coastguard Worker 
1106*f6dc9357SAndroid Build Coastguard Worker   #define MY_PATH_MAX  PATH_MAX
1107*f6dc9357SAndroid Build Coastguard Worker   // #define MY_PATH_MAX  1024
1108*f6dc9357SAndroid Build Coastguard Worker 
1109*f6dc9357SAndroid Build Coastguard Worker   char s[MY_PATH_MAX + 1];
1110*f6dc9357SAndroid Build Coastguard Worker   char *res = getcwd(s, MY_PATH_MAX);
1111*f6dc9357SAndroid Build Coastguard Worker   if (res)
1112*f6dc9357SAndroid Build Coastguard Worker   {
1113*f6dc9357SAndroid Build Coastguard Worker     path = fas2fs(s);
1114*f6dc9357SAndroid Build Coastguard Worker     return true;
1115*f6dc9357SAndroid Build Coastguard Worker   }
1116*f6dc9357SAndroid Build Coastguard Worker   {
1117*f6dc9357SAndroid Build Coastguard Worker     // if (errno != ERANGE) return false;
1118*f6dc9357SAndroid Build Coastguard Worker     #if defined(__GLIBC__) || defined(__APPLE__)
1119*f6dc9357SAndroid Build Coastguard Worker     /* As an extension to the POSIX.1-2001 standard, glibc's getcwd()
1120*f6dc9357SAndroid Build Coastguard Worker        allocates the buffer dynamically using malloc(3) if buf is NULL. */
1121*f6dc9357SAndroid Build Coastguard Worker     res = getcwd(NULL, 0);
1122*f6dc9357SAndroid Build Coastguard Worker     if (res)
1123*f6dc9357SAndroid Build Coastguard Worker     {
1124*f6dc9357SAndroid Build Coastguard Worker       path = fas2fs(res);
1125*f6dc9357SAndroid Build Coastguard Worker       ::free(res);
1126*f6dc9357SAndroid Build Coastguard Worker       return true;
1127*f6dc9357SAndroid Build Coastguard Worker     }
1128*f6dc9357SAndroid Build Coastguard Worker     #endif
1129*f6dc9357SAndroid Build Coastguard Worker     return false;
1130*f6dc9357SAndroid Build Coastguard Worker   }
1131*f6dc9357SAndroid Build Coastguard Worker }
1132*f6dc9357SAndroid Build Coastguard Worker 
1133*f6dc9357SAndroid Build Coastguard Worker 
1134*f6dc9357SAndroid Build Coastguard Worker 
1135*f6dc9357SAndroid Build Coastguard Worker // #undef UTIME_OMIT // to debug
1136*f6dc9357SAndroid Build Coastguard Worker 
1137*f6dc9357SAndroid Build Coastguard Worker #ifndef UTIME_OMIT
1138*f6dc9357SAndroid Build Coastguard Worker   /* we can define UTIME_OMIT for debian and another systems.
1139*f6dc9357SAndroid Build Coastguard Worker      Is it OK to define UTIME_OMIT to -2 here, if UTIME_OMIT is not defined? */
1140*f6dc9357SAndroid Build Coastguard Worker   // #define UTIME_OMIT -2
1141*f6dc9357SAndroid Build Coastguard Worker #endif
1142*f6dc9357SAndroid Build Coastguard Worker 
1143*f6dc9357SAndroid Build Coastguard Worker 
1144*f6dc9357SAndroid Build Coastguard Worker 
1145*f6dc9357SAndroid Build Coastguard Worker 
1146*f6dc9357SAndroid Build Coastguard Worker 
SetDirTime(CFSTR path,const CFiTime * cTime,const CFiTime * aTime,const CFiTime * mTime)1147*f6dc9357SAndroid Build Coastguard Worker bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)
1148*f6dc9357SAndroid Build Coastguard Worker {
1149*f6dc9357SAndroid Build Coastguard Worker   // need testing
1150*f6dc9357SAndroid Build Coastguard Worker   /*
1151*f6dc9357SAndroid Build Coastguard Worker   struct utimbuf buf;
1152*f6dc9357SAndroid Build Coastguard Worker   struct stat st;
1153*f6dc9357SAndroid Build Coastguard Worker   UNUSED_VAR(cTime)
1154*f6dc9357SAndroid Build Coastguard Worker 
1155*f6dc9357SAndroid Build Coastguard Worker   printf("\nstat = %s\n", path);
1156*f6dc9357SAndroid Build Coastguard Worker   int ret = stat(path, &st);
1157*f6dc9357SAndroid Build Coastguard Worker 
1158*f6dc9357SAndroid Build Coastguard Worker   if (ret == 0)
1159*f6dc9357SAndroid Build Coastguard Worker   {
1160*f6dc9357SAndroid Build Coastguard Worker     buf.actime  = st.st_atime;
1161*f6dc9357SAndroid Build Coastguard Worker     buf.modtime = st.st_mtime;
1162*f6dc9357SAndroid Build Coastguard Worker   }
1163*f6dc9357SAndroid Build Coastguard Worker   else
1164*f6dc9357SAndroid Build Coastguard Worker   {
1165*f6dc9357SAndroid Build Coastguard Worker     time_t cur_time = time(0);
1166*f6dc9357SAndroid Build Coastguard Worker     buf.actime  = cur_time;
1167*f6dc9357SAndroid Build Coastguard Worker     buf.modtime = cur_time;
1168*f6dc9357SAndroid Build Coastguard Worker   }
1169*f6dc9357SAndroid Build Coastguard Worker 
1170*f6dc9357SAndroid Build Coastguard Worker   if (aTime)
1171*f6dc9357SAndroid Build Coastguard Worker   {
1172*f6dc9357SAndroid Build Coastguard Worker     UInt32 ut;
1173*f6dc9357SAndroid Build Coastguard Worker     if (NTime::FileTimeToUnixTime(*aTime, ut))
1174*f6dc9357SAndroid Build Coastguard Worker       buf.actime = ut;
1175*f6dc9357SAndroid Build Coastguard Worker   }
1176*f6dc9357SAndroid Build Coastguard Worker 
1177*f6dc9357SAndroid Build Coastguard Worker   if (mTime)
1178*f6dc9357SAndroid Build Coastguard Worker   {
1179*f6dc9357SAndroid Build Coastguard Worker     UInt32 ut;
1180*f6dc9357SAndroid Build Coastguard Worker     if (NTime::FileTimeToUnixTime(*mTime, ut))
1181*f6dc9357SAndroid Build Coastguard Worker       buf.modtime = ut;
1182*f6dc9357SAndroid Build Coastguard Worker   }
1183*f6dc9357SAndroid Build Coastguard Worker 
1184*f6dc9357SAndroid Build Coastguard Worker   return utime(path, &buf) == 0;
1185*f6dc9357SAndroid Build Coastguard Worker   */
1186*f6dc9357SAndroid Build Coastguard Worker 
1187*f6dc9357SAndroid Build Coastguard Worker   // if (!aTime && !mTime) return true;
1188*f6dc9357SAndroid Build Coastguard Worker 
1189*f6dc9357SAndroid Build Coastguard Worker   struct timespec times[2];
1190*f6dc9357SAndroid Build Coastguard Worker   UNUSED_VAR(cTime)
1191*f6dc9357SAndroid Build Coastguard Worker 
1192*f6dc9357SAndroid Build Coastguard Worker   bool needChange;
1193*f6dc9357SAndroid Build Coastguard Worker   needChange  = FiTime_To_timespec(aTime, times[0]);
1194*f6dc9357SAndroid Build Coastguard Worker   needChange |= FiTime_To_timespec(mTime, times[1]);
1195*f6dc9357SAndroid Build Coastguard Worker 
1196*f6dc9357SAndroid Build Coastguard Worker   /*
1197*f6dc9357SAndroid Build Coastguard Worker   if (mTime)
1198*f6dc9357SAndroid Build Coastguard Worker   {
1199*f6dc9357SAndroid Build Coastguard Worker     printf("\n time = %ld.%9ld\n", mTime->tv_sec, mTime->tv_nsec);
1200*f6dc9357SAndroid Build Coastguard Worker   }
1201*f6dc9357SAndroid Build Coastguard Worker   */
1202*f6dc9357SAndroid Build Coastguard Worker 
1203*f6dc9357SAndroid Build Coastguard Worker   if (!needChange)
1204*f6dc9357SAndroid Build Coastguard Worker     return true;
1205*f6dc9357SAndroid Build Coastguard Worker   const int flags = 0; // follow link
1206*f6dc9357SAndroid Build Coastguard Worker     // = AT_SYMLINK_NOFOLLOW; // don't follow link
1207*f6dc9357SAndroid Build Coastguard Worker   return utimensat(AT_FDCWD, path, times, flags) == 0;
1208*f6dc9357SAndroid Build Coastguard Worker }
1209*f6dc9357SAndroid Build Coastguard Worker 
1210*f6dc9357SAndroid Build Coastguard Worker 
1211*f6dc9357SAndroid Build Coastguard Worker 
1212*f6dc9357SAndroid Build Coastguard Worker struct C_umask
1213*f6dc9357SAndroid Build Coastguard Worker {
1214*f6dc9357SAndroid Build Coastguard Worker   mode_t mask;
1215*f6dc9357SAndroid Build Coastguard Worker 
C_umaskNWindows::NFile::NDir::C_umask1216*f6dc9357SAndroid Build Coastguard Worker   C_umask()
1217*f6dc9357SAndroid Build Coastguard Worker   {
1218*f6dc9357SAndroid Build Coastguard Worker     /* by security reasons we restrict attributes according
1219*f6dc9357SAndroid Build Coastguard Worker        with process's file mode creation mask (umask) */
1220*f6dc9357SAndroid Build Coastguard Worker     const mode_t um = umask(0); // octal :0022 is expected
1221*f6dc9357SAndroid Build Coastguard Worker     mask = 0777 & (~um);        // octal: 0755 is expected
1222*f6dc9357SAndroid Build Coastguard Worker     umask(um);  // restore the umask
1223*f6dc9357SAndroid Build Coastguard Worker     // printf("\n umask = 0%03o mask = 0%03o\n", um, mask);
1224*f6dc9357SAndroid Build Coastguard Worker 
1225*f6dc9357SAndroid Build Coastguard Worker     // mask = 0777; // debug we can disable the restriction:
1226*f6dc9357SAndroid Build Coastguard Worker   }
1227*f6dc9357SAndroid Build Coastguard Worker };
1228*f6dc9357SAndroid Build Coastguard Worker 
1229*f6dc9357SAndroid Build Coastguard Worker static C_umask g_umask;
1230*f6dc9357SAndroid Build Coastguard Worker 
1231*f6dc9357SAndroid Build Coastguard Worker // #define PRF(x) x;
1232*f6dc9357SAndroid Build Coastguard Worker #define PRF(x)
1233*f6dc9357SAndroid Build Coastguard Worker 
1234*f6dc9357SAndroid Build Coastguard Worker #define TRACE_SetFileAttrib(msg) \
1235*f6dc9357SAndroid Build Coastguard Worker   PRF(printf("\nSetFileAttrib(%s, %x) : %s\n", (const char *)path, attrib, msg);)
1236*f6dc9357SAndroid Build Coastguard Worker 
1237*f6dc9357SAndroid Build Coastguard Worker #define TRACE_chmod(s, mode) \
1238*f6dc9357SAndroid Build Coastguard Worker   PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode));)
1239*f6dc9357SAndroid Build Coastguard Worker 
my_chown(CFSTR path,uid_t owner,gid_t group)1240*f6dc9357SAndroid Build Coastguard Worker int my_chown(CFSTR path, uid_t owner, gid_t group)
1241*f6dc9357SAndroid Build Coastguard Worker {
1242*f6dc9357SAndroid Build Coastguard Worker   return chown(path, owner, group);
1243*f6dc9357SAndroid Build Coastguard Worker }
1244*f6dc9357SAndroid Build Coastguard Worker 
SetFileAttrib_PosixHighDetect(CFSTR path,DWORD attrib)1245*f6dc9357SAndroid Build Coastguard Worker bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
1246*f6dc9357SAndroid Build Coastguard Worker {
1247*f6dc9357SAndroid Build Coastguard Worker   TRACE_SetFileAttrib("")
1248*f6dc9357SAndroid Build Coastguard Worker 
1249*f6dc9357SAndroid Build Coastguard Worker   struct stat st;
1250*f6dc9357SAndroid Build Coastguard Worker 
1251*f6dc9357SAndroid Build Coastguard Worker   bool use_lstat = true;
1252*f6dc9357SAndroid Build Coastguard Worker   if (use_lstat)
1253*f6dc9357SAndroid Build Coastguard Worker   {
1254*f6dc9357SAndroid Build Coastguard Worker     if (lstat(path, &st) != 0)
1255*f6dc9357SAndroid Build Coastguard Worker     {
1256*f6dc9357SAndroid Build Coastguard Worker       TRACE_SetFileAttrib("bad lstat()")
1257*f6dc9357SAndroid Build Coastguard Worker       return false;
1258*f6dc9357SAndroid Build Coastguard Worker     }
1259*f6dc9357SAndroid Build Coastguard Worker     // TRACE_chmod("lstat", st.st_mode);
1260*f6dc9357SAndroid Build Coastguard Worker   }
1261*f6dc9357SAndroid Build Coastguard Worker   else
1262*f6dc9357SAndroid Build Coastguard Worker   {
1263*f6dc9357SAndroid Build Coastguard Worker     if (stat(path, &st) != 0)
1264*f6dc9357SAndroid Build Coastguard Worker     {
1265*f6dc9357SAndroid Build Coastguard Worker       TRACE_SetFileAttrib("bad stat()")
1266*f6dc9357SAndroid Build Coastguard Worker       return false;
1267*f6dc9357SAndroid Build Coastguard Worker     }
1268*f6dc9357SAndroid Build Coastguard Worker   }
1269*f6dc9357SAndroid Build Coastguard Worker 
1270*f6dc9357SAndroid Build Coastguard Worker   if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION)
1271*f6dc9357SAndroid Build Coastguard Worker   {
1272*f6dc9357SAndroid Build Coastguard Worker     TRACE_SetFileAttrib("attrib & FILE_ATTRIBUTE_UNIX_EXTENSION")
1273*f6dc9357SAndroid Build Coastguard Worker     st.st_mode = attrib >> 16;
1274*f6dc9357SAndroid Build Coastguard Worker     if (S_ISDIR(st.st_mode))
1275*f6dc9357SAndroid Build Coastguard Worker     {
1276*f6dc9357SAndroid Build Coastguard Worker       // user/7z must be able to create files in this directory
1277*f6dc9357SAndroid Build Coastguard Worker       st.st_mode |= (S_IRUSR | S_IWUSR | S_IXUSR);
1278*f6dc9357SAndroid Build Coastguard Worker     }
1279*f6dc9357SAndroid Build Coastguard Worker     else if (!S_ISREG(st.st_mode))
1280*f6dc9357SAndroid Build Coastguard Worker       return true;
1281*f6dc9357SAndroid Build Coastguard Worker   }
1282*f6dc9357SAndroid Build Coastguard Worker   else if (S_ISLNK(st.st_mode))
1283*f6dc9357SAndroid Build Coastguard Worker   {
1284*f6dc9357SAndroid Build Coastguard Worker     /* for most systems: permissions for symlinks are fixed to rwxrwxrwx.
1285*f6dc9357SAndroid Build Coastguard Worker        so we don't need chmod() for symlinks. */
1286*f6dc9357SAndroid Build Coastguard Worker     return true;
1287*f6dc9357SAndroid Build Coastguard Worker     // SetLastError(ENOSYS);
1288*f6dc9357SAndroid Build Coastguard Worker     // return false;
1289*f6dc9357SAndroid Build Coastguard Worker   }
1290*f6dc9357SAndroid Build Coastguard Worker   else
1291*f6dc9357SAndroid Build Coastguard Worker   {
1292*f6dc9357SAndroid Build Coastguard Worker     TRACE_SetFileAttrib("Only Windows Attributes")
1293*f6dc9357SAndroid Build Coastguard Worker     // Only Windows Attributes
1294*f6dc9357SAndroid Build Coastguard Worker     if (S_ISDIR(st.st_mode)
1295*f6dc9357SAndroid Build Coastguard Worker         || (attrib & FILE_ATTRIBUTE_READONLY) == 0)
1296*f6dc9357SAndroid Build Coastguard Worker       return true;
1297*f6dc9357SAndroid Build Coastguard Worker     st.st_mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions
1298*f6dc9357SAndroid Build Coastguard Worker   }
1299*f6dc9357SAndroid Build Coastguard Worker 
1300*f6dc9357SAndroid Build Coastguard Worker   int res;
1301*f6dc9357SAndroid Build Coastguard Worker   /*
1302*f6dc9357SAndroid Build Coastguard Worker   if (S_ISLNK(st.st_mode))
1303*f6dc9357SAndroid Build Coastguard Worker   {
1304*f6dc9357SAndroid Build Coastguard Worker     printf("\nfchmodat()\n");
1305*f6dc9357SAndroid Build Coastguard Worker     TRACE_chmod(path, (st.st_mode) & g_umask.mask)
1306*f6dc9357SAndroid Build Coastguard Worker     // AT_SYMLINK_NOFOLLOW is not implemted still in Linux.
1307*f6dc9357SAndroid Build Coastguard Worker     res = fchmodat(AT_FDCWD, path, (st.st_mode) & g_umask.mask,
1308*f6dc9357SAndroid Build Coastguard Worker         S_ISLNK(st.st_mode) ? AT_SYMLINK_NOFOLLOW : 0);
1309*f6dc9357SAndroid Build Coastguard Worker   }
1310*f6dc9357SAndroid Build Coastguard Worker   else
1311*f6dc9357SAndroid Build Coastguard Worker   */
1312*f6dc9357SAndroid Build Coastguard Worker   {
1313*f6dc9357SAndroid Build Coastguard Worker     TRACE_chmod(path, (st.st_mode) & g_umask.mask)
1314*f6dc9357SAndroid Build Coastguard Worker     res = chmod(path, (st.st_mode) & g_umask.mask);
1315*f6dc9357SAndroid Build Coastguard Worker   }
1316*f6dc9357SAndroid Build Coastguard Worker   // TRACE_SetFileAttrib("End")
1317*f6dc9357SAndroid Build Coastguard Worker   return (res == 0);
1318*f6dc9357SAndroid Build Coastguard Worker }
1319*f6dc9357SAndroid Build Coastguard Worker 
1320*f6dc9357SAndroid Build Coastguard Worker 
MyCreateHardLink(CFSTR newFileName,CFSTR existFileName)1321*f6dc9357SAndroid Build Coastguard Worker bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
1322*f6dc9357SAndroid Build Coastguard Worker {
1323*f6dc9357SAndroid Build Coastguard Worker   PRF(printf("\nhard link() %s -> %s\n", newFileName, existFileName);)
1324*f6dc9357SAndroid Build Coastguard Worker   return (link(existFileName, newFileName) == 0);
1325*f6dc9357SAndroid Build Coastguard Worker }
1326*f6dc9357SAndroid Build Coastguard Worker 
1327*f6dc9357SAndroid Build Coastguard Worker #endif // !_WIN32
1328*f6dc9357SAndroid Build Coastguard Worker 
1329*f6dc9357SAndroid Build Coastguard Worker // #endif
1330*f6dc9357SAndroid Build Coastguard Worker 
1331*f6dc9357SAndroid Build Coastguard Worker }}}
1332