1370b324cSopenharmony_ci// Windows/FileDir.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci 6370b324cSopenharmony_ci#ifndef _WIN32 7370b324cSopenharmony_ci#include <stdio.h> 8370b324cSopenharmony_ci#include <stdlib.h> 9370b324cSopenharmony_ci#include <errno.h> 10370b324cSopenharmony_ci#include <limits.h> 11370b324cSopenharmony_ci#include <unistd.h> 12370b324cSopenharmony_ci#include <time.h> 13370b324cSopenharmony_ci#include <utime.h> 14370b324cSopenharmony_ci#include <fcntl.h> 15370b324cSopenharmony_ci#include <sys/stat.h> 16370b324cSopenharmony_ci#include <sys/types.h> 17370b324cSopenharmony_ci 18370b324cSopenharmony_ci#include "../Common/StringConvert.h" 19370b324cSopenharmony_ci#include "../Common/C_FileIO.h" 20370b324cSopenharmony_ci#endif 21370b324cSopenharmony_ci 22370b324cSopenharmony_ci#include "FileDir.h" 23370b324cSopenharmony_ci#include "FileFind.h" 24370b324cSopenharmony_ci#include "FileName.h" 25370b324cSopenharmony_ci 26370b324cSopenharmony_ci#ifndef _UNICODE 27370b324cSopenharmony_ciextern bool g_IsNT; 28370b324cSopenharmony_ci#endif 29370b324cSopenharmony_ci 30370b324cSopenharmony_ciusing namespace NWindows; 31370b324cSopenharmony_ciusing namespace NFile; 32370b324cSopenharmony_ciusing namespace NName; 33370b324cSopenharmony_ci 34370b324cSopenharmony_ci#ifndef _WIN32 35370b324cSopenharmony_ci 36370b324cSopenharmony_cistatic bool FiTime_To_timespec(const CFiTime *ft, timespec &ts) 37370b324cSopenharmony_ci{ 38370b324cSopenharmony_ci if (ft) 39370b324cSopenharmony_ci { 40370b324cSopenharmony_ci ts = *ft; 41370b324cSopenharmony_ci return true; 42370b324cSopenharmony_ci } 43370b324cSopenharmony_ci // else 44370b324cSopenharmony_ci { 45370b324cSopenharmony_ci ts.tv_sec = 0; 46370b324cSopenharmony_ci ts.tv_nsec = 47370b324cSopenharmony_ci #ifdef UTIME_OMIT 48370b324cSopenharmony_ci UTIME_OMIT; // -2 keep old timesptamp 49370b324cSopenharmony_ci #else 50370b324cSopenharmony_ci // UTIME_NOW; -1 // set to the current time 51370b324cSopenharmony_ci 0; 52370b324cSopenharmony_ci #endif 53370b324cSopenharmony_ci return false; 54370b324cSopenharmony_ci } 55370b324cSopenharmony_ci} 56370b324cSopenharmony_ci#endif 57370b324cSopenharmony_ci 58370b324cSopenharmony_cinamespace NWindows { 59370b324cSopenharmony_cinamespace NFile { 60370b324cSopenharmony_cinamespace NDir { 61370b324cSopenharmony_ci 62370b324cSopenharmony_ci#ifdef _WIN32 63370b324cSopenharmony_ci 64370b324cSopenharmony_ci#ifndef UNDER_CE 65370b324cSopenharmony_ci 66370b324cSopenharmony_cibool GetWindowsDir(FString &path) 67370b324cSopenharmony_ci{ 68370b324cSopenharmony_ci const unsigned kBufSize = MAX_PATH + 16; 69370b324cSopenharmony_ci UINT len; 70370b324cSopenharmony_ci #ifndef _UNICODE 71370b324cSopenharmony_ci if (!g_IsNT) 72370b324cSopenharmony_ci { 73370b324cSopenharmony_ci TCHAR s[kBufSize + 1]; 74370b324cSopenharmony_ci s[0] = 0; 75370b324cSopenharmony_ci len = ::GetWindowsDirectory(s, kBufSize); 76370b324cSopenharmony_ci path = fas2fs(s); 77370b324cSopenharmony_ci } 78370b324cSopenharmony_ci else 79370b324cSopenharmony_ci #endif 80370b324cSopenharmony_ci { 81370b324cSopenharmony_ci WCHAR s[kBufSize + 1]; 82370b324cSopenharmony_ci s[0] = 0; 83370b324cSopenharmony_ci len = ::GetWindowsDirectoryW(s, kBufSize); 84370b324cSopenharmony_ci path = us2fs(s); 85370b324cSopenharmony_ci } 86370b324cSopenharmony_ci return (len != 0 && len < kBufSize); 87370b324cSopenharmony_ci} 88370b324cSopenharmony_ci 89370b324cSopenharmony_ci 90370b324cSopenharmony_ci/* 91370b324cSopenharmony_cinew DOCs for GetSystemDirectory: 92370b324cSopenharmony_ci returned path does not end with a backslash unless the 93370b324cSopenharmony_ci system directory is the root directory. 94370b324cSopenharmony_ci*/ 95370b324cSopenharmony_ci 96370b324cSopenharmony_cibool GetSystemDir(FString &path) 97370b324cSopenharmony_ci{ 98370b324cSopenharmony_ci const unsigned kBufSize = MAX_PATH + 16; 99370b324cSopenharmony_ci UINT len; 100370b324cSopenharmony_ci #ifndef _UNICODE 101370b324cSopenharmony_ci if (!g_IsNT) 102370b324cSopenharmony_ci { 103370b324cSopenharmony_ci TCHAR s[kBufSize + 1]; 104370b324cSopenharmony_ci s[0] = 0; 105370b324cSopenharmony_ci len = ::GetSystemDirectory(s, kBufSize); 106370b324cSopenharmony_ci path = fas2fs(s); 107370b324cSopenharmony_ci } 108370b324cSopenharmony_ci else 109370b324cSopenharmony_ci #endif 110370b324cSopenharmony_ci { 111370b324cSopenharmony_ci WCHAR s[kBufSize + 1]; 112370b324cSopenharmony_ci s[0] = 0; 113370b324cSopenharmony_ci len = ::GetSystemDirectoryW(s, kBufSize); 114370b324cSopenharmony_ci path = us2fs(s); 115370b324cSopenharmony_ci } 116370b324cSopenharmony_ci return (len != 0 && len < kBufSize); 117370b324cSopenharmony_ci} 118370b324cSopenharmony_ci#endif // UNDER_CE 119370b324cSopenharmony_ci 120370b324cSopenharmony_ci 121370b324cSopenharmony_cibool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) 122370b324cSopenharmony_ci{ 123370b324cSopenharmony_ci #ifndef _UNICODE 124370b324cSopenharmony_ci if (!g_IsNT) 125370b324cSopenharmony_ci { 126370b324cSopenharmony_ci ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 127370b324cSopenharmony_ci return false; 128370b324cSopenharmony_ci } 129370b324cSopenharmony_ci #endif 130370b324cSopenharmony_ci 131370b324cSopenharmony_ci HANDLE hDir = INVALID_HANDLE_VALUE; 132370b324cSopenharmony_ci IF_USE_MAIN_PATH 133370b324cSopenharmony_ci hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 134370b324cSopenharmony_ci NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); 135370b324cSopenharmony_ci #ifdef Z7_LONG_PATH 136370b324cSopenharmony_ci if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH) 137370b324cSopenharmony_ci { 138370b324cSopenharmony_ci UString superPath; 139370b324cSopenharmony_ci if (GetSuperPath(path, superPath, USE_MAIN_PATH)) 140370b324cSopenharmony_ci hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 141370b324cSopenharmony_ci NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); 142370b324cSopenharmony_ci } 143370b324cSopenharmony_ci #endif 144370b324cSopenharmony_ci 145370b324cSopenharmony_ci bool res = false; 146370b324cSopenharmony_ci if (hDir != INVALID_HANDLE_VALUE) 147370b324cSopenharmony_ci { 148370b324cSopenharmony_ci res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime)); 149370b324cSopenharmony_ci ::CloseHandle(hDir); 150370b324cSopenharmony_ci } 151370b324cSopenharmony_ci return res; 152370b324cSopenharmony_ci} 153370b324cSopenharmony_ci 154370b324cSopenharmony_ci 155370b324cSopenharmony_ci 156370b324cSopenharmony_cibool SetFileAttrib(CFSTR path, DWORD attrib) 157370b324cSopenharmony_ci{ 158370b324cSopenharmony_ci #ifndef _UNICODE 159370b324cSopenharmony_ci if (!g_IsNT) 160370b324cSopenharmony_ci { 161370b324cSopenharmony_ci if (::SetFileAttributes(fs2fas(path), attrib)) 162370b324cSopenharmony_ci return true; 163370b324cSopenharmony_ci } 164370b324cSopenharmony_ci else 165370b324cSopenharmony_ci #endif 166370b324cSopenharmony_ci { 167370b324cSopenharmony_ci IF_USE_MAIN_PATH 168370b324cSopenharmony_ci if (::SetFileAttributesW(fs2us(path), attrib)) 169370b324cSopenharmony_ci return true; 170370b324cSopenharmony_ci #ifdef Z7_LONG_PATH 171370b324cSopenharmony_ci if (USE_SUPER_PATH) 172370b324cSopenharmony_ci { 173370b324cSopenharmony_ci UString superPath; 174370b324cSopenharmony_ci if (GetSuperPath(path, superPath, USE_MAIN_PATH)) 175370b324cSopenharmony_ci return BOOLToBool(::SetFileAttributesW(superPath, attrib)); 176370b324cSopenharmony_ci } 177370b324cSopenharmony_ci #endif 178370b324cSopenharmony_ci } 179370b324cSopenharmony_ci return false; 180370b324cSopenharmony_ci} 181370b324cSopenharmony_ci 182370b324cSopenharmony_ci 183370b324cSopenharmony_cibool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) 184370b324cSopenharmony_ci{ 185370b324cSopenharmony_ci #ifdef _WIN32 186370b324cSopenharmony_ci if ((attrib & 0xF0000000) != 0) 187370b324cSopenharmony_ci attrib &= 0x3FFF; 188370b324cSopenharmony_ci #endif 189370b324cSopenharmony_ci return SetFileAttrib(path, attrib); 190370b324cSopenharmony_ci} 191370b324cSopenharmony_ci 192370b324cSopenharmony_ci 193370b324cSopenharmony_cibool RemoveDir(CFSTR path) 194370b324cSopenharmony_ci{ 195370b324cSopenharmony_ci #ifndef _UNICODE 196370b324cSopenharmony_ci if (!g_IsNT) 197370b324cSopenharmony_ci { 198370b324cSopenharmony_ci if (::RemoveDirectory(fs2fas(path))) 199370b324cSopenharmony_ci return true; 200370b324cSopenharmony_ci } 201370b324cSopenharmony_ci else 202370b324cSopenharmony_ci #endif 203370b324cSopenharmony_ci { 204370b324cSopenharmony_ci IF_USE_MAIN_PATH 205370b324cSopenharmony_ci if (::RemoveDirectoryW(fs2us(path))) 206370b324cSopenharmony_ci return true; 207370b324cSopenharmony_ci #ifdef Z7_LONG_PATH 208370b324cSopenharmony_ci if (USE_SUPER_PATH) 209370b324cSopenharmony_ci { 210370b324cSopenharmony_ci UString superPath; 211370b324cSopenharmony_ci if (GetSuperPath(path, superPath, USE_MAIN_PATH)) 212370b324cSopenharmony_ci return BOOLToBool(::RemoveDirectoryW(superPath)); 213370b324cSopenharmony_ci } 214370b324cSopenharmony_ci #endif 215370b324cSopenharmony_ci } 216370b324cSopenharmony_ci return false; 217370b324cSopenharmony_ci} 218370b324cSopenharmony_ci 219370b324cSopenharmony_ci 220370b324cSopenharmony_cibool MyMoveFile(CFSTR oldFile, CFSTR newFile) 221370b324cSopenharmony_ci{ 222370b324cSopenharmony_ci #ifndef _UNICODE 223370b324cSopenharmony_ci if (!g_IsNT) 224370b324cSopenharmony_ci { 225370b324cSopenharmony_ci if (::MoveFile(fs2fas(oldFile), fs2fas(newFile))) 226370b324cSopenharmony_ci return true; 227370b324cSopenharmony_ci } 228370b324cSopenharmony_ci else 229370b324cSopenharmony_ci #endif 230370b324cSopenharmony_ci { 231370b324cSopenharmony_ci IF_USE_MAIN_PATH_2(oldFile, newFile) 232370b324cSopenharmony_ci { 233370b324cSopenharmony_ci if (::MoveFileW(fs2us(oldFile), fs2us(newFile))) 234370b324cSopenharmony_ci return true; 235370b324cSopenharmony_ci } 236370b324cSopenharmony_ci #ifdef Z7_LONG_PATH 237370b324cSopenharmony_ci if (USE_SUPER_PATH_2) 238370b324cSopenharmony_ci { 239370b324cSopenharmony_ci UString d1, d2; 240370b324cSopenharmony_ci if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2)) 241370b324cSopenharmony_ci return BOOLToBool(::MoveFileW(d1, d2)); 242370b324cSopenharmony_ci } 243370b324cSopenharmony_ci #endif 244370b324cSopenharmony_ci } 245370b324cSopenharmony_ci return false; 246370b324cSopenharmony_ci} 247370b324cSopenharmony_ci 248370b324cSopenharmony_ci#ifndef UNDER_CE 249370b324cSopenharmony_ciEXTERN_C_BEGIN 250370b324cSopenharmony_citypedef BOOL (WINAPI *Func_CreateHardLinkW)( 251370b324cSopenharmony_ci LPCWSTR lpFileName, 252370b324cSopenharmony_ci LPCWSTR lpExistingFileName, 253370b324cSopenharmony_ci LPSECURITY_ATTRIBUTES lpSecurityAttributes 254370b324cSopenharmony_ci ); 255370b324cSopenharmony_ciEXTERN_C_END 256370b324cSopenharmony_ci#endif // UNDER_CE 257370b324cSopenharmony_ci 258370b324cSopenharmony_cibool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) 259370b324cSopenharmony_ci{ 260370b324cSopenharmony_ci #ifndef _UNICODE 261370b324cSopenharmony_ci if (!g_IsNT) 262370b324cSopenharmony_ci { 263370b324cSopenharmony_ci SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 264370b324cSopenharmony_ci return false; 265370b324cSopenharmony_ci /* 266370b324cSopenharmony_ci if (::CreateHardLink(fs2fas(newFileName), fs2fas(existFileName), NULL)) 267370b324cSopenharmony_ci return true; 268370b324cSopenharmony_ci */ 269370b324cSopenharmony_ci } 270370b324cSopenharmony_ci else 271370b324cSopenharmony_ci #endif 272370b324cSopenharmony_ci { 273370b324cSopenharmony_ci const 274370b324cSopenharmony_ci Func_CreateHardLinkW 275370b324cSopenharmony_ci my_CreateHardLinkW = Z7_GET_PROC_ADDRESS( 276370b324cSopenharmony_ci Func_CreateHardLinkW, ::GetModuleHandleW(L"kernel32.dll"), 277370b324cSopenharmony_ci "CreateHardLinkW"); 278370b324cSopenharmony_ci if (!my_CreateHardLinkW) 279370b324cSopenharmony_ci return false; 280370b324cSopenharmony_ci IF_USE_MAIN_PATH_2(newFileName, existFileName) 281370b324cSopenharmony_ci { 282370b324cSopenharmony_ci if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL)) 283370b324cSopenharmony_ci return true; 284370b324cSopenharmony_ci } 285370b324cSopenharmony_ci #ifdef Z7_LONG_PATH 286370b324cSopenharmony_ci if (USE_SUPER_PATH_2) 287370b324cSopenharmony_ci { 288370b324cSopenharmony_ci UString d1, d2; 289370b324cSopenharmony_ci if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2)) 290370b324cSopenharmony_ci return BOOLToBool(my_CreateHardLinkW(d1, d2, NULL)); 291370b324cSopenharmony_ci } 292370b324cSopenharmony_ci #endif 293370b324cSopenharmony_ci } 294370b324cSopenharmony_ci return false; 295370b324cSopenharmony_ci} 296370b324cSopenharmony_ci 297370b324cSopenharmony_ci 298370b324cSopenharmony_ci/* 299370b324cSopenharmony_ciWinXP-64 CreateDir(): 300370b324cSopenharmony_ci "" - ERROR_PATH_NOT_FOUND 301370b324cSopenharmony_ci \ - ERROR_ACCESS_DENIED 302370b324cSopenharmony_ci C:\ - ERROR_ACCESS_DENIED, if there is such drive, 303370b324cSopenharmony_ci 304370b324cSopenharmony_ci D:\folder - ERROR_PATH_NOT_FOUND, if there is no such drive, 305370b324cSopenharmony_ci C:\nonExistent\folder - ERROR_PATH_NOT_FOUND 306370b324cSopenharmony_ci 307370b324cSopenharmony_ci C:\existFolder - ERROR_ALREADY_EXISTS 308370b324cSopenharmony_ci C:\existFolder\ - ERROR_ALREADY_EXISTS 309370b324cSopenharmony_ci 310370b324cSopenharmony_ci C:\folder - OK 311370b324cSopenharmony_ci C:\folder\ - OK 312370b324cSopenharmony_ci 313370b324cSopenharmony_ci \\Server\nonExistent - ERROR_BAD_NETPATH 314370b324cSopenharmony_ci \\Server\Share_Readonly - ERROR_ACCESS_DENIED 315370b324cSopenharmony_ci \\Server\Share - ERROR_ALREADY_EXISTS 316370b324cSopenharmony_ci 317370b324cSopenharmony_ci \\Server\Share_NTFS_drive - ERROR_ACCESS_DENIED 318370b324cSopenharmony_ci \\Server\Share_FAT_drive - ERROR_ALREADY_EXISTS 319370b324cSopenharmony_ci*/ 320370b324cSopenharmony_ci 321370b324cSopenharmony_cibool CreateDir(CFSTR path) 322370b324cSopenharmony_ci{ 323370b324cSopenharmony_ci #ifndef _UNICODE 324370b324cSopenharmony_ci if (!g_IsNT) 325370b324cSopenharmony_ci { 326370b324cSopenharmony_ci if (::CreateDirectory(fs2fas(path), NULL)) 327370b324cSopenharmony_ci return true; 328370b324cSopenharmony_ci } 329370b324cSopenharmony_ci else 330370b324cSopenharmony_ci #endif 331370b324cSopenharmony_ci { 332370b324cSopenharmony_ci IF_USE_MAIN_PATH 333370b324cSopenharmony_ci if (::CreateDirectoryW(fs2us(path), NULL)) 334370b324cSopenharmony_ci return true; 335370b324cSopenharmony_ci #ifdef Z7_LONG_PATH 336370b324cSopenharmony_ci if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH) 337370b324cSopenharmony_ci { 338370b324cSopenharmony_ci UString superPath; 339370b324cSopenharmony_ci if (GetSuperPath(path, superPath, USE_MAIN_PATH)) 340370b324cSopenharmony_ci return BOOLToBool(::CreateDirectoryW(superPath, NULL)); 341370b324cSopenharmony_ci } 342370b324cSopenharmony_ci #endif 343370b324cSopenharmony_ci } 344370b324cSopenharmony_ci return false; 345370b324cSopenharmony_ci} 346370b324cSopenharmony_ci 347370b324cSopenharmony_ci/* 348370b324cSopenharmony_ci CreateDir2 returns true, if directory can contain files after the call (two cases): 349370b324cSopenharmony_ci 1) the directory already exists 350370b324cSopenharmony_ci 2) the directory was created 351370b324cSopenharmony_ci path must be WITHOUT trailing path separator. 352370b324cSopenharmony_ci 353370b324cSopenharmony_ci We need CreateDir2, since fileInfo.Find() for reserved names like "com8" 354370b324cSopenharmony_ci returns FILE instead of DIRECTORY. And we need to use SuperPath */ 355370b324cSopenharmony_ci 356370b324cSopenharmony_cistatic bool CreateDir2(CFSTR path) 357370b324cSopenharmony_ci{ 358370b324cSopenharmony_ci #ifndef _UNICODE 359370b324cSopenharmony_ci if (!g_IsNT) 360370b324cSopenharmony_ci { 361370b324cSopenharmony_ci if (::CreateDirectory(fs2fas(path), NULL)) 362370b324cSopenharmony_ci return true; 363370b324cSopenharmony_ci } 364370b324cSopenharmony_ci else 365370b324cSopenharmony_ci #endif 366370b324cSopenharmony_ci { 367370b324cSopenharmony_ci IF_USE_MAIN_PATH 368370b324cSopenharmony_ci if (::CreateDirectoryW(fs2us(path), NULL)) 369370b324cSopenharmony_ci return true; 370370b324cSopenharmony_ci #ifdef Z7_LONG_PATH 371370b324cSopenharmony_ci if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH) 372370b324cSopenharmony_ci { 373370b324cSopenharmony_ci UString superPath; 374370b324cSopenharmony_ci if (GetSuperPath(path, superPath, USE_MAIN_PATH)) 375370b324cSopenharmony_ci { 376370b324cSopenharmony_ci if (::CreateDirectoryW(superPath, NULL)) 377370b324cSopenharmony_ci return true; 378370b324cSopenharmony_ci if (::GetLastError() != ERROR_ALREADY_EXISTS) 379370b324cSopenharmony_ci return false; 380370b324cSopenharmony_ci NFind::CFileInfo fi; 381370b324cSopenharmony_ci if (!fi.Find(us2fs(superPath))) 382370b324cSopenharmony_ci return false; 383370b324cSopenharmony_ci return fi.IsDir(); 384370b324cSopenharmony_ci } 385370b324cSopenharmony_ci } 386370b324cSopenharmony_ci #endif 387370b324cSopenharmony_ci } 388370b324cSopenharmony_ci if (::GetLastError() != ERROR_ALREADY_EXISTS) 389370b324cSopenharmony_ci return false; 390370b324cSopenharmony_ci NFind::CFileInfo fi; 391370b324cSopenharmony_ci if (!fi.Find(path)) 392370b324cSopenharmony_ci return false; 393370b324cSopenharmony_ci return fi.IsDir(); 394370b324cSopenharmony_ci} 395370b324cSopenharmony_ci 396370b324cSopenharmony_ci#endif // _WIN32 397370b324cSopenharmony_ci 398370b324cSopenharmony_cistatic bool CreateDir2(CFSTR path); 399370b324cSopenharmony_ci 400370b324cSopenharmony_cibool CreateComplexDir(CFSTR _path) 401370b324cSopenharmony_ci{ 402370b324cSopenharmony_ci #ifdef _WIN32 403370b324cSopenharmony_ci 404370b324cSopenharmony_ci { 405370b324cSopenharmony_ci const DWORD attrib = NFind::GetFileAttrib(_path); 406370b324cSopenharmony_ci if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) 407370b324cSopenharmony_ci return true; 408370b324cSopenharmony_ci } 409370b324cSopenharmony_ci 410370b324cSopenharmony_ci #ifndef UNDER_CE 411370b324cSopenharmony_ci 412370b324cSopenharmony_ci if (IsDriveRootPath_SuperAllowed(_path)) 413370b324cSopenharmony_ci return false; 414370b324cSopenharmony_ci 415370b324cSopenharmony_ci const unsigned prefixSize = GetRootPrefixSize(_path); 416370b324cSopenharmony_ci 417370b324cSopenharmony_ci #endif // UNDER_CE 418370b324cSopenharmony_ci 419370b324cSopenharmony_ci #else // _WIN32 420370b324cSopenharmony_ci 421370b324cSopenharmony_ci // Posix 422370b324cSopenharmony_ci NFind::CFileInfo fi; 423370b324cSopenharmony_ci if (fi.Find(_path)) 424370b324cSopenharmony_ci { 425370b324cSopenharmony_ci if (fi.IsDir()) 426370b324cSopenharmony_ci return true; 427370b324cSopenharmony_ci } 428370b324cSopenharmony_ci 429370b324cSopenharmony_ci #endif // _WIN32 430370b324cSopenharmony_ci 431370b324cSopenharmony_ci FString path (_path); 432370b324cSopenharmony_ci 433370b324cSopenharmony_ci int pos = path.ReverseFind_PathSepar(); 434370b324cSopenharmony_ci if (pos >= 0 && (unsigned)pos == path.Len() - 1) 435370b324cSopenharmony_ci { 436370b324cSopenharmony_ci if (path.Len() == 1) 437370b324cSopenharmony_ci return true; 438370b324cSopenharmony_ci path.DeleteBack(); 439370b324cSopenharmony_ci } 440370b324cSopenharmony_ci 441370b324cSopenharmony_ci const FString path2 (path); 442370b324cSopenharmony_ci pos = (int)path.Len(); 443370b324cSopenharmony_ci 444370b324cSopenharmony_ci for (;;) 445370b324cSopenharmony_ci { 446370b324cSopenharmony_ci if (CreateDir2(path)) 447370b324cSopenharmony_ci break; 448370b324cSopenharmony_ci if (::GetLastError() == ERROR_ALREADY_EXISTS) 449370b324cSopenharmony_ci return false; 450370b324cSopenharmony_ci pos = path.ReverseFind_PathSepar(); 451370b324cSopenharmony_ci if (pos < 0 || pos == 0) 452370b324cSopenharmony_ci return false; 453370b324cSopenharmony_ci 454370b324cSopenharmony_ci #if defined(_WIN32) && !defined(UNDER_CE) 455370b324cSopenharmony_ci if (pos == 1 && IS_PATH_SEPAR(path[0])) 456370b324cSopenharmony_ci return false; 457370b324cSopenharmony_ci if (prefixSize >= (unsigned)pos + 1) 458370b324cSopenharmony_ci return false; 459370b324cSopenharmony_ci #endif 460370b324cSopenharmony_ci 461370b324cSopenharmony_ci path.DeleteFrom((unsigned)pos); 462370b324cSopenharmony_ci } 463370b324cSopenharmony_ci 464370b324cSopenharmony_ci while (pos < (int)path2.Len()) 465370b324cSopenharmony_ci { 466370b324cSopenharmony_ci int pos2 = NName::FindSepar(path2.Ptr((unsigned)pos + 1)); 467370b324cSopenharmony_ci if (pos2 < 0) 468370b324cSopenharmony_ci pos = (int)path2.Len(); 469370b324cSopenharmony_ci else 470370b324cSopenharmony_ci pos += 1 + pos2; 471370b324cSopenharmony_ci path.SetFrom(path2, (unsigned)pos); 472370b324cSopenharmony_ci if (!CreateDir(path)) 473370b324cSopenharmony_ci return false; 474370b324cSopenharmony_ci } 475370b324cSopenharmony_ci 476370b324cSopenharmony_ci return true; 477370b324cSopenharmony_ci} 478370b324cSopenharmony_ci 479370b324cSopenharmony_ci 480370b324cSopenharmony_ci#ifdef _WIN32 481370b324cSopenharmony_ci 482370b324cSopenharmony_cibool DeleteFileAlways(CFSTR path) 483370b324cSopenharmony_ci{ 484370b324cSopenharmony_ci /* If alt stream, we also need to clear READ-ONLY attribute of main file before delete. 485370b324cSopenharmony_ci SetFileAttrib("name:stream", ) changes attributes of main file. */ 486370b324cSopenharmony_ci { 487370b324cSopenharmony_ci DWORD attrib = NFind::GetFileAttrib(path); 488370b324cSopenharmony_ci if (attrib != INVALID_FILE_ATTRIBUTES 489370b324cSopenharmony_ci && (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0 490370b324cSopenharmony_ci && (attrib & FILE_ATTRIBUTE_READONLY) != 0) 491370b324cSopenharmony_ci { 492370b324cSopenharmony_ci if (!SetFileAttrib(path, attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY)) 493370b324cSopenharmony_ci return false; 494370b324cSopenharmony_ci } 495370b324cSopenharmony_ci } 496370b324cSopenharmony_ci 497370b324cSopenharmony_ci #ifndef _UNICODE 498370b324cSopenharmony_ci if (!g_IsNT) 499370b324cSopenharmony_ci { 500370b324cSopenharmony_ci if (::DeleteFile(fs2fas(path))) 501370b324cSopenharmony_ci return true; 502370b324cSopenharmony_ci } 503370b324cSopenharmony_ci else 504370b324cSopenharmony_ci #endif 505370b324cSopenharmony_ci { 506370b324cSopenharmony_ci /* DeleteFile("name::$DATA") deletes all alt streams (same as delete DeleteFile("name")). 507370b324cSopenharmony_ci Maybe it's better to open "name::$DATA" and clear data for unnamed stream? */ 508370b324cSopenharmony_ci IF_USE_MAIN_PATH 509370b324cSopenharmony_ci if (::DeleteFileW(fs2us(path))) 510370b324cSopenharmony_ci return true; 511370b324cSopenharmony_ci #ifdef Z7_LONG_PATH 512370b324cSopenharmony_ci if (USE_SUPER_PATH) 513370b324cSopenharmony_ci { 514370b324cSopenharmony_ci UString superPath; 515370b324cSopenharmony_ci if (GetSuperPath(path, superPath, USE_MAIN_PATH)) 516370b324cSopenharmony_ci return BOOLToBool(::DeleteFileW(superPath)); 517370b324cSopenharmony_ci } 518370b324cSopenharmony_ci #endif 519370b324cSopenharmony_ci } 520370b324cSopenharmony_ci return false; 521370b324cSopenharmony_ci} 522370b324cSopenharmony_ci 523370b324cSopenharmony_ci 524370b324cSopenharmony_ci 525370b324cSopenharmony_cibool RemoveDirWithSubItems(const FString &path) 526370b324cSopenharmony_ci{ 527370b324cSopenharmony_ci bool needRemoveSubItems = true; 528370b324cSopenharmony_ci { 529370b324cSopenharmony_ci NFind::CFileInfo fi; 530370b324cSopenharmony_ci if (!fi.Find(path)) 531370b324cSopenharmony_ci return false; 532370b324cSopenharmony_ci if (!fi.IsDir()) 533370b324cSopenharmony_ci { 534370b324cSopenharmony_ci ::SetLastError(ERROR_DIRECTORY); 535370b324cSopenharmony_ci return false; 536370b324cSopenharmony_ci } 537370b324cSopenharmony_ci if (fi.HasReparsePoint()) 538370b324cSopenharmony_ci needRemoveSubItems = false; 539370b324cSopenharmony_ci } 540370b324cSopenharmony_ci 541370b324cSopenharmony_ci if (needRemoveSubItems) 542370b324cSopenharmony_ci { 543370b324cSopenharmony_ci FString s (path); 544370b324cSopenharmony_ci s.Add_PathSepar(); 545370b324cSopenharmony_ci const unsigned prefixSize = s.Len(); 546370b324cSopenharmony_ci NFind::CEnumerator enumerator; 547370b324cSopenharmony_ci enumerator.SetDirPrefix(s); 548370b324cSopenharmony_ci NFind::CDirEntry fi; 549370b324cSopenharmony_ci bool isError = false; 550370b324cSopenharmony_ci DWORD lastError = 0; 551370b324cSopenharmony_ci while (enumerator.Next(fi)) 552370b324cSopenharmony_ci { 553370b324cSopenharmony_ci s.DeleteFrom(prefixSize); 554370b324cSopenharmony_ci s += fi.Name; 555370b324cSopenharmony_ci if (fi.IsDir()) 556370b324cSopenharmony_ci { 557370b324cSopenharmony_ci if (!RemoveDirWithSubItems(s)) 558370b324cSopenharmony_ci { 559370b324cSopenharmony_ci lastError = GetLastError(); 560370b324cSopenharmony_ci isError = true; 561370b324cSopenharmony_ci } 562370b324cSopenharmony_ci } 563370b324cSopenharmony_ci else if (!DeleteFileAlways(s)) 564370b324cSopenharmony_ci { 565370b324cSopenharmony_ci lastError = GetLastError(); 566370b324cSopenharmony_ci isError = false; 567370b324cSopenharmony_ci } 568370b324cSopenharmony_ci } 569370b324cSopenharmony_ci if (isError) 570370b324cSopenharmony_ci { 571370b324cSopenharmony_ci SetLastError(lastError); 572370b324cSopenharmony_ci return false; 573370b324cSopenharmony_ci } 574370b324cSopenharmony_ci } 575370b324cSopenharmony_ci 576370b324cSopenharmony_ci // we clear read-only attrib to remove read-only dir 577370b324cSopenharmony_ci if (!SetFileAttrib(path, 0)) 578370b324cSopenharmony_ci return false; 579370b324cSopenharmony_ci return RemoveDir(path); 580370b324cSopenharmony_ci} 581370b324cSopenharmony_ci 582370b324cSopenharmony_ci#endif // _WIN32 583370b324cSopenharmony_ci 584370b324cSopenharmony_ci#ifdef UNDER_CE 585370b324cSopenharmony_ci 586370b324cSopenharmony_cibool MyGetFullPathName(CFSTR path, FString &resFullPath) 587370b324cSopenharmony_ci{ 588370b324cSopenharmony_ci resFullPath = path; 589370b324cSopenharmony_ci return true; 590370b324cSopenharmony_ci} 591370b324cSopenharmony_ci 592370b324cSopenharmony_ci#else 593370b324cSopenharmony_ci 594370b324cSopenharmony_cibool MyGetFullPathName(CFSTR path, FString &resFullPath) 595370b324cSopenharmony_ci{ 596370b324cSopenharmony_ci return GetFullPath(path, resFullPath); 597370b324cSopenharmony_ci} 598370b324cSopenharmony_ci 599370b324cSopenharmony_ci#ifdef _WIN32 600370b324cSopenharmony_ci 601370b324cSopenharmony_ci/* Win10: SetCurrentDirectory() doesn't support long paths and 602370b324cSopenharmony_ci doesn't support super prefix "\\?\", if long path behavior is not 603370b324cSopenharmony_ci enabled in registry (LongPathsEnabled) and in manifest (longPathAware). */ 604370b324cSopenharmony_ci 605370b324cSopenharmony_cibool SetCurrentDir(CFSTR path) 606370b324cSopenharmony_ci{ 607370b324cSopenharmony_ci #ifndef _UNICODE 608370b324cSopenharmony_ci if (!g_IsNT) 609370b324cSopenharmony_ci { 610370b324cSopenharmony_ci return BOOLToBool(::SetCurrentDirectory(fs2fas(path))); 611370b324cSopenharmony_ci } 612370b324cSopenharmony_ci else 613370b324cSopenharmony_ci #endif 614370b324cSopenharmony_ci { 615370b324cSopenharmony_ci return BOOLToBool(::SetCurrentDirectoryW(fs2us(path))); 616370b324cSopenharmony_ci } 617370b324cSopenharmony_ci} 618370b324cSopenharmony_ci 619370b324cSopenharmony_ci 620370b324cSopenharmony_ci/* 621370b324cSopenharmony_ciwe use system function GetCurrentDirectory() 622370b324cSopenharmony_cinew GetCurrentDirectory() DOCs: 623370b324cSopenharmony_ci - If the function fails, the return value is zero. 624370b324cSopenharmony_ci - If the function succeeds, the return value specifies 625370b324cSopenharmony_ci the number of characters that are written to the buffer, 626370b324cSopenharmony_ci not including the terminating null character. 627370b324cSopenharmony_ci - If the buffer is not large enough, the return value specifies 628370b324cSopenharmony_ci the required size of the buffer, in characters, 629370b324cSopenharmony_ci including the null-terminating character. 630370b324cSopenharmony_ci 631370b324cSopenharmony_ciGetCurrentDir() calls GetCurrentDirectory(). 632370b324cSopenharmony_ciGetCurrentDirectory() in win10 in tests: 633370b324cSopenharmony_ci the returned (path) does not end with a backslash, if 634370b324cSopenharmony_ci current directory is not root directory of drive. 635370b324cSopenharmony_ci But that behavior is not guarantied in specification docs. 636370b324cSopenharmony_ci*/ 637370b324cSopenharmony_ci 638370b324cSopenharmony_cibool GetCurrentDir(FString &path) 639370b324cSopenharmony_ci{ 640370b324cSopenharmony_ci const unsigned kBufSize = MAX_PATH + 16; 641370b324cSopenharmony_ci path.Empty(); 642370b324cSopenharmony_ci 643370b324cSopenharmony_ci #ifndef _UNICODE 644370b324cSopenharmony_ci if (!g_IsNT) 645370b324cSopenharmony_ci { 646370b324cSopenharmony_ci TCHAR s[kBufSize + 1]; 647370b324cSopenharmony_ci s[0] = 0; 648370b324cSopenharmony_ci const DWORD len = ::GetCurrentDirectory(kBufSize, s); 649370b324cSopenharmony_ci if (len == 0 || len >= kBufSize) 650370b324cSopenharmony_ci return false; 651370b324cSopenharmony_ci s[kBufSize] = 0; // optional guard 652370b324cSopenharmony_ci path = fas2fs(s); 653370b324cSopenharmony_ci return true; 654370b324cSopenharmony_ci } 655370b324cSopenharmony_ci else 656370b324cSopenharmony_ci #endif 657370b324cSopenharmony_ci { 658370b324cSopenharmony_ci DWORD len; 659370b324cSopenharmony_ci { 660370b324cSopenharmony_ci WCHAR s[kBufSize + 1]; 661370b324cSopenharmony_ci s[0] = 0; 662370b324cSopenharmony_ci len = ::GetCurrentDirectoryW(kBufSize, s); 663370b324cSopenharmony_ci if (len == 0) 664370b324cSopenharmony_ci return false; 665370b324cSopenharmony_ci if (len < kBufSize) 666370b324cSopenharmony_ci { 667370b324cSopenharmony_ci s[kBufSize] = 0; // optional guard 668370b324cSopenharmony_ci path = us2fs(s); 669370b324cSopenharmony_ci return true; 670370b324cSopenharmony_ci } 671370b324cSopenharmony_ci } 672370b324cSopenharmony_ci UString temp; 673370b324cSopenharmony_ci const DWORD len2 = ::GetCurrentDirectoryW(len, temp.GetBuf(len)); 674370b324cSopenharmony_ci if (len2 == 0) 675370b324cSopenharmony_ci return false; 676370b324cSopenharmony_ci temp.ReleaseBuf_CalcLen(len); 677370b324cSopenharmony_ci if (temp.Len() != len2 || len - 1 != len2) 678370b324cSopenharmony_ci { 679370b324cSopenharmony_ci /* it's unexpected case, if current dir of process 680370b324cSopenharmony_ci was changed between two function calls, 681370b324cSopenharmony_ci or some unexpected function implementation */ 682370b324cSopenharmony_ci // SetLastError((DWORD)E_FAIL); // we can set some error code 683370b324cSopenharmony_ci return false; 684370b324cSopenharmony_ci } 685370b324cSopenharmony_ci path = us2fs(temp); 686370b324cSopenharmony_ci return true; 687370b324cSopenharmony_ci } 688370b324cSopenharmony_ci} 689370b324cSopenharmony_ci 690370b324cSopenharmony_ci#endif // _WIN32 691370b324cSopenharmony_ci#endif // UNDER_CE 692370b324cSopenharmony_ci 693370b324cSopenharmony_ci 694370b324cSopenharmony_cibool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName) 695370b324cSopenharmony_ci{ 696370b324cSopenharmony_ci bool res = MyGetFullPathName(path, resDirPrefix); 697370b324cSopenharmony_ci if (!res) 698370b324cSopenharmony_ci resDirPrefix = path; 699370b324cSopenharmony_ci int pos = resDirPrefix.ReverseFind_PathSepar(); 700370b324cSopenharmony_ci pos++; 701370b324cSopenharmony_ci resFileName = resDirPrefix.Ptr((unsigned)pos); 702370b324cSopenharmony_ci resDirPrefix.DeleteFrom((unsigned)pos); 703370b324cSopenharmony_ci return res; 704370b324cSopenharmony_ci} 705370b324cSopenharmony_ci 706370b324cSopenharmony_cibool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix) 707370b324cSopenharmony_ci{ 708370b324cSopenharmony_ci FString resFileName; 709370b324cSopenharmony_ci return GetFullPathAndSplit(path, resDirPrefix, resFileName); 710370b324cSopenharmony_ci} 711370b324cSopenharmony_ci 712370b324cSopenharmony_ci 713370b324cSopenharmony_ci 714370b324cSopenharmony_cibool MyGetTempPath(FString &path) 715370b324cSopenharmony_ci{ 716370b324cSopenharmony_ci #ifdef _WIN32 717370b324cSopenharmony_ci 718370b324cSopenharmony_ci /* 719370b324cSopenharmony_ci new DOCs for GetTempPathW(): 720370b324cSopenharmony_ci - The returned string ends with a backslash. 721370b324cSopenharmony_ci - The maximum possible return value is MAX_PATH+1 (261). 722370b324cSopenharmony_ci */ 723370b324cSopenharmony_ci 724370b324cSopenharmony_ci const unsigned kBufSize = MAX_PATH + 16; 725370b324cSopenharmony_ci DWORD len; 726370b324cSopenharmony_ci #ifndef _UNICODE 727370b324cSopenharmony_ci if (!g_IsNT) 728370b324cSopenharmony_ci { 729370b324cSopenharmony_ci TCHAR s[kBufSize + 1]; 730370b324cSopenharmony_ci s[0] = 0; 731370b324cSopenharmony_ci len = ::GetTempPath(kBufSize, s); 732370b324cSopenharmony_ci path = fas2fs(s); 733370b324cSopenharmony_ci } 734370b324cSopenharmony_ci else 735370b324cSopenharmony_ci #endif 736370b324cSopenharmony_ci { 737370b324cSopenharmony_ci WCHAR s[kBufSize + 1]; 738370b324cSopenharmony_ci s[0] = 0; 739370b324cSopenharmony_ci len = ::GetTempPathW(kBufSize, s); 740370b324cSopenharmony_ci path = us2fs(s); 741370b324cSopenharmony_ci } 742370b324cSopenharmony_ci /* win10: GetTempPathW() doesn't set backslash at the end of path, 743370b324cSopenharmony_ci if (buffer_size == len_of(path_with_backslash)). 744370b324cSopenharmony_ci So we normalize path here: */ 745370b324cSopenharmony_ci NormalizeDirPathPrefix(path); 746370b324cSopenharmony_ci return (len != 0 && len < kBufSize); 747370b324cSopenharmony_ci 748370b324cSopenharmony_ci #else // !_WIN32 749370b324cSopenharmony_ci 750370b324cSopenharmony_ci // FIXME: improve that code 751370b324cSopenharmony_ci path = STRING_PATH_SEPARATOR "tmp"; 752370b324cSopenharmony_ci const char *s; 753370b324cSopenharmony_ci if (NFind::DoesDirExist_FollowLink(path)) 754370b324cSopenharmony_ci s = STRING_PATH_SEPARATOR "tmp" STRING_PATH_SEPARATOR; 755370b324cSopenharmony_ci else 756370b324cSopenharmony_ci s = "." STRING_PATH_SEPARATOR; 757370b324cSopenharmony_ci path = s; 758370b324cSopenharmony_ci return true; 759370b324cSopenharmony_ci 760370b324cSopenharmony_ci #endif 761370b324cSopenharmony_ci} 762370b324cSopenharmony_ci 763370b324cSopenharmony_ci 764370b324cSopenharmony_cibool CreateTempFile2(CFSTR prefix, bool addRandom, AString &postfix, NIO::COutFile *outFile) 765370b324cSopenharmony_ci{ 766370b324cSopenharmony_ci UInt32 d = 767370b324cSopenharmony_ci #ifdef _WIN32 768370b324cSopenharmony_ci (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); 769370b324cSopenharmony_ci #else 770370b324cSopenharmony_ci (UInt32)(time(NULL) << 12) ^ ((UInt32)getppid() << 14) ^ (UInt32)(getpid()); 771370b324cSopenharmony_ci #endif 772370b324cSopenharmony_ci 773370b324cSopenharmony_ci for (unsigned i = 0; i < 100; i++) 774370b324cSopenharmony_ci { 775370b324cSopenharmony_ci postfix.Empty(); 776370b324cSopenharmony_ci if (addRandom) 777370b324cSopenharmony_ci { 778370b324cSopenharmony_ci char s[16]; 779370b324cSopenharmony_ci UInt32 val = d; 780370b324cSopenharmony_ci unsigned k; 781370b324cSopenharmony_ci for (k = 0; k < 8; k++) 782370b324cSopenharmony_ci { 783370b324cSopenharmony_ci const unsigned t = val & 0xF; 784370b324cSopenharmony_ci val >>= 4; 785370b324cSopenharmony_ci s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); 786370b324cSopenharmony_ci } 787370b324cSopenharmony_ci s[k] = '\0'; 788370b324cSopenharmony_ci if (outFile) 789370b324cSopenharmony_ci postfix.Add_Dot(); 790370b324cSopenharmony_ci postfix += s; 791370b324cSopenharmony_ci UInt32 step = GetTickCount() + 2; 792370b324cSopenharmony_ci if (step == 0) 793370b324cSopenharmony_ci step = 1; 794370b324cSopenharmony_ci d += step; 795370b324cSopenharmony_ci } 796370b324cSopenharmony_ci addRandom = true; 797370b324cSopenharmony_ci if (outFile) 798370b324cSopenharmony_ci postfix += ".tmp"; 799370b324cSopenharmony_ci FString path (prefix); 800370b324cSopenharmony_ci path += postfix; 801370b324cSopenharmony_ci if (NFind::DoesFileOrDirExist(path)) 802370b324cSopenharmony_ci { 803370b324cSopenharmony_ci SetLastError(ERROR_ALREADY_EXISTS); 804370b324cSopenharmony_ci continue; 805370b324cSopenharmony_ci } 806370b324cSopenharmony_ci if (outFile) 807370b324cSopenharmony_ci { 808370b324cSopenharmony_ci if (outFile->Create(path, false)) 809370b324cSopenharmony_ci return true; 810370b324cSopenharmony_ci } 811370b324cSopenharmony_ci else 812370b324cSopenharmony_ci { 813370b324cSopenharmony_ci if (CreateDir(path)) 814370b324cSopenharmony_ci return true; 815370b324cSopenharmony_ci } 816370b324cSopenharmony_ci const DWORD error = GetLastError(); 817370b324cSopenharmony_ci if (error != ERROR_FILE_EXISTS && 818370b324cSopenharmony_ci error != ERROR_ALREADY_EXISTS) 819370b324cSopenharmony_ci break; 820370b324cSopenharmony_ci } 821370b324cSopenharmony_ci postfix.Empty(); 822370b324cSopenharmony_ci return false; 823370b324cSopenharmony_ci} 824370b324cSopenharmony_ci 825370b324cSopenharmony_cibool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile) 826370b324cSopenharmony_ci{ 827370b324cSopenharmony_ci if (!Remove()) 828370b324cSopenharmony_ci return false; 829370b324cSopenharmony_ci _path.Empty(); 830370b324cSopenharmony_ci AString postfix; 831370b324cSopenharmony_ci if (!CreateTempFile2(prefix, false, postfix, outFile)) 832370b324cSopenharmony_ci return false; 833370b324cSopenharmony_ci _path = prefix; 834370b324cSopenharmony_ci _path += postfix; 835370b324cSopenharmony_ci _mustBeDeleted = true; 836370b324cSopenharmony_ci return true; 837370b324cSopenharmony_ci} 838370b324cSopenharmony_ci 839370b324cSopenharmony_cibool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile) 840370b324cSopenharmony_ci{ 841370b324cSopenharmony_ci if (!Remove()) 842370b324cSopenharmony_ci return false; 843370b324cSopenharmony_ci _path.Empty(); 844370b324cSopenharmony_ci FString tempPath; 845370b324cSopenharmony_ci if (!MyGetTempPath(tempPath)) 846370b324cSopenharmony_ci return false; 847370b324cSopenharmony_ci AString postfix; 848370b324cSopenharmony_ci tempPath += namePrefix; 849370b324cSopenharmony_ci if (!CreateTempFile2(tempPath, true, postfix, outFile)) 850370b324cSopenharmony_ci return false; 851370b324cSopenharmony_ci _path = tempPath; 852370b324cSopenharmony_ci _path += postfix; 853370b324cSopenharmony_ci _mustBeDeleted = true; 854370b324cSopenharmony_ci return true; 855370b324cSopenharmony_ci} 856370b324cSopenharmony_ci 857370b324cSopenharmony_cibool CTempFile::Remove() 858370b324cSopenharmony_ci{ 859370b324cSopenharmony_ci if (!_mustBeDeleted) 860370b324cSopenharmony_ci return true; 861370b324cSopenharmony_ci _mustBeDeleted = !DeleteFileAlways(_path); 862370b324cSopenharmony_ci return !_mustBeDeleted; 863370b324cSopenharmony_ci} 864370b324cSopenharmony_ci 865370b324cSopenharmony_cibool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) 866370b324cSopenharmony_ci{ 867370b324cSopenharmony_ci // DWORD attrib = 0; 868370b324cSopenharmony_ci if (deleteDestBefore) 869370b324cSopenharmony_ci { 870370b324cSopenharmony_ci if (NFind::DoesFileExist_Raw(name)) 871370b324cSopenharmony_ci { 872370b324cSopenharmony_ci // attrib = NFind::GetFileAttrib(name); 873370b324cSopenharmony_ci if (!DeleteFileAlways(name)) 874370b324cSopenharmony_ci return false; 875370b324cSopenharmony_ci } 876370b324cSopenharmony_ci } 877370b324cSopenharmony_ci DisableDeleting(); 878370b324cSopenharmony_ci return MyMoveFile(_path, name); 879370b324cSopenharmony_ci 880370b324cSopenharmony_ci /* 881370b324cSopenharmony_ci if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) 882370b324cSopenharmony_ci { 883370b324cSopenharmony_ci DWORD attrib2 = NFind::GetFileAttrib(name); 884370b324cSopenharmony_ci if (attrib2 != INVALID_FILE_ATTRIBUTES) 885370b324cSopenharmony_ci SetFileAttrib(name, attrib2 | FILE_ATTRIBUTE_READONLY); 886370b324cSopenharmony_ci } 887370b324cSopenharmony_ci */ 888370b324cSopenharmony_ci} 889370b324cSopenharmony_ci 890370b324cSopenharmony_ci#ifdef _WIN32 891370b324cSopenharmony_cibool CTempDir::Create(CFSTR prefix) 892370b324cSopenharmony_ci{ 893370b324cSopenharmony_ci if (!Remove()) 894370b324cSopenharmony_ci return false; 895370b324cSopenharmony_ci _path.Empty(); 896370b324cSopenharmony_ci FString tempPath; 897370b324cSopenharmony_ci if (!MyGetTempPath(tempPath)) 898370b324cSopenharmony_ci return false; 899370b324cSopenharmony_ci tempPath += prefix; 900370b324cSopenharmony_ci AString postfix; 901370b324cSopenharmony_ci if (!CreateTempFile2(tempPath, true, postfix, NULL)) 902370b324cSopenharmony_ci return false; 903370b324cSopenharmony_ci _path = tempPath; 904370b324cSopenharmony_ci _path += postfix; 905370b324cSopenharmony_ci _mustBeDeleted = true; 906370b324cSopenharmony_ci return true; 907370b324cSopenharmony_ci} 908370b324cSopenharmony_ci 909370b324cSopenharmony_cibool CTempDir::Remove() 910370b324cSopenharmony_ci{ 911370b324cSopenharmony_ci if (!_mustBeDeleted) 912370b324cSopenharmony_ci return true; 913370b324cSopenharmony_ci _mustBeDeleted = !RemoveDirWithSubItems(_path); 914370b324cSopenharmony_ci return !_mustBeDeleted; 915370b324cSopenharmony_ci} 916370b324cSopenharmony_ci#endif 917370b324cSopenharmony_ci 918370b324cSopenharmony_ci 919370b324cSopenharmony_ci 920370b324cSopenharmony_ci#ifndef _WIN32 921370b324cSopenharmony_ci 922370b324cSopenharmony_cibool RemoveDir(CFSTR path) 923370b324cSopenharmony_ci{ 924370b324cSopenharmony_ci return (rmdir(path) == 0); 925370b324cSopenharmony_ci} 926370b324cSopenharmony_ci 927370b324cSopenharmony_ci 928370b324cSopenharmony_cistatic BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile) 929370b324cSopenharmony_ci{ 930370b324cSopenharmony_ci NWindows::NFile::NIO::COutFile outFile; 931370b324cSopenharmony_ci if (!outFile.Create(newFile, false)) 932370b324cSopenharmony_ci return FALSE; 933370b324cSopenharmony_ci 934370b324cSopenharmony_ci NWindows::NFile::NIO::CInFile inFile; 935370b324cSopenharmony_ci if (!inFile.Open(oldFile)) 936370b324cSopenharmony_ci return FALSE; 937370b324cSopenharmony_ci 938370b324cSopenharmony_ci char buf[1 << 14]; 939370b324cSopenharmony_ci 940370b324cSopenharmony_ci for (;;) 941370b324cSopenharmony_ci { 942370b324cSopenharmony_ci const ssize_t num = inFile.read_part(buf, sizeof(buf)); 943370b324cSopenharmony_ci if (num == 0) 944370b324cSopenharmony_ci return TRUE; 945370b324cSopenharmony_ci if (num < 0) 946370b324cSopenharmony_ci return FALSE; 947370b324cSopenharmony_ci size_t processed; 948370b324cSopenharmony_ci const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed); 949370b324cSopenharmony_ci if (num2 != num || processed != (size_t)num) 950370b324cSopenharmony_ci return FALSE; 951370b324cSopenharmony_ci } 952370b324cSopenharmony_ci} 953370b324cSopenharmony_ci 954370b324cSopenharmony_ci 955370b324cSopenharmony_cibool MyMoveFile(CFSTR oldFile, CFSTR newFile) 956370b324cSopenharmony_ci{ 957370b324cSopenharmony_ci int res = rename(oldFile, newFile); 958370b324cSopenharmony_ci if (res == 0) 959370b324cSopenharmony_ci return true; 960370b324cSopenharmony_ci if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem) 961370b324cSopenharmony_ci return false; 962370b324cSopenharmony_ci 963370b324cSopenharmony_ci if (My_CopyFile(oldFile, newFile) == FALSE) 964370b324cSopenharmony_ci return false; 965370b324cSopenharmony_ci 966370b324cSopenharmony_ci struct stat info_file; 967370b324cSopenharmony_ci res = stat(oldFile, &info_file); 968370b324cSopenharmony_ci if (res != 0) 969370b324cSopenharmony_ci return false; 970370b324cSopenharmony_ci 971370b324cSopenharmony_ci /* 972370b324cSopenharmony_ci ret = chmod(dst,info_file.st_mode & g_umask.mask); 973370b324cSopenharmony_ci */ 974370b324cSopenharmony_ci return (unlink(oldFile) == 0); 975370b324cSopenharmony_ci} 976370b324cSopenharmony_ci 977370b324cSopenharmony_ci 978370b324cSopenharmony_cibool CreateDir(CFSTR path) 979370b324cSopenharmony_ci{ 980370b324cSopenharmony_ci return (mkdir(path, 0777) == 0); // change it 981370b324cSopenharmony_ci} 982370b324cSopenharmony_ci 983370b324cSopenharmony_cistatic bool CreateDir2(CFSTR path) 984370b324cSopenharmony_ci{ 985370b324cSopenharmony_ci return (mkdir(path, 0777) == 0); // change it 986370b324cSopenharmony_ci} 987370b324cSopenharmony_ci 988370b324cSopenharmony_ci 989370b324cSopenharmony_cibool DeleteFileAlways(CFSTR path) 990370b324cSopenharmony_ci{ 991370b324cSopenharmony_ci return (remove(path) == 0); 992370b324cSopenharmony_ci} 993370b324cSopenharmony_ci 994370b324cSopenharmony_cibool SetCurrentDir(CFSTR path) 995370b324cSopenharmony_ci{ 996370b324cSopenharmony_ci return (chdir(path) == 0); 997370b324cSopenharmony_ci} 998370b324cSopenharmony_ci 999370b324cSopenharmony_ci 1000370b324cSopenharmony_cibool GetCurrentDir(FString &path) 1001370b324cSopenharmony_ci{ 1002370b324cSopenharmony_ci path.Empty(); 1003370b324cSopenharmony_ci 1004370b324cSopenharmony_ci #define MY_PATH_MAX PATH_MAX 1005370b324cSopenharmony_ci // #define MY_PATH_MAX 1024 1006370b324cSopenharmony_ci 1007370b324cSopenharmony_ci char s[MY_PATH_MAX + 1]; 1008370b324cSopenharmony_ci char *res = getcwd(s, MY_PATH_MAX); 1009370b324cSopenharmony_ci if (res) 1010370b324cSopenharmony_ci { 1011370b324cSopenharmony_ci path = fas2fs(s); 1012370b324cSopenharmony_ci return true; 1013370b324cSopenharmony_ci } 1014370b324cSopenharmony_ci { 1015370b324cSopenharmony_ci // if (errno != ERANGE) return false; 1016370b324cSopenharmony_ci #if defined(__GLIBC__) || defined(__APPLE__) 1017370b324cSopenharmony_ci /* As an extension to the POSIX.1-2001 standard, glibc's getcwd() 1018370b324cSopenharmony_ci allocates the buffer dynamically using malloc(3) if buf is NULL. */ 1019370b324cSopenharmony_ci res = getcwd(NULL, 0); 1020370b324cSopenharmony_ci if (res) 1021370b324cSopenharmony_ci { 1022370b324cSopenharmony_ci path = fas2fs(res); 1023370b324cSopenharmony_ci ::free(res); 1024370b324cSopenharmony_ci return true; 1025370b324cSopenharmony_ci } 1026370b324cSopenharmony_ci #endif 1027370b324cSopenharmony_ci return false; 1028370b324cSopenharmony_ci } 1029370b324cSopenharmony_ci} 1030370b324cSopenharmony_ci 1031370b324cSopenharmony_ci 1032370b324cSopenharmony_ci 1033370b324cSopenharmony_ci// #undef UTIME_OMIT // to debug 1034370b324cSopenharmony_ci 1035370b324cSopenharmony_ci#ifndef UTIME_OMIT 1036370b324cSopenharmony_ci /* we can define UTIME_OMIT for debian and another systems. 1037370b324cSopenharmony_ci Is it OK to define UTIME_OMIT to -2 here, if UTIME_OMIT is not defined? */ 1038370b324cSopenharmony_ci // #define UTIME_OMIT -2 1039370b324cSopenharmony_ci#endif 1040370b324cSopenharmony_ci 1041370b324cSopenharmony_ci 1042370b324cSopenharmony_ci 1043370b324cSopenharmony_ci 1044370b324cSopenharmony_ci 1045370b324cSopenharmony_cibool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) 1046370b324cSopenharmony_ci{ 1047370b324cSopenharmony_ci // need testing 1048370b324cSopenharmony_ci /* 1049370b324cSopenharmony_ci struct utimbuf buf; 1050370b324cSopenharmony_ci struct stat st; 1051370b324cSopenharmony_ci UNUSED_VAR(cTime) 1052370b324cSopenharmony_ci 1053370b324cSopenharmony_ci printf("\nstat = %s\n", path); 1054370b324cSopenharmony_ci int ret = stat(path, &st); 1055370b324cSopenharmony_ci 1056370b324cSopenharmony_ci if (ret == 0) 1057370b324cSopenharmony_ci { 1058370b324cSopenharmony_ci buf.actime = st.st_atime; 1059370b324cSopenharmony_ci buf.modtime = st.st_mtime; 1060370b324cSopenharmony_ci } 1061370b324cSopenharmony_ci else 1062370b324cSopenharmony_ci { 1063370b324cSopenharmony_ci time_t cur_time = time(0); 1064370b324cSopenharmony_ci buf.actime = cur_time; 1065370b324cSopenharmony_ci buf.modtime = cur_time; 1066370b324cSopenharmony_ci } 1067370b324cSopenharmony_ci 1068370b324cSopenharmony_ci if (aTime) 1069370b324cSopenharmony_ci { 1070370b324cSopenharmony_ci UInt32 ut; 1071370b324cSopenharmony_ci if (NTime::FileTimeToUnixTime(*aTime, ut)) 1072370b324cSopenharmony_ci buf.actime = ut; 1073370b324cSopenharmony_ci } 1074370b324cSopenharmony_ci 1075370b324cSopenharmony_ci if (mTime) 1076370b324cSopenharmony_ci { 1077370b324cSopenharmony_ci UInt32 ut; 1078370b324cSopenharmony_ci if (NTime::FileTimeToUnixTime(*mTime, ut)) 1079370b324cSopenharmony_ci buf.modtime = ut; 1080370b324cSopenharmony_ci } 1081370b324cSopenharmony_ci 1082370b324cSopenharmony_ci return utime(path, &buf) == 0; 1083370b324cSopenharmony_ci */ 1084370b324cSopenharmony_ci 1085370b324cSopenharmony_ci // if (!aTime && !mTime) return true; 1086370b324cSopenharmony_ci 1087370b324cSopenharmony_ci struct timespec times[2]; 1088370b324cSopenharmony_ci UNUSED_VAR(cTime) 1089370b324cSopenharmony_ci 1090370b324cSopenharmony_ci bool needChange; 1091370b324cSopenharmony_ci needChange = FiTime_To_timespec(aTime, times[0]); 1092370b324cSopenharmony_ci needChange |= FiTime_To_timespec(mTime, times[1]); 1093370b324cSopenharmony_ci 1094370b324cSopenharmony_ci /* 1095370b324cSopenharmony_ci if (mTime) 1096370b324cSopenharmony_ci { 1097370b324cSopenharmony_ci printf("\n time = %ld.%9ld\n", mTime->tv_sec, mTime->tv_nsec); 1098370b324cSopenharmony_ci } 1099370b324cSopenharmony_ci */ 1100370b324cSopenharmony_ci 1101370b324cSopenharmony_ci if (!needChange) 1102370b324cSopenharmony_ci return true; 1103370b324cSopenharmony_ci const int flags = 0; // follow link 1104370b324cSopenharmony_ci // = AT_SYMLINK_NOFOLLOW; // don't follow link 1105370b324cSopenharmony_ci return utimensat(AT_FDCWD, path, times, flags) == 0; 1106370b324cSopenharmony_ci} 1107370b324cSopenharmony_ci 1108370b324cSopenharmony_ci 1109370b324cSopenharmony_ci 1110370b324cSopenharmony_cistruct C_umask 1111370b324cSopenharmony_ci{ 1112370b324cSopenharmony_ci mode_t mask; 1113370b324cSopenharmony_ci 1114370b324cSopenharmony_ci C_umask() 1115370b324cSopenharmony_ci { 1116370b324cSopenharmony_ci /* by security reasons we restrict attributes according 1117370b324cSopenharmony_ci with process's file mode creation mask (umask) */ 1118370b324cSopenharmony_ci const mode_t um = umask(0); // octal :0022 is expected 1119370b324cSopenharmony_ci mask = 0777 & (~um); // octal: 0755 is expected 1120370b324cSopenharmony_ci umask(um); // restore the umask 1121370b324cSopenharmony_ci // printf("\n umask = 0%03o mask = 0%03o\n", um, mask); 1122370b324cSopenharmony_ci 1123370b324cSopenharmony_ci // mask = 0777; // debug we can disable the restriction: 1124370b324cSopenharmony_ci } 1125370b324cSopenharmony_ci}; 1126370b324cSopenharmony_ci 1127370b324cSopenharmony_cistatic C_umask g_umask; 1128370b324cSopenharmony_ci 1129370b324cSopenharmony_ci// #define PRF(x) x; 1130370b324cSopenharmony_ci#define PRF(x) 1131370b324cSopenharmony_ci 1132370b324cSopenharmony_ci#define TRACE_SetFileAttrib(msg) \ 1133370b324cSopenharmony_ci PRF(printf("\nSetFileAttrib(%s, %x) : %s\n", (const char *)path, attrib, msg);) 1134370b324cSopenharmony_ci 1135370b324cSopenharmony_ci#define TRACE_chmod(s, mode) \ 1136370b324cSopenharmony_ci PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode));) 1137370b324cSopenharmony_ci 1138370b324cSopenharmony_ciint my_chown(CFSTR path, uid_t owner, gid_t group) 1139370b324cSopenharmony_ci{ 1140370b324cSopenharmony_ci return chown(path, owner, group); 1141370b324cSopenharmony_ci} 1142370b324cSopenharmony_ci 1143370b324cSopenharmony_cibool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) 1144370b324cSopenharmony_ci{ 1145370b324cSopenharmony_ci TRACE_SetFileAttrib("") 1146370b324cSopenharmony_ci 1147370b324cSopenharmony_ci struct stat st; 1148370b324cSopenharmony_ci 1149370b324cSopenharmony_ci bool use_lstat = true; 1150370b324cSopenharmony_ci if (use_lstat) 1151370b324cSopenharmony_ci { 1152370b324cSopenharmony_ci if (lstat(path, &st) != 0) 1153370b324cSopenharmony_ci { 1154370b324cSopenharmony_ci TRACE_SetFileAttrib("bad lstat()") 1155370b324cSopenharmony_ci return false; 1156370b324cSopenharmony_ci } 1157370b324cSopenharmony_ci // TRACE_chmod("lstat", st.st_mode); 1158370b324cSopenharmony_ci } 1159370b324cSopenharmony_ci else 1160370b324cSopenharmony_ci { 1161370b324cSopenharmony_ci if (stat(path, &st) != 0) 1162370b324cSopenharmony_ci { 1163370b324cSopenharmony_ci TRACE_SetFileAttrib("bad stat()") 1164370b324cSopenharmony_ci return false; 1165370b324cSopenharmony_ci } 1166370b324cSopenharmony_ci } 1167370b324cSopenharmony_ci 1168370b324cSopenharmony_ci if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) 1169370b324cSopenharmony_ci { 1170370b324cSopenharmony_ci TRACE_SetFileAttrib("attrib & FILE_ATTRIBUTE_UNIX_EXTENSION") 1171370b324cSopenharmony_ci st.st_mode = attrib >> 16; 1172370b324cSopenharmony_ci if (S_ISDIR(st.st_mode)) 1173370b324cSopenharmony_ci { 1174370b324cSopenharmony_ci // user/7z must be able to create files in this directory 1175370b324cSopenharmony_ci st.st_mode |= (S_IRUSR | S_IWUSR | S_IXUSR); 1176370b324cSopenharmony_ci } 1177370b324cSopenharmony_ci else if (!S_ISREG(st.st_mode)) 1178370b324cSopenharmony_ci return true; 1179370b324cSopenharmony_ci } 1180370b324cSopenharmony_ci else if (S_ISLNK(st.st_mode)) 1181370b324cSopenharmony_ci { 1182370b324cSopenharmony_ci /* for most systems: permissions for symlinks are fixed to rwxrwxrwx. 1183370b324cSopenharmony_ci so we don't need chmod() for symlinks. */ 1184370b324cSopenharmony_ci return true; 1185370b324cSopenharmony_ci // SetLastError(ENOSYS); 1186370b324cSopenharmony_ci // return false; 1187370b324cSopenharmony_ci } 1188370b324cSopenharmony_ci else 1189370b324cSopenharmony_ci { 1190370b324cSopenharmony_ci TRACE_SetFileAttrib("Only Windows Attributes") 1191370b324cSopenharmony_ci // Only Windows Attributes 1192370b324cSopenharmony_ci if (S_ISDIR(st.st_mode) 1193370b324cSopenharmony_ci || (attrib & FILE_ATTRIBUTE_READONLY) == 0) 1194370b324cSopenharmony_ci return true; 1195370b324cSopenharmony_ci st.st_mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions 1196370b324cSopenharmony_ci } 1197370b324cSopenharmony_ci 1198370b324cSopenharmony_ci int res; 1199370b324cSopenharmony_ci /* 1200370b324cSopenharmony_ci if (S_ISLNK(st.st_mode)) 1201370b324cSopenharmony_ci { 1202370b324cSopenharmony_ci printf("\nfchmodat()\n"); 1203370b324cSopenharmony_ci TRACE_chmod(path, (st.st_mode) & g_umask.mask) 1204370b324cSopenharmony_ci // AT_SYMLINK_NOFOLLOW is not implemted still in Linux. 1205370b324cSopenharmony_ci res = fchmodat(AT_FDCWD, path, (st.st_mode) & g_umask.mask, 1206370b324cSopenharmony_ci S_ISLNK(st.st_mode) ? AT_SYMLINK_NOFOLLOW : 0); 1207370b324cSopenharmony_ci } 1208370b324cSopenharmony_ci else 1209370b324cSopenharmony_ci */ 1210370b324cSopenharmony_ci { 1211370b324cSopenharmony_ci TRACE_chmod(path, (st.st_mode) & g_umask.mask) 1212370b324cSopenharmony_ci res = chmod(path, (st.st_mode) & g_umask.mask); 1213370b324cSopenharmony_ci } 1214370b324cSopenharmony_ci // TRACE_SetFileAttrib("End") 1215370b324cSopenharmony_ci return (res == 0); 1216370b324cSopenharmony_ci} 1217370b324cSopenharmony_ci 1218370b324cSopenharmony_ci 1219370b324cSopenharmony_cibool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) 1220370b324cSopenharmony_ci{ 1221370b324cSopenharmony_ci PRF(printf("\nhard link() %s -> %s\n", newFileName, existFileName);) 1222370b324cSopenharmony_ci return (link(existFileName, newFileName) == 0); 1223370b324cSopenharmony_ci} 1224370b324cSopenharmony_ci 1225370b324cSopenharmony_ci#endif // !_WIN32 1226370b324cSopenharmony_ci 1227370b324cSopenharmony_ci// #endif 1228370b324cSopenharmony_ci 1229370b324cSopenharmony_ci}}} 1230