1370b324cSopenharmony_ci// Windows/FileIO.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci#ifdef Z7_DEVICE_FILE 6370b324cSopenharmony_ci#include "../../C/Alloc.h" 7370b324cSopenharmony_ci#endif 8370b324cSopenharmony_ci 9370b324cSopenharmony_ci// #include <stdio.h> 10370b324cSopenharmony_ci 11370b324cSopenharmony_ci/* 12370b324cSopenharmony_ci#ifndef _WIN32 13370b324cSopenharmony_ci// for ioctl BLKGETSIZE64 14370b324cSopenharmony_ci#include <sys/ioctl.h> 15370b324cSopenharmony_ci#include <linux/fs.h> 16370b324cSopenharmony_ci#endif 17370b324cSopenharmony_ci*/ 18370b324cSopenharmony_ci 19370b324cSopenharmony_ci#include "FileIO.h" 20370b324cSopenharmony_ci#include "FileName.h" 21370b324cSopenharmony_ci 22370b324cSopenharmony_ciHRESULT GetLastError_noZero_HRESULT() 23370b324cSopenharmony_ci{ 24370b324cSopenharmony_ci const DWORD res = ::GetLastError(); 25370b324cSopenharmony_ci if (res == 0) 26370b324cSopenharmony_ci return E_FAIL; 27370b324cSopenharmony_ci return HRESULT_FROM_WIN32(res); 28370b324cSopenharmony_ci} 29370b324cSopenharmony_ci 30370b324cSopenharmony_ci#ifdef _WIN32 31370b324cSopenharmony_ci 32370b324cSopenharmony_ci#ifndef _UNICODE 33370b324cSopenharmony_ciextern bool g_IsNT; 34370b324cSopenharmony_ci#endif 35370b324cSopenharmony_ci 36370b324cSopenharmony_ciusing namespace NWindows; 37370b324cSopenharmony_ciusing namespace NFile; 38370b324cSopenharmony_ciusing namespace NName; 39370b324cSopenharmony_ci 40370b324cSopenharmony_cinamespace NWindows { 41370b324cSopenharmony_cinamespace NFile { 42370b324cSopenharmony_ci 43370b324cSopenharmony_ci#ifdef Z7_DEVICE_FILE 44370b324cSopenharmony_ci 45370b324cSopenharmony_cinamespace NSystem 46370b324cSopenharmony_ci{ 47370b324cSopenharmony_cibool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); 48370b324cSopenharmony_ci} 49370b324cSopenharmony_ci#endif 50370b324cSopenharmony_ci 51370b324cSopenharmony_cinamespace NIO { 52370b324cSopenharmony_ci 53370b324cSopenharmony_ci/* 54370b324cSopenharmony_ciWinXP-64 CreateFile(): 55370b324cSopenharmony_ci "" - ERROR_PATH_NOT_FOUND 56370b324cSopenharmony_ci :stream - OK 57370b324cSopenharmony_ci .:stream - ERROR_PATH_NOT_FOUND 58370b324cSopenharmony_ci .\:stream - OK 59370b324cSopenharmony_ci 60370b324cSopenharmony_ci folder\:stream - ERROR_INVALID_NAME 61370b324cSopenharmony_ci folder:stream - OK 62370b324cSopenharmony_ci 63370b324cSopenharmony_ci c:\:stream - OK 64370b324cSopenharmony_ci 65370b324cSopenharmony_ci c::stream - ERROR_INVALID_NAME, if current dir is NOT ROOT ( c:\dir1 ) 66370b324cSopenharmony_ci c::stream - OK, if current dir is ROOT ( c:\ ) 67370b324cSopenharmony_ci*/ 68370b324cSopenharmony_ci 69370b324cSopenharmony_cibool CFileBase::Create(CFSTR path, DWORD desiredAccess, 70370b324cSopenharmony_ci DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) 71370b324cSopenharmony_ci{ 72370b324cSopenharmony_ci if (!Close()) 73370b324cSopenharmony_ci return false; 74370b324cSopenharmony_ci 75370b324cSopenharmony_ci #ifdef Z7_DEVICE_FILE 76370b324cSopenharmony_ci IsDeviceFile = false; 77370b324cSopenharmony_ci #endif 78370b324cSopenharmony_ci 79370b324cSopenharmony_ci #ifndef _UNICODE 80370b324cSopenharmony_ci if (!g_IsNT) 81370b324cSopenharmony_ci { 82370b324cSopenharmony_ci _handle = ::CreateFile(fs2fas(path), desiredAccess, shareMode, 83370b324cSopenharmony_ci (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); 84370b324cSopenharmony_ci } 85370b324cSopenharmony_ci else 86370b324cSopenharmony_ci #endif 87370b324cSopenharmony_ci { 88370b324cSopenharmony_ci IF_USE_MAIN_PATH 89370b324cSopenharmony_ci _handle = ::CreateFileW(fs2us(path), desiredAccess, shareMode, 90370b324cSopenharmony_ci (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); 91370b324cSopenharmony_ci #ifdef Z7_LONG_PATH 92370b324cSopenharmony_ci if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH) 93370b324cSopenharmony_ci { 94370b324cSopenharmony_ci UString superPath; 95370b324cSopenharmony_ci if (GetSuperPath(path, superPath, USE_MAIN_PATH)) 96370b324cSopenharmony_ci _handle = ::CreateFileW(superPath, desiredAccess, shareMode, 97370b324cSopenharmony_ci (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); 98370b324cSopenharmony_ci } 99370b324cSopenharmony_ci #endif 100370b324cSopenharmony_ci } 101370b324cSopenharmony_ci 102370b324cSopenharmony_ci /* 103370b324cSopenharmony_ci #ifndef UNDER_CE 104370b324cSopenharmony_ci #ifndef Z7_SFX 105370b324cSopenharmony_ci if (_handle == INVALID_HANDLE_VALUE) 106370b324cSopenharmony_ci { 107370b324cSopenharmony_ci // it's debug hack to open symbolic links in Windows XP and WSL links in Windows 10 108370b324cSopenharmony_ci DWORD lastError = GetLastError(); 109370b324cSopenharmony_ci if (lastError == ERROR_CANT_ACCESS_FILE) 110370b324cSopenharmony_ci { 111370b324cSopenharmony_ci CByteBuffer buf; 112370b324cSopenharmony_ci if (NIO::GetReparseData(path, buf, NULL)) 113370b324cSopenharmony_ci { 114370b324cSopenharmony_ci CReparseAttr attr; 115370b324cSopenharmony_ci if (attr.Parse(buf, buf.Size())) 116370b324cSopenharmony_ci { 117370b324cSopenharmony_ci FString dirPrefix, fileName; 118370b324cSopenharmony_ci if (NDir::GetFullPathAndSplit(path, dirPrefix, fileName)) 119370b324cSopenharmony_ci { 120370b324cSopenharmony_ci FString fullPath; 121370b324cSopenharmony_ci if (GetFullPath(dirPrefix, us2fs(attr.GetPath()), fullPath)) 122370b324cSopenharmony_ci { 123370b324cSopenharmony_ci // FIX IT: recursion levels must be restricted 124370b324cSopenharmony_ci return Create(fullPath, desiredAccess, 125370b324cSopenharmony_ci shareMode, creationDisposition, flagsAndAttributes); 126370b324cSopenharmony_ci } 127370b324cSopenharmony_ci } 128370b324cSopenharmony_ci } 129370b324cSopenharmony_ci } 130370b324cSopenharmony_ci SetLastError(lastError); 131370b324cSopenharmony_ci } 132370b324cSopenharmony_ci } 133370b324cSopenharmony_ci #endif 134370b324cSopenharmony_ci #endif 135370b324cSopenharmony_ci */ 136370b324cSopenharmony_ci 137370b324cSopenharmony_ci return (_handle != INVALID_HANDLE_VALUE); 138370b324cSopenharmony_ci} 139370b324cSopenharmony_ci 140370b324cSopenharmony_cibool CFileBase::Close() throw() 141370b324cSopenharmony_ci{ 142370b324cSopenharmony_ci if (_handle == INVALID_HANDLE_VALUE) 143370b324cSopenharmony_ci return true; 144370b324cSopenharmony_ci if (!::CloseHandle(_handle)) 145370b324cSopenharmony_ci return false; 146370b324cSopenharmony_ci _handle = INVALID_HANDLE_VALUE; 147370b324cSopenharmony_ci return true; 148370b324cSopenharmony_ci} 149370b324cSopenharmony_ci 150370b324cSopenharmony_cibool CFileBase::GetLength(UInt64 &length) const throw() 151370b324cSopenharmony_ci{ 152370b324cSopenharmony_ci #ifdef Z7_DEVICE_FILE 153370b324cSopenharmony_ci if (IsDeviceFile && SizeDefined) 154370b324cSopenharmony_ci { 155370b324cSopenharmony_ci length = Size; 156370b324cSopenharmony_ci return true; 157370b324cSopenharmony_ci } 158370b324cSopenharmony_ci #endif 159370b324cSopenharmony_ci 160370b324cSopenharmony_ci DWORD high = 0; 161370b324cSopenharmony_ci const DWORD low = ::GetFileSize(_handle, &high); 162370b324cSopenharmony_ci if (low == INVALID_FILE_SIZE) 163370b324cSopenharmony_ci if (::GetLastError() != NO_ERROR) 164370b324cSopenharmony_ci return false; 165370b324cSopenharmony_ci length = (((UInt64)high) << 32) + low; 166370b324cSopenharmony_ci return true; 167370b324cSopenharmony_ci 168370b324cSopenharmony_ci /* 169370b324cSopenharmony_ci LARGE_INTEGER fileSize; 170370b324cSopenharmony_ci // GetFileSizeEx() is unsupported in 98/ME/NT, and supported in Win2000+ 171370b324cSopenharmony_ci if (!GetFileSizeEx(_handle, &fileSize)) 172370b324cSopenharmony_ci return false; 173370b324cSopenharmony_ci length = (UInt64)fileSize.QuadPart; 174370b324cSopenharmony_ci return true; 175370b324cSopenharmony_ci */ 176370b324cSopenharmony_ci} 177370b324cSopenharmony_ci 178370b324cSopenharmony_ci 179370b324cSopenharmony_ci/* Specification for SetFilePointer(): 180370b324cSopenharmony_ci 181370b324cSopenharmony_ci If a new file pointer is a negative value, 182370b324cSopenharmony_ci { 183370b324cSopenharmony_ci the function fails, 184370b324cSopenharmony_ci the file pointer is not moved, 185370b324cSopenharmony_ci the code returned by GetLastError() is ERROR_NEGATIVE_SEEK. 186370b324cSopenharmony_ci } 187370b324cSopenharmony_ci 188370b324cSopenharmony_ci If the hFile handle is opened with the FILE_FLAG_NO_BUFFERING flag set 189370b324cSopenharmony_ci { 190370b324cSopenharmony_ci an application can move the file pointer only to sector-aligned positions. 191370b324cSopenharmony_ci A sector-aligned position is a position that is a whole number multiple of 192370b324cSopenharmony_ci the volume sector size. 193370b324cSopenharmony_ci An application can obtain a volume sector size by calling the GetDiskFreeSpace. 194370b324cSopenharmony_ci } 195370b324cSopenharmony_ci 196370b324cSopenharmony_ci It is not an error to set a file pointer to a position beyond the end of the file. 197370b324cSopenharmony_ci The size of the file does not increase until you call the SetEndOfFile, WriteFile, or WriteFileEx function. 198370b324cSopenharmony_ci 199370b324cSopenharmony_ci If the return value is INVALID_SET_FILE_POINTER and if lpDistanceToMoveHigh is non-NULL, 200370b324cSopenharmony_ci an application must call GetLastError to determine whether or not the function has succeeded or failed. 201370b324cSopenharmony_ci*/ 202370b324cSopenharmony_ci 203370b324cSopenharmony_cibool CFileBase::GetPosition(UInt64 &position) const throw() 204370b324cSopenharmony_ci{ 205370b324cSopenharmony_ci LONG high = 0; 206370b324cSopenharmony_ci const DWORD low = ::SetFilePointer(_handle, 0, &high, FILE_CURRENT); 207370b324cSopenharmony_ci if (low == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) 208370b324cSopenharmony_ci { 209370b324cSopenharmony_ci // for error case we can set (position) to (-1) or (0) or leave (position) unchanged. 210370b324cSopenharmony_ci // position = (UInt64)(Int64)-1; // for debug 211370b324cSopenharmony_ci position = 0; 212370b324cSopenharmony_ci return false; 213370b324cSopenharmony_ci } 214370b324cSopenharmony_ci position = (((UInt64)(UInt32)high) << 32) + low; 215370b324cSopenharmony_ci return true; 216370b324cSopenharmony_ci // we don't want recursed GetPosition() 217370b324cSopenharmony_ci // return Seek(0, FILE_CURRENT, position); 218370b324cSopenharmony_ci} 219370b324cSopenharmony_ci 220370b324cSopenharmony_cibool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw() 221370b324cSopenharmony_ci{ 222370b324cSopenharmony_ci #ifdef Z7_DEVICE_FILE 223370b324cSopenharmony_ci if (IsDeviceFile && SizeDefined && moveMethod == FILE_END) 224370b324cSopenharmony_ci { 225370b324cSopenharmony_ci distanceToMove += Size; 226370b324cSopenharmony_ci moveMethod = FILE_BEGIN; 227370b324cSopenharmony_ci } 228370b324cSopenharmony_ci #endif 229370b324cSopenharmony_ci 230370b324cSopenharmony_ci LONG high = (LONG)(distanceToMove >> 32); 231370b324cSopenharmony_ci const DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod); 232370b324cSopenharmony_ci if (low == INVALID_SET_FILE_POINTER) 233370b324cSopenharmony_ci { 234370b324cSopenharmony_ci const DWORD lastError = ::GetLastError(); 235370b324cSopenharmony_ci if (lastError != NO_ERROR) 236370b324cSopenharmony_ci { 237370b324cSopenharmony_ci // 21.07: we set (newPosition) to real position even after error. 238370b324cSopenharmony_ci GetPosition(newPosition); 239370b324cSopenharmony_ci SetLastError(lastError); // restore LastError 240370b324cSopenharmony_ci return false; 241370b324cSopenharmony_ci } 242370b324cSopenharmony_ci } 243370b324cSopenharmony_ci newPosition = (((UInt64)(UInt32)high) << 32) + low; 244370b324cSopenharmony_ci return true; 245370b324cSopenharmony_ci} 246370b324cSopenharmony_ci 247370b324cSopenharmony_cibool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const throw() 248370b324cSopenharmony_ci{ 249370b324cSopenharmony_ci return Seek((Int64)position, FILE_BEGIN, newPosition); 250370b324cSopenharmony_ci} 251370b324cSopenharmony_ci 252370b324cSopenharmony_cibool CFileBase::SeekToBegin() const throw() 253370b324cSopenharmony_ci{ 254370b324cSopenharmony_ci UInt64 newPosition = 0; 255370b324cSopenharmony_ci return Seek(0, newPosition) && (newPosition == 0); 256370b324cSopenharmony_ci} 257370b324cSopenharmony_ci 258370b324cSopenharmony_cibool CFileBase::SeekToEnd(UInt64 &newPosition) const throw() 259370b324cSopenharmony_ci{ 260370b324cSopenharmony_ci return Seek(0, FILE_END, newPosition); 261370b324cSopenharmony_ci} 262370b324cSopenharmony_ci 263370b324cSopenharmony_ci// ---------- CInFile --------- 264370b324cSopenharmony_ci 265370b324cSopenharmony_ci#ifdef Z7_DEVICE_FILE 266370b324cSopenharmony_ci 267370b324cSopenharmony_civoid CInFile::CorrectDeviceSize() 268370b324cSopenharmony_ci{ 269370b324cSopenharmony_ci // maybe we must decrease kClusterSize to 1 << 12, if we want correct size at tail 270370b324cSopenharmony_ci const UInt32 kClusterSize = 1 << 14; 271370b324cSopenharmony_ci UInt64 pos = Size & ~(UInt64)(kClusterSize - 1); 272370b324cSopenharmony_ci UInt64 realNewPosition; 273370b324cSopenharmony_ci if (!Seek(pos, realNewPosition)) 274370b324cSopenharmony_ci return; 275370b324cSopenharmony_ci Byte *buf = (Byte *)MidAlloc(kClusterSize); 276370b324cSopenharmony_ci 277370b324cSopenharmony_ci bool needbackward = true; 278370b324cSopenharmony_ci 279370b324cSopenharmony_ci for (;;) 280370b324cSopenharmony_ci { 281370b324cSopenharmony_ci UInt32 processed = 0; 282370b324cSopenharmony_ci // up test is slow for "PhysicalDrive". 283370b324cSopenharmony_ci // processed size for latest block for "PhysicalDrive0" is 0. 284370b324cSopenharmony_ci if (!Read1(buf, kClusterSize, processed)) 285370b324cSopenharmony_ci break; 286370b324cSopenharmony_ci if (processed == 0) 287370b324cSopenharmony_ci break; 288370b324cSopenharmony_ci needbackward = false; 289370b324cSopenharmony_ci Size = pos + processed; 290370b324cSopenharmony_ci if (processed != kClusterSize) 291370b324cSopenharmony_ci break; 292370b324cSopenharmony_ci pos += kClusterSize; 293370b324cSopenharmony_ci } 294370b324cSopenharmony_ci 295370b324cSopenharmony_ci if (needbackward && pos != 0) 296370b324cSopenharmony_ci { 297370b324cSopenharmony_ci pos -= kClusterSize; 298370b324cSopenharmony_ci for (;;) 299370b324cSopenharmony_ci { 300370b324cSopenharmony_ci // break; 301370b324cSopenharmony_ci if (!Seek(pos, realNewPosition)) 302370b324cSopenharmony_ci break; 303370b324cSopenharmony_ci if (!buf) 304370b324cSopenharmony_ci { 305370b324cSopenharmony_ci buf = (Byte *)MidAlloc(kClusterSize); 306370b324cSopenharmony_ci if (!buf) 307370b324cSopenharmony_ci break; 308370b324cSopenharmony_ci } 309370b324cSopenharmony_ci UInt32 processed = 0; 310370b324cSopenharmony_ci // that code doesn't work for "PhysicalDrive0" 311370b324cSopenharmony_ci if (!Read1(buf, kClusterSize, processed)) 312370b324cSopenharmony_ci break; 313370b324cSopenharmony_ci if (processed != 0) 314370b324cSopenharmony_ci { 315370b324cSopenharmony_ci Size = pos + processed; 316370b324cSopenharmony_ci break; 317370b324cSopenharmony_ci } 318370b324cSopenharmony_ci if (pos == 0) 319370b324cSopenharmony_ci break; 320370b324cSopenharmony_ci pos -= kClusterSize; 321370b324cSopenharmony_ci } 322370b324cSopenharmony_ci } 323370b324cSopenharmony_ci MidFree(buf); 324370b324cSopenharmony_ci} 325370b324cSopenharmony_ci 326370b324cSopenharmony_ci 327370b324cSopenharmony_civoid CInFile::CalcDeviceSize(CFSTR s) 328370b324cSopenharmony_ci{ 329370b324cSopenharmony_ci SizeDefined = false; 330370b324cSopenharmony_ci Size = 0; 331370b324cSopenharmony_ci if (_handle == INVALID_HANDLE_VALUE || !IsDeviceFile) 332370b324cSopenharmony_ci return; 333370b324cSopenharmony_ci #ifdef UNDER_CE 334370b324cSopenharmony_ci 335370b324cSopenharmony_ci SizeDefined = true; 336370b324cSopenharmony_ci Size = 128 << 20; 337370b324cSopenharmony_ci 338370b324cSopenharmony_ci #else 339370b324cSopenharmony_ci 340370b324cSopenharmony_ci PARTITION_INFORMATION partInfo; 341370b324cSopenharmony_ci bool needCorrectSize = true; 342370b324cSopenharmony_ci 343370b324cSopenharmony_ci /* 344370b324cSopenharmony_ci WinXP 64-bit: 345370b324cSopenharmony_ci 346370b324cSopenharmony_ci HDD \\.\PhysicalDrive0 (MBR): 347370b324cSopenharmony_ci GetPartitionInfo == GeometryEx : corrrect size? (includes tail) 348370b324cSopenharmony_ci Geometry : smaller than GeometryEx (no tail, maybe correct too?) 349370b324cSopenharmony_ci MyGetDiskFreeSpace : FAIL 350370b324cSopenharmony_ci Size correction is slow and block size (kClusterSize) must be small? 351370b324cSopenharmony_ci 352370b324cSopenharmony_ci HDD partition \\.\N: (NTFS): 353370b324cSopenharmony_ci MyGetDiskFreeSpace : Size of NTFS clusters. Same size can be calculated after correction 354370b324cSopenharmony_ci GetPartitionInfo : size of partition data: NTFS clusters + TAIL; TAIL contains extra empty sectors and copy of first sector of NTFS 355370b324cSopenharmony_ci Geometry / CdRomGeometry / GeometryEx : size of HDD (not that partition) 356370b324cSopenharmony_ci 357370b324cSopenharmony_ci CD-ROM drive (ISO): 358370b324cSopenharmony_ci MyGetDiskFreeSpace : correct size. Same size can be calculated after correction 359370b324cSopenharmony_ci Geometry == CdRomGeometry : smaller than corrrect size 360370b324cSopenharmony_ci GetPartitionInfo == GeometryEx : larger than corrrect size 361370b324cSopenharmony_ci 362370b324cSopenharmony_ci Floppy \\.\a: (FAT): 363370b324cSopenharmony_ci Geometry : correct size. 364370b324cSopenharmony_ci CdRomGeometry / GeometryEx / GetPartitionInfo / MyGetDiskFreeSpace - FAIL 365370b324cSopenharmony_ci correction works OK for FAT. 366370b324cSopenharmony_ci correction works OK for non-FAT, if kClusterSize = 512. 367370b324cSopenharmony_ci */ 368370b324cSopenharmony_ci 369370b324cSopenharmony_ci if (GetPartitionInfo(&partInfo)) 370370b324cSopenharmony_ci { 371370b324cSopenharmony_ci Size = (UInt64)partInfo.PartitionLength.QuadPart; 372370b324cSopenharmony_ci SizeDefined = true; 373370b324cSopenharmony_ci needCorrectSize = false; 374370b324cSopenharmony_ci if ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\' && (s)[5] == ':' && (s)[6] == 0) 375370b324cSopenharmony_ci { 376370b324cSopenharmony_ci FChar path[4] = { s[4], ':', '\\', 0 }; 377370b324cSopenharmony_ci UInt64 clusterSize, totalSize, freeSize; 378370b324cSopenharmony_ci if (NSystem::MyGetDiskFreeSpace(path, clusterSize, totalSize, freeSize)) 379370b324cSopenharmony_ci Size = totalSize; 380370b324cSopenharmony_ci else 381370b324cSopenharmony_ci needCorrectSize = true; 382370b324cSopenharmony_ci } 383370b324cSopenharmony_ci } 384370b324cSopenharmony_ci 385370b324cSopenharmony_ci if (!SizeDefined) 386370b324cSopenharmony_ci { 387370b324cSopenharmony_ci my_DISK_GEOMETRY_EX geomEx; 388370b324cSopenharmony_ci SizeDefined = GetGeometryEx(&geomEx); 389370b324cSopenharmony_ci if (SizeDefined) 390370b324cSopenharmony_ci Size = (UInt64)geomEx.DiskSize.QuadPart; 391370b324cSopenharmony_ci else 392370b324cSopenharmony_ci { 393370b324cSopenharmony_ci DISK_GEOMETRY geom; 394370b324cSopenharmony_ci SizeDefined = GetGeometry(&geom); 395370b324cSopenharmony_ci if (!SizeDefined) 396370b324cSopenharmony_ci SizeDefined = GetCdRomGeometry(&geom); 397370b324cSopenharmony_ci if (SizeDefined) 398370b324cSopenharmony_ci Size = (UInt64)geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; 399370b324cSopenharmony_ci } 400370b324cSopenharmony_ci } 401370b324cSopenharmony_ci 402370b324cSopenharmony_ci if (needCorrectSize && SizeDefined && Size != 0) 403370b324cSopenharmony_ci { 404370b324cSopenharmony_ci CorrectDeviceSize(); 405370b324cSopenharmony_ci SeekToBegin(); 406370b324cSopenharmony_ci } 407370b324cSopenharmony_ci 408370b324cSopenharmony_ci // SeekToBegin(); 409370b324cSopenharmony_ci #endif 410370b324cSopenharmony_ci} 411370b324cSopenharmony_ci 412370b324cSopenharmony_ci// ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 && 413370b324cSopenharmony_ci 414370b324cSopenharmony_ci#define MY_DEVICE_EXTRA_CODE \ 415370b324cSopenharmony_ci IsDeviceFile = IsDevicePath(fileName); \ 416370b324cSopenharmony_ci CalcDeviceSize(fileName); 417370b324cSopenharmony_ci#else 418370b324cSopenharmony_ci#define MY_DEVICE_EXTRA_CODE 419370b324cSopenharmony_ci#endif 420370b324cSopenharmony_ci 421370b324cSopenharmony_cibool CInFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) 422370b324cSopenharmony_ci{ 423370b324cSopenharmony_ci DWORD desiredAccess = GENERIC_READ; 424370b324cSopenharmony_ci 425370b324cSopenharmony_ci #ifdef _WIN32 426370b324cSopenharmony_ci if (PreserveATime) 427370b324cSopenharmony_ci desiredAccess |= FILE_WRITE_ATTRIBUTES; 428370b324cSopenharmony_ci #endif 429370b324cSopenharmony_ci 430370b324cSopenharmony_ci bool res = Create(fileName, desiredAccess, shareMode, creationDisposition, flagsAndAttributes); 431370b324cSopenharmony_ci 432370b324cSopenharmony_ci #ifdef _WIN32 433370b324cSopenharmony_ci if (res && PreserveATime) 434370b324cSopenharmony_ci { 435370b324cSopenharmony_ci FILETIME ft; 436370b324cSopenharmony_ci ft.dwHighDateTime = ft.dwLowDateTime = 0xFFFFFFFF; 437370b324cSopenharmony_ci ::SetFileTime(_handle, NULL, &ft, NULL); 438370b324cSopenharmony_ci } 439370b324cSopenharmony_ci #endif 440370b324cSopenharmony_ci 441370b324cSopenharmony_ci MY_DEVICE_EXTRA_CODE 442370b324cSopenharmony_ci return res; 443370b324cSopenharmony_ci} 444370b324cSopenharmony_ci 445370b324cSopenharmony_cibool CInFile::OpenShared(CFSTR fileName, bool shareForWrite) 446370b324cSopenharmony_ci{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } 447370b324cSopenharmony_ci 448370b324cSopenharmony_cibool CInFile::Open(CFSTR fileName) 449370b324cSopenharmony_ci { return OpenShared(fileName, false); } 450370b324cSopenharmony_ci 451370b324cSopenharmony_ci// ReadFile and WriteFile functions in Windows have BUG: 452370b324cSopenharmony_ci// If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) 453370b324cSopenharmony_ci// from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES 454370b324cSopenharmony_ci// (Insufficient system resources exist to complete the requested service). 455370b324cSopenharmony_ci 456370b324cSopenharmony_ci// Probably in some version of Windows there are problems with other sizes: 457370b324cSopenharmony_ci// for 32 MB (maybe also for 16 MB). 458370b324cSopenharmony_ci// And message can be "Network connection was lost" 459370b324cSopenharmony_ci 460370b324cSopenharmony_cistatic const UInt32 kChunkSizeMax = (1 << 22); 461370b324cSopenharmony_ci 462370b324cSopenharmony_cibool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw() 463370b324cSopenharmony_ci{ 464370b324cSopenharmony_ci DWORD processedLoc = 0; 465370b324cSopenharmony_ci const bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); 466370b324cSopenharmony_ci processedSize = (UInt32)processedLoc; 467370b324cSopenharmony_ci return res; 468370b324cSopenharmony_ci} 469370b324cSopenharmony_ci 470370b324cSopenharmony_cibool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw() 471370b324cSopenharmony_ci{ 472370b324cSopenharmony_ci if (size > kChunkSizeMax) 473370b324cSopenharmony_ci size = kChunkSizeMax; 474370b324cSopenharmony_ci return Read1(data, size, processedSize); 475370b324cSopenharmony_ci} 476370b324cSopenharmony_ci 477370b324cSopenharmony_cibool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) throw() 478370b324cSopenharmony_ci{ 479370b324cSopenharmony_ci processedSize = 0; 480370b324cSopenharmony_ci do 481370b324cSopenharmony_ci { 482370b324cSopenharmony_ci UInt32 processedLoc = 0; 483370b324cSopenharmony_ci const bool res = ReadPart(data, size, processedLoc); 484370b324cSopenharmony_ci processedSize += processedLoc; 485370b324cSopenharmony_ci if (!res) 486370b324cSopenharmony_ci return false; 487370b324cSopenharmony_ci if (processedLoc == 0) 488370b324cSopenharmony_ci return true; 489370b324cSopenharmony_ci data = (void *)((unsigned char *)data + processedLoc); 490370b324cSopenharmony_ci size -= processedLoc; 491370b324cSopenharmony_ci } 492370b324cSopenharmony_ci while (size > 0); 493370b324cSopenharmony_ci return true; 494370b324cSopenharmony_ci} 495370b324cSopenharmony_ci 496370b324cSopenharmony_cibool CInFile::ReadFull(void *data, size_t size, size_t &processedSize) throw() 497370b324cSopenharmony_ci{ 498370b324cSopenharmony_ci processedSize = 0; 499370b324cSopenharmony_ci do 500370b324cSopenharmony_ci { 501370b324cSopenharmony_ci UInt32 processedLoc = 0; 502370b324cSopenharmony_ci const UInt32 sizeLoc = (size > kChunkSizeMax ? (UInt32)kChunkSizeMax : (UInt32)size); 503370b324cSopenharmony_ci const bool res = Read1(data, sizeLoc, processedLoc); 504370b324cSopenharmony_ci processedSize += processedLoc; 505370b324cSopenharmony_ci if (!res) 506370b324cSopenharmony_ci return false; 507370b324cSopenharmony_ci if (processedLoc == 0) 508370b324cSopenharmony_ci return true; 509370b324cSopenharmony_ci data = (void *)((unsigned char *)data + processedLoc); 510370b324cSopenharmony_ci size -= processedLoc; 511370b324cSopenharmony_ci } 512370b324cSopenharmony_ci while (size > 0); 513370b324cSopenharmony_ci return true; 514370b324cSopenharmony_ci} 515370b324cSopenharmony_ci 516370b324cSopenharmony_ci// ---------- COutFile --------- 517370b324cSopenharmony_ci 518370b324cSopenharmony_cistatic inline DWORD GetCreationDisposition(bool createAlways) 519370b324cSopenharmony_ci { return createAlways? CREATE_ALWAYS: CREATE_NEW; } 520370b324cSopenharmony_ci 521370b324cSopenharmony_cibool COutFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) 522370b324cSopenharmony_ci { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } 523370b324cSopenharmony_ci 524370b324cSopenharmony_cibool COutFile::Open(CFSTR fileName, DWORD creationDisposition) 525370b324cSopenharmony_ci { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } 526370b324cSopenharmony_ci 527370b324cSopenharmony_cibool COutFile::Create(CFSTR fileName, bool createAlways) 528370b324cSopenharmony_ci { return Open(fileName, GetCreationDisposition(createAlways)); } 529370b324cSopenharmony_ci 530370b324cSopenharmony_cibool COutFile::CreateAlways(CFSTR fileName, DWORD flagsAndAttributes) 531370b324cSopenharmony_ci { return Open(fileName, FILE_SHARE_READ, GetCreationDisposition(true), flagsAndAttributes); } 532370b324cSopenharmony_ci 533370b324cSopenharmony_cibool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() 534370b324cSopenharmony_ci { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } 535370b324cSopenharmony_ci 536370b324cSopenharmony_cibool COutFile::SetMTime(const FILETIME *mTime) throw() { return SetTime(NULL, NULL, mTime); } 537370b324cSopenharmony_ci 538370b324cSopenharmony_cibool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw() 539370b324cSopenharmony_ci{ 540370b324cSopenharmony_ci if (size > kChunkSizeMax) 541370b324cSopenharmony_ci size = kChunkSizeMax; 542370b324cSopenharmony_ci DWORD processedLoc = 0; 543370b324cSopenharmony_ci bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); 544370b324cSopenharmony_ci processedSize = (UInt32)processedLoc; 545370b324cSopenharmony_ci return res; 546370b324cSopenharmony_ci} 547370b324cSopenharmony_ci 548370b324cSopenharmony_cibool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) throw() 549370b324cSopenharmony_ci{ 550370b324cSopenharmony_ci processedSize = 0; 551370b324cSopenharmony_ci do 552370b324cSopenharmony_ci { 553370b324cSopenharmony_ci UInt32 processedLoc = 0; 554370b324cSopenharmony_ci const bool res = WritePart(data, size, processedLoc); 555370b324cSopenharmony_ci processedSize += processedLoc; 556370b324cSopenharmony_ci if (!res) 557370b324cSopenharmony_ci return false; 558370b324cSopenharmony_ci if (processedLoc == 0) 559370b324cSopenharmony_ci return true; 560370b324cSopenharmony_ci data = (const void *)((const unsigned char *)data + processedLoc); 561370b324cSopenharmony_ci size -= processedLoc; 562370b324cSopenharmony_ci } 563370b324cSopenharmony_ci while (size != 0); 564370b324cSopenharmony_ci return true; 565370b324cSopenharmony_ci} 566370b324cSopenharmony_ci 567370b324cSopenharmony_cibool COutFile::WriteFull(const void *data, size_t size) throw() 568370b324cSopenharmony_ci{ 569370b324cSopenharmony_ci do 570370b324cSopenharmony_ci { 571370b324cSopenharmony_ci UInt32 processedLoc = 0; 572370b324cSopenharmony_ci const UInt32 sizeCur = (size > kChunkSizeMax ? kChunkSizeMax : (UInt32)size); 573370b324cSopenharmony_ci if (!WritePart(data, sizeCur, processedLoc)) 574370b324cSopenharmony_ci return false; 575370b324cSopenharmony_ci if (processedLoc == 0) 576370b324cSopenharmony_ci return (size == 0); 577370b324cSopenharmony_ci data = (const void *)((const unsigned char *)data + processedLoc); 578370b324cSopenharmony_ci size -= processedLoc; 579370b324cSopenharmony_ci } 580370b324cSopenharmony_ci while (size != 0); 581370b324cSopenharmony_ci return true; 582370b324cSopenharmony_ci} 583370b324cSopenharmony_ci 584370b324cSopenharmony_cibool COutFile::SetEndOfFile() throw() { return BOOLToBool(::SetEndOfFile(_handle)); } 585370b324cSopenharmony_ci 586370b324cSopenharmony_cibool COutFile::SetLength(UInt64 length) throw() 587370b324cSopenharmony_ci{ 588370b324cSopenharmony_ci UInt64 newPosition; 589370b324cSopenharmony_ci if (!Seek(length, newPosition)) 590370b324cSopenharmony_ci return false; 591370b324cSopenharmony_ci if (newPosition != length) 592370b324cSopenharmony_ci return false; 593370b324cSopenharmony_ci return SetEndOfFile(); 594370b324cSopenharmony_ci} 595370b324cSopenharmony_ci 596370b324cSopenharmony_cibool COutFile::SetLength_KeepPosition(UInt64 length) throw() 597370b324cSopenharmony_ci{ 598370b324cSopenharmony_ci UInt64 currentPos = 0; 599370b324cSopenharmony_ci if (!GetPosition(currentPos)) 600370b324cSopenharmony_ci return false; 601370b324cSopenharmony_ci DWORD lastError = 0; 602370b324cSopenharmony_ci const bool result = SetLength(length); 603370b324cSopenharmony_ci if (!result) 604370b324cSopenharmony_ci lastError = GetLastError(); 605370b324cSopenharmony_ci UInt64 currentPos2; 606370b324cSopenharmony_ci const bool result2 = Seek(currentPos, currentPos2); 607370b324cSopenharmony_ci if (lastError != 0) 608370b324cSopenharmony_ci SetLastError(lastError); 609370b324cSopenharmony_ci return (result && result2); 610370b324cSopenharmony_ci} 611370b324cSopenharmony_ci 612370b324cSopenharmony_ci}}} 613370b324cSopenharmony_ci 614370b324cSopenharmony_ci#else // _WIN32 615370b324cSopenharmony_ci 616370b324cSopenharmony_ci 617370b324cSopenharmony_ci// POSIX 618370b324cSopenharmony_ci 619370b324cSopenharmony_ci#include <fcntl.h> 620370b324cSopenharmony_ci#include <unistd.h> 621370b324cSopenharmony_ci 622370b324cSopenharmony_cinamespace NWindows { 623370b324cSopenharmony_cinamespace NFile { 624370b324cSopenharmony_ci 625370b324cSopenharmony_cinamespace NDir { 626370b324cSopenharmony_cibool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime); 627370b324cSopenharmony_ci} 628370b324cSopenharmony_ci 629370b324cSopenharmony_cinamespace NIO { 630370b324cSopenharmony_ci 631370b324cSopenharmony_cibool CFileBase::OpenBinary(const char *name, int flags, mode_t mode) 632370b324cSopenharmony_ci{ 633370b324cSopenharmony_ci #ifdef O_BINARY 634370b324cSopenharmony_ci flags |= O_BINARY; 635370b324cSopenharmony_ci #endif 636370b324cSopenharmony_ci 637370b324cSopenharmony_ci Close(); 638370b324cSopenharmony_ci _handle = ::open(name, flags, mode); 639370b324cSopenharmony_ci return _handle != -1; 640370b324cSopenharmony_ci 641370b324cSopenharmony_ci /* 642370b324cSopenharmony_ci if (_handle == -1) 643370b324cSopenharmony_ci return false; 644370b324cSopenharmony_ci if (IsString1PrefixedByString2(name, "/dev/")) 645370b324cSopenharmony_ci { 646370b324cSopenharmony_ci // /dev/sda 647370b324cSopenharmony_ci // IsDeviceFile = true; // for debug 648370b324cSopenharmony_ci // SizeDefined = false; 649370b324cSopenharmony_ci // SizeDefined = (GetDeviceSize_InBytes(Size) == 0); 650370b324cSopenharmony_ci } 651370b324cSopenharmony_ci return true; 652370b324cSopenharmony_ci */ 653370b324cSopenharmony_ci} 654370b324cSopenharmony_ci 655370b324cSopenharmony_cibool CFileBase::Close() 656370b324cSopenharmony_ci{ 657370b324cSopenharmony_ci if (_handle == -1) 658370b324cSopenharmony_ci return true; 659370b324cSopenharmony_ci if (close(_handle) != 0) 660370b324cSopenharmony_ci return false; 661370b324cSopenharmony_ci _handle = -1; 662370b324cSopenharmony_ci /* 663370b324cSopenharmony_ci IsDeviceFile = false; 664370b324cSopenharmony_ci SizeDefined = false; 665370b324cSopenharmony_ci */ 666370b324cSopenharmony_ci return true; 667370b324cSopenharmony_ci} 668370b324cSopenharmony_ci 669370b324cSopenharmony_cibool CFileBase::GetLength(UInt64 &length) const 670370b324cSopenharmony_ci{ 671370b324cSopenharmony_ci length = 0; 672370b324cSopenharmony_ci // length = (UInt64)(Int64)-1; // for debug 673370b324cSopenharmony_ci const off_t curPos = seekToCur(); 674370b324cSopenharmony_ci if (curPos == -1) 675370b324cSopenharmony_ci return false; 676370b324cSopenharmony_ci const off_t lengthTemp = seek(0, SEEK_END); 677370b324cSopenharmony_ci seek(curPos, SEEK_SET); 678370b324cSopenharmony_ci length = (UInt64)lengthTemp; 679370b324cSopenharmony_ci 680370b324cSopenharmony_ci /* 681370b324cSopenharmony_ci // 22.00: 682370b324cSopenharmony_ci if (lengthTemp == 1) 683370b324cSopenharmony_ci if (IsDeviceFile && SizeDefined) 684370b324cSopenharmony_ci { 685370b324cSopenharmony_ci length = Size; 686370b324cSopenharmony_ci return true; 687370b324cSopenharmony_ci } 688370b324cSopenharmony_ci */ 689370b324cSopenharmony_ci 690370b324cSopenharmony_ci return (lengthTemp != -1); 691370b324cSopenharmony_ci} 692370b324cSopenharmony_ci 693370b324cSopenharmony_cioff_t CFileBase::seek(off_t distanceToMove, int moveMethod) const 694370b324cSopenharmony_ci{ 695370b324cSopenharmony_ci /* 696370b324cSopenharmony_ci if (IsDeviceFile && SizeDefined && moveMethod == SEEK_END) 697370b324cSopenharmony_ci { 698370b324cSopenharmony_ci printf("\n seek : IsDeviceFile moveMethod = %d distanceToMove = %ld\n", moveMethod, distanceToMove); 699370b324cSopenharmony_ci distanceToMove += Size; 700370b324cSopenharmony_ci moveMethod = SEEK_SET; 701370b324cSopenharmony_ci } 702370b324cSopenharmony_ci */ 703370b324cSopenharmony_ci 704370b324cSopenharmony_ci // printf("\nCFileBase::seek() moveMethod = %d, distanceToMove = %lld", moveMethod, (long long)distanceToMove); 705370b324cSopenharmony_ci // off_t res = ::lseek(_handle, distanceToMove, moveMethod); 706370b324cSopenharmony_ci // printf("\n lseek : moveMethod = %d distanceToMove = %ld\n", moveMethod, distanceToMove); 707370b324cSopenharmony_ci return ::lseek(_handle, distanceToMove, moveMethod); 708370b324cSopenharmony_ci // return res; 709370b324cSopenharmony_ci} 710370b324cSopenharmony_ci 711370b324cSopenharmony_cioff_t CFileBase::seekToBegin() const throw() 712370b324cSopenharmony_ci{ 713370b324cSopenharmony_ci return seek(0, SEEK_SET); 714370b324cSopenharmony_ci} 715370b324cSopenharmony_ci 716370b324cSopenharmony_cioff_t CFileBase::seekToCur() const throw() 717370b324cSopenharmony_ci{ 718370b324cSopenharmony_ci return seek(0, SEEK_CUR); 719370b324cSopenharmony_ci} 720370b324cSopenharmony_ci 721370b324cSopenharmony_ci/* 722370b324cSopenharmony_cibool CFileBase::SeekToBegin() const throw() 723370b324cSopenharmony_ci{ 724370b324cSopenharmony_ci return (::seek(0, SEEK_SET) != -1); 725370b324cSopenharmony_ci} 726370b324cSopenharmony_ci*/ 727370b324cSopenharmony_ci 728370b324cSopenharmony_ci 729370b324cSopenharmony_ci///////////////////////// 730370b324cSopenharmony_ci// CInFile 731370b324cSopenharmony_ci 732370b324cSopenharmony_cibool CInFile::Open(const char *name) 733370b324cSopenharmony_ci{ 734370b324cSopenharmony_ci return CFileBase::OpenBinary(name, O_RDONLY); 735370b324cSopenharmony_ci} 736370b324cSopenharmony_ci 737370b324cSopenharmony_cibool CInFile::OpenShared(const char *name, bool) 738370b324cSopenharmony_ci{ 739370b324cSopenharmony_ci return Open(name); 740370b324cSopenharmony_ci} 741370b324cSopenharmony_ci 742370b324cSopenharmony_ci 743370b324cSopenharmony_ci/* 744370b324cSopenharmony_ciint CFileBase::my_ioctl_BLKGETSIZE64(unsigned long long *numBlocks) 745370b324cSopenharmony_ci{ 746370b324cSopenharmony_ci // we can read "/sys/block/sda/size" "/sys/block/sda/sda1/size" - partition 747370b324cSopenharmony_ci // #include <linux/fs.h> 748370b324cSopenharmony_ci return ioctl(_handle, BLKGETSIZE64, numBlocks); 749370b324cSopenharmony_ci // in block size 750370b324cSopenharmony_ci} 751370b324cSopenharmony_ci 752370b324cSopenharmony_ciint CFileBase::GetDeviceSize_InBytes(UInt64 &size) 753370b324cSopenharmony_ci{ 754370b324cSopenharmony_ci size = 0; 755370b324cSopenharmony_ci unsigned long long numBlocks; 756370b324cSopenharmony_ci int res = my_ioctl_BLKGETSIZE64(&numBlocks); 757370b324cSopenharmony_ci if (res == 0) 758370b324cSopenharmony_ci size = numBlocks; // another blockSize s possible? 759370b324cSopenharmony_ci printf("\nGetDeviceSize_InBytes res = %d, size = %lld\n", res, (long long)size); 760370b324cSopenharmony_ci return res; 761370b324cSopenharmony_ci} 762370b324cSopenharmony_ci*/ 763370b324cSopenharmony_ci 764370b324cSopenharmony_ci/* 765370b324cSopenharmony_ciOn Linux (32-bit and 64-bit): 766370b324cSopenharmony_ciread(), write() (and similar system calls) will transfer at most 767370b324cSopenharmony_ci0x7ffff000 = (2GiB - 4 KiB) bytes, returning the number of bytes actually transferred. 768370b324cSopenharmony_ci*/ 769370b324cSopenharmony_ci 770370b324cSopenharmony_cistatic const size_t kChunkSizeMax = ((size_t)1 << 22); 771370b324cSopenharmony_ci 772370b324cSopenharmony_cissize_t CInFile::read_part(void *data, size_t size) throw() 773370b324cSopenharmony_ci{ 774370b324cSopenharmony_ci if (size > kChunkSizeMax) 775370b324cSopenharmony_ci size = kChunkSizeMax; 776370b324cSopenharmony_ci return ::read(_handle, data, size); 777370b324cSopenharmony_ci} 778370b324cSopenharmony_ci 779370b324cSopenharmony_cibool CInFile::ReadFull(void *data, size_t size, size_t &processed) throw() 780370b324cSopenharmony_ci{ 781370b324cSopenharmony_ci processed = 0; 782370b324cSopenharmony_ci do 783370b324cSopenharmony_ci { 784370b324cSopenharmony_ci const ssize_t res = read_part(data, size); 785370b324cSopenharmony_ci if (res < 0) 786370b324cSopenharmony_ci return false; 787370b324cSopenharmony_ci if (res == 0) 788370b324cSopenharmony_ci break; 789370b324cSopenharmony_ci data = (void *)((unsigned char *)data + (size_t)res); 790370b324cSopenharmony_ci size -= (size_t)res; 791370b324cSopenharmony_ci processed += (size_t)res; 792370b324cSopenharmony_ci } 793370b324cSopenharmony_ci while (size > 0); 794370b324cSopenharmony_ci return true; 795370b324cSopenharmony_ci} 796370b324cSopenharmony_ci 797370b324cSopenharmony_ci 798370b324cSopenharmony_ci///////////////////////// 799370b324cSopenharmony_ci// COutFile 800370b324cSopenharmony_ci 801370b324cSopenharmony_cibool COutFile::Create(const char *name, bool createAlways) 802370b324cSopenharmony_ci{ 803370b324cSopenharmony_ci Path = name; // change it : set it only if open is success. 804370b324cSopenharmony_ci if (createAlways) 805370b324cSopenharmony_ci { 806370b324cSopenharmony_ci Close(); 807370b324cSopenharmony_ci _handle = ::creat(name, mode_for_Create); 808370b324cSopenharmony_ci return _handle != -1; 809370b324cSopenharmony_ci } 810370b324cSopenharmony_ci return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY, mode_for_Create); 811370b324cSopenharmony_ci} 812370b324cSopenharmony_ci 813370b324cSopenharmony_cibool COutFile::Open(const char *name, DWORD creationDisposition) 814370b324cSopenharmony_ci{ 815370b324cSopenharmony_ci UNUSED_VAR(creationDisposition) // FIXME 816370b324cSopenharmony_ci return Create(name, false); 817370b324cSopenharmony_ci} 818370b324cSopenharmony_ci 819370b324cSopenharmony_cissize_t COutFile::write_part(const void *data, size_t size) throw() 820370b324cSopenharmony_ci{ 821370b324cSopenharmony_ci if (size > kChunkSizeMax) 822370b324cSopenharmony_ci size = kChunkSizeMax; 823370b324cSopenharmony_ci return ::write(_handle, data, size); 824370b324cSopenharmony_ci} 825370b324cSopenharmony_ci 826370b324cSopenharmony_cissize_t COutFile::write_full(const void *data, size_t size, size_t &processed) throw() 827370b324cSopenharmony_ci{ 828370b324cSopenharmony_ci processed = 0; 829370b324cSopenharmony_ci do 830370b324cSopenharmony_ci { 831370b324cSopenharmony_ci const ssize_t res = write_part(data, size); 832370b324cSopenharmony_ci if (res < 0) 833370b324cSopenharmony_ci return res; 834370b324cSopenharmony_ci if (res == 0) 835370b324cSopenharmony_ci break; 836370b324cSopenharmony_ci data = (const void *)((const unsigned char *)data + (size_t)res); 837370b324cSopenharmony_ci size -= (size_t)res; 838370b324cSopenharmony_ci processed += (size_t)res; 839370b324cSopenharmony_ci } 840370b324cSopenharmony_ci while (size > 0); 841370b324cSopenharmony_ci return (ssize_t)processed; 842370b324cSopenharmony_ci} 843370b324cSopenharmony_ci 844370b324cSopenharmony_cibool COutFile::SetLength(UInt64 length) throw() 845370b324cSopenharmony_ci{ 846370b324cSopenharmony_ci const off_t len2 = (off_t)length; 847370b324cSopenharmony_ci if ((Int64)length != len2) 848370b324cSopenharmony_ci { 849370b324cSopenharmony_ci SetLastError(EFBIG); 850370b324cSopenharmony_ci return false; 851370b324cSopenharmony_ci } 852370b324cSopenharmony_ci // The value of the seek pointer shall not be modified by a call to ftruncate(). 853370b324cSopenharmony_ci const int iret = ftruncate(_handle, len2); 854370b324cSopenharmony_ci return (iret == 0); 855370b324cSopenharmony_ci} 856370b324cSopenharmony_ci 857370b324cSopenharmony_cibool COutFile::Close() 858370b324cSopenharmony_ci{ 859370b324cSopenharmony_ci const bool res = CFileBase::Close(); 860370b324cSopenharmony_ci if (!res) 861370b324cSopenharmony_ci return res; 862370b324cSopenharmony_ci if (CTime_defined || ATime_defined || MTime_defined) 863370b324cSopenharmony_ci { 864370b324cSopenharmony_ci /* bool res2 = */ NWindows::NFile::NDir::SetDirTime(Path, 865370b324cSopenharmony_ci CTime_defined ? &CTime : NULL, 866370b324cSopenharmony_ci ATime_defined ? &ATime : NULL, 867370b324cSopenharmony_ci MTime_defined ? &MTime : NULL); 868370b324cSopenharmony_ci } 869370b324cSopenharmony_ci return res; 870370b324cSopenharmony_ci} 871370b324cSopenharmony_ci 872370b324cSopenharmony_cibool COutFile::SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw() 873370b324cSopenharmony_ci{ 874370b324cSopenharmony_ci // On some OS (cygwin, MacOSX ...), you must close the file before updating times 875370b324cSopenharmony_ci // return true; 876370b324cSopenharmony_ci 877370b324cSopenharmony_ci if (cTime) { CTime = *cTime; CTime_defined = true; } else CTime_defined = false; 878370b324cSopenharmony_ci if (aTime) { ATime = *aTime; ATime_defined = true; } else ATime_defined = false; 879370b324cSopenharmony_ci if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; 880370b324cSopenharmony_ci return true; 881370b324cSopenharmony_ci 882370b324cSopenharmony_ci /* 883370b324cSopenharmony_ci struct timespec times[2]; 884370b324cSopenharmony_ci UNUSED_VAR(cTime) 885370b324cSopenharmony_ci if (!aTime && !mTime) 886370b324cSopenharmony_ci return true; 887370b324cSopenharmony_ci bool needChange; 888370b324cSopenharmony_ci needChange = FiTime_To_timespec(aTime, times[0]); 889370b324cSopenharmony_ci needChange |= FiTime_To_timespec(mTime, times[1]); 890370b324cSopenharmony_ci if (!needChange) 891370b324cSopenharmony_ci return true; 892370b324cSopenharmony_ci return futimens(_handle, times) == 0; 893370b324cSopenharmony_ci */ 894370b324cSopenharmony_ci} 895370b324cSopenharmony_ci 896370b324cSopenharmony_cibool COutFile::SetMTime(const CFiTime *mTime) throw() 897370b324cSopenharmony_ci{ 898370b324cSopenharmony_ci if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; 899370b324cSopenharmony_ci return true; 900370b324cSopenharmony_ci} 901370b324cSopenharmony_ci 902370b324cSopenharmony_ci}}} 903370b324cSopenharmony_ci 904370b324cSopenharmony_ci 905370b324cSopenharmony_ci#endif 906