Changeset 77825 in vbox for trunk/src/VBox
- Timestamp:
- Mar 21, 2019 12:33:42 PM (6 years ago)
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 2 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/Makefile.kmk
r77816 r77825 666 666 generic/RTEnvDupEx-generic.cpp \ 667 667 generic/RTFileCopy-generic.cpp \ 668 generic/RTFileCopyEx-generic.cpp \ 669 generic/RTFileCopyByHandlesEx-generic.cpp \ 668 670 generic/RTFileCopyRange-generic.cpp \ 669 671 generic/RTFileCopyRangeEx-generic.cpp \ … … 1788 1790 generic/RTEnvDupEx-generic.cpp \ 1789 1791 generic/RTFileCopy-generic.cpp \ 1792 generic/RTFileCopyEx-generic.cpp \ 1793 generic/RTFileCopyByHandlesEx-generic.cpp \ 1790 1794 generic/RTFileQuerySize-generic.cpp \ 1791 1795 generic/RTFileReadAll-generic.cpp \ -
trunk/src/VBox/Runtime/generic/RTFileCopyByHandlesEx-generic.cpp
r77822 r77825 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - File I/O.3 * IPRT - RTFileCopyByHandlesEx, generic implementation. 4 4 */ 5 5 … … 32 32 #include <iprt/file.h> 33 33 34 #include <iprt/alloca.h> 35 #include <iprt/assert.h> 34 36 #include <iprt/mem.h> 35 #include <iprt/assert.h> 36 #include <iprt/alloca.h> 37 #include <iprt/string.h> 38 #include <iprt/err.h> 39 #include "internal/file.h" 40 41 42 /********************************************************************************************************************************* 43 * Global Variables * 44 *********************************************************************************************************************************/ 45 /** Set of forced set open flags for files opened read-only. */ 46 static unsigned g_fOpenReadSet = 0; 47 48 /** Set of forced cleared open flags for files opened read-only. */ 49 static unsigned g_fOpenReadMask = 0; 50 51 /** Set of forced set open flags for files opened write-only. */ 52 static unsigned g_fOpenWriteSet = 0; 53 54 /** Set of forced cleared open flags for files opened write-only. */ 55 static unsigned g_fOpenWriteMask = 0; 56 57 /** Set of forced set open flags for files opened read-write. */ 58 static unsigned g_fOpenReadWriteSet = 0; 59 60 /** Set of forced cleared open flags for files opened read-write. */ 61 static unsigned g_fOpenReadWriteMask = 0; 62 63 64 /** 65 * Force the use of open flags for all files opened after the setting is 66 * changed. The caller is responsible for not causing races with RTFileOpen(). 67 * 68 * @returns iprt status code. 69 * @param fOpenForAccess Access mode to which the set/mask settings apply. 70 * @param fSet Open flags to be forced set. 71 * @param fMask Open flags to be masked out. 72 */ 73 RTR3DECL(int) RTFileSetForceFlags(unsigned fOpenForAccess, unsigned fSet, unsigned fMask) 74 { 75 /* 76 * For now allow only RTFILE_O_WRITE_THROUGH. The other flags either 77 * make no sense in this context or are not useful to apply to all files. 78 */ 79 if ((fSet | fMask) & ~RTFILE_O_WRITE_THROUGH) 80 return VERR_INVALID_PARAMETER; 81 switch (fOpenForAccess) 82 { 83 case RTFILE_O_READ: 84 g_fOpenReadSet = fSet; 85 g_fOpenReadMask = fMask; 86 break; 87 case RTFILE_O_WRITE: 88 g_fOpenWriteSet = fSet; 89 g_fOpenWriteMask = fMask; 90 break; 91 case RTFILE_O_READWRITE: 92 g_fOpenReadWriteSet = fSet; 93 g_fOpenReadWriteMask = fMask; 94 break; 95 default: 96 AssertMsgFailed(("Invalid access mode %d\n", fOpenForAccess)); 97 return VERR_INVALID_PARAMETER; 98 } 99 return VINF_SUCCESS; 100 } 101 102 103 /** 104 * Adjusts and validates the flags. 105 * 106 * The adjustments are made according to the wishes specified using the RTFileSetForceFlags API. 107 * 108 * @returns IPRT status code. 109 * @param pfOpen Pointer to the user specified flags on input. 110 * Updated on successful return. 111 * @internal 112 */ 113 int rtFileRecalcAndValidateFlags(uint64_t *pfOpen) 114 { 115 /* 116 * Recalc. 117 */ 118 uint32_t fOpen = *pfOpen; 119 switch (fOpen & RTFILE_O_ACCESS_MASK) 120 { 121 case RTFILE_O_READ: 122 fOpen |= g_fOpenReadSet; 123 fOpen &= ~g_fOpenReadMask; 124 break; 125 case RTFILE_O_WRITE: 126 fOpen |= g_fOpenWriteSet; 127 fOpen &= ~g_fOpenWriteMask; 128 break; 129 case RTFILE_O_READWRITE: 130 fOpen |= g_fOpenReadWriteSet; 131 fOpen &= ~g_fOpenReadWriteMask; 132 break; 133 #ifdef RT_OS_WINDOWS 134 case RTFILE_O_ATTR_ONLY: 135 if (fOpen & RTFILE_O_ACCESS_ATTR_MASK) 136 break; 137 #endif 138 default: 139 AssertMsgFailed(("Invalid access mode value, fOpen=%#llx\n", fOpen)); 140 return VERR_INVALID_PARAMETER; 141 } 142 143 /* 144 * Validate . 145 */ 146 #ifdef RT_OS_WINDOWS 147 AssertMsgReturn((fOpen & RTFILE_O_ACCESS_MASK) || (fOpen & RTFILE_O_ACCESS_ATTR_MASK), 148 ("Missing RTFILE_O_READ/WRITE/ACCESS_ATTR: fOpen=%#llx\n", fOpen), VERR_INVALID_PARAMETER); 149 #else 150 AssertMsgReturn(fOpen & RTFILE_O_ACCESS_MASK, ("Missing RTFILE_O_READ/WRITE: fOpen=%#llx\n", fOpen), VERR_INVALID_PARAMETER); 151 #endif 152 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) 153 AssertMsgReturn(!(fOpen & (~(uint64_t)RTFILE_O_VALID_MASK | RTFILE_O_NON_BLOCK)), ("%#llx\n", fOpen), VERR_INVALID_PARAMETER); 154 #else 155 AssertMsgReturn(!(fOpen & ~(uint64_t)RTFILE_O_VALID_MASK), ("%#llx\n", fOpen), VERR_INVALID_PARAMETER); 156 #endif 157 AssertMsgReturn((fOpen & (RTFILE_O_TRUNCATE | RTFILE_O_WRITE)) != RTFILE_O_TRUNCATE, ("%#llx\n", fOpen), VERR_INVALID_PARAMETER); 158 159 switch (fOpen & RTFILE_O_ACTION_MASK) 160 { 161 case 0: /* temporarily */ 162 AssertMsgFailed(("Missing RTFILE_O_OPEN/CREATE*! (continuable assertion)\n")); 163 fOpen |= RTFILE_O_OPEN; 164 break; 165 case RTFILE_O_OPEN: 166 AssertMsgReturn(!(RTFILE_O_NOT_CONTENT_INDEXED & fOpen), ("%#llx\n", fOpen), VERR_INVALID_PARAMETER); 167 case RTFILE_O_OPEN_CREATE: 168 case RTFILE_O_CREATE: 169 case RTFILE_O_CREATE_REPLACE: 170 break; 171 default: 172 AssertMsgFailed(("Invalid action value: fOpen=%#llx\n", fOpen)); 173 return VERR_INVALID_PARAMETER; 174 } 175 176 switch (fOpen & RTFILE_O_DENY_MASK) 177 { 178 case 0: /* temporarily */ 179 AssertMsgFailed(("Missing RTFILE_O_DENY_*! (continuable assertion)\n")); 180 fOpen |= RTFILE_O_DENY_NONE; 181 break; 182 case RTFILE_O_DENY_NONE: 183 case RTFILE_O_DENY_READ: 184 case RTFILE_O_DENY_WRITE: 185 case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ: 186 case RTFILE_O_DENY_NOT_DELETE: 187 case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_READ: 188 case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_WRITE: 189 case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ: 190 break; 191 default: 192 AssertMsgFailed(("Invalid deny value: fOpen=%#llx\n", fOpen)); 193 return VERR_INVALID_PARAMETER; 194 } 195 196 /* done */ 197 *pfOpen = fOpen; 198 return VINF_SUCCESS; 199 } 200 201 202 /** 203 * Gets the current file position. 204 * 205 * @returns File offset. 206 * @returns ~0UUL on failure. 207 * @param File File handle. 208 */ 209 RTR3DECL(uint64_t) RTFileTell(RTFILE File) 210 { 211 /* 212 * Call the seek api to query the stuff. 213 */ 214 uint64_t off = 0; 215 int rc = RTFileSeek(File, 0, RTFILE_SEEK_CURRENT, &off); 216 if (RT_SUCCESS(rc)) 217 return off; 218 AssertMsgFailed(("RTFileSeek(%d) -> %d\n", File, rc)); 219 return ~0ULL; 220 } 221 222 223 /** 224 * Determine the maximum file size. 225 * 226 * @returns The max size of the file. 227 * -1 on failure, the file position is undefined. 228 * @param File Handle to the file. 229 * @see RTFileGetMaxSizeEx. 230 */ 231 RTR3DECL(RTFOFF) RTFileGetMaxSize(RTFILE File) 232 { 233 RTFOFF cbMax; 234 int rc = RTFileGetMaxSizeEx(File, &cbMax); 235 return RT_SUCCESS(rc) ? cbMax : -1; 236 } 237 238 239 RTDECL(int) RTFileCopyByHandles(RTFILE FileSrc, RTFILE FileDst) 240 { 241 return RTFileCopyByHandlesEx(FileSrc, FileDst, NULL, NULL); 242 } 243 244 245 RTDECL(int) RTFileCopyEx(const char *pszSrc, const char *pszDst, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser) 246 { 247 /* 248 * Validate input. 249 */ 250 AssertMsgReturn(VALID_PTR(pszSrc), ("pszSrc=%p\n", pszSrc), VERR_INVALID_PARAMETER); 251 AssertMsgReturn(*pszSrc, ("pszSrc=%p\n", pszSrc), VERR_INVALID_PARAMETER); 252 AssertMsgReturn(VALID_PTR(pszDst), ("pszDst=%p\n", pszDst), VERR_INVALID_PARAMETER); 253 AssertMsgReturn(*pszDst, ("pszDst=%p\n", pszDst), VERR_INVALID_PARAMETER); 254 AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER); 255 AssertMsgReturn(!(fFlags & ~RTFILECOPY_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER); 256 257 /* 258 * Open the files. 259 */ 260 RTFILE FileSrc; 261 int rc = RTFileOpen(&FileSrc, pszSrc, 262 RTFILE_O_READ | RTFILE_O_OPEN 263 | (fFlags & RTFILECOPY_FLAGS_NO_SRC_DENY_WRITE ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE)); 264 if (RT_SUCCESS(rc)) 265 { 266 RTFILE FileDst; 267 rc = RTFileOpen(&FileDst, pszDst, 268 RTFILE_O_WRITE | RTFILE_O_CREATE 269 | (fFlags & RTFILECOPY_FLAGS_NO_DST_DENY_WRITE ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE)); 270 if (RT_SUCCESS(rc)) 271 { 272 /* 273 * Call the ByHandles version and let it do the job. 274 */ 275 rc = RTFileCopyByHandlesEx(FileSrc, FileDst, pfnProgress, pvUser); 276 277 /* 278 * Close the files regardless of the result. 279 * Don't bother cleaning up or anything like that. 280 */ 281 int rc2 = RTFileClose(FileDst); 282 AssertRC(rc2); 283 if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) 284 rc = rc2; 285 } 286 287 int rc2 = RTFileClose(FileSrc); 288 AssertRC(rc2); 289 if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) 290 rc = rc2; 291 } 292 return rc; 293 } 37 #include <iprt/errcore.h> 294 38 295 39 … … 410 154 } 411 155 412 413 RTDECL(int) RTFileCompare(const char *pszFile1, const char *pszFile2)414 {415 return RTFileCompareEx(pszFile1, pszFile2, 0 /*fFlags*/, NULL, NULL);416 }417 418 419 RTDECL(int) RTFileCompareByHandles(RTFILE hFile1, RTFILE hFile2)420 {421 return RTFileCompareByHandlesEx(hFile1, hFile2, 0 /*fFlags*/, NULL, NULL);422 }423 424 425 RTDECL(int) RTFileCompareEx(const char *pszFile1, const char *pszFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)426 {427 /*428 * Validate input.429 */430 AssertPtrReturn(pszFile1, VERR_INVALID_POINTER);431 AssertReturn(*pszFile1, VERR_INVALID_PARAMETER);432 AssertPtrReturn(pszFile2, VERR_INVALID_POINTER);433 AssertReturn(*pszFile2, VERR_INVALID_PARAMETER);434 AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);435 AssertMsgReturn(!(fFlags & ~RTFILECOMP_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);436 437 /*438 * Open the files.439 */440 RTFILE hFile1;441 int rc = RTFileOpen(&hFile1, pszFile1,442 RTFILE_O_READ | RTFILE_O_OPEN443 | (fFlags & RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE1 ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));444 if (RT_SUCCESS(rc))445 {446 RTFILE hFile2;447 rc = RTFileOpen(&hFile2, pszFile2,448 RTFILE_O_READ | RTFILE_O_OPEN449 | (fFlags & RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE2 ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));450 if (RT_SUCCESS(rc))451 {452 /*453 * Call the ByHandles version and let it do the job.454 */455 rc = RTFileCompareByHandlesEx(hFile1, hFile2, fFlags, pfnProgress, pvUser);456 457 /* Clean up */458 int rc2 = RTFileClose(hFile2);459 AssertRC(rc2);460 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))461 rc = rc2;462 }463 464 int rc2 = RTFileClose(hFile1);465 AssertRC(rc2);466 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))467 rc = rc2;468 }469 return rc;470 }471 472 473 RTDECL(int) RTFileCompareByHandlesEx(RTFILE hFile1, RTFILE hFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)474 {475 /*476 * Validate input.477 */478 AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE);479 AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE);480 AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);481 AssertMsgReturn(!(fFlags & ~RTFILECOMP_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);482 483 /*484 * Compare the file sizes first.485 */486 uint64_t cbFile1;487 int rc = RTFileGetSize(hFile1, &cbFile1);488 if (RT_FAILURE(rc))489 return rc;490 491 uint64_t cbFile2;492 rc = RTFileGetSize(hFile1, &cbFile2);493 if (RT_FAILURE(rc))494 return rc;495 496 if (cbFile1 != cbFile2)497 return VERR_NOT_EQUAL;498 499 500 /*501 * Allocate buffer.502 */503 size_t cbBuf;504 uint8_t *pbBuf1Free = NULL;505 uint8_t *pbBuf1;506 uint8_t *pbBuf2Free = NULL;507 uint8_t *pbBuf2;508 if (cbFile1 < _512K)509 {510 cbBuf = 8*_1K;511 pbBuf1 = (uint8_t *)alloca(cbBuf);512 pbBuf2 = (uint8_t *)alloca(cbBuf);513 }514 else515 {516 cbBuf = _128K;517 pbBuf1 = pbBuf1Free = (uint8_t *)RTMemTmpAlloc(cbBuf);518 pbBuf2 = pbBuf2Free = (uint8_t *)RTMemTmpAlloc(cbBuf);519 }520 if (pbBuf1 && pbBuf2)521 {522 /*523 * Seek to the start of each file524 * and set the size of the destination file.525 */526 rc = RTFileSeek(hFile1, 0, RTFILE_SEEK_BEGIN, NULL);527 if (RT_SUCCESS(rc))528 {529 rc = RTFileSeek(hFile2, 0, RTFILE_SEEK_BEGIN, NULL);530 if (RT_SUCCESS(rc) && pfnProgress)531 rc = pfnProgress(0, pvUser);532 if (RT_SUCCESS(rc))533 {534 /*535 * Compare loop.536 */537 unsigned uPercentage = 0;538 RTFOFF off = 0;539 RTFOFF cbPercent = cbFile1 / 100;540 RTFOFF offNextPercent = cbPercent;541 while (off < (RTFOFF)cbFile1)542 {543 /* read the blocks */544 RTFOFF cbLeft = cbFile1 - off;545 size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft;546 rc = RTFileRead(hFile1, pbBuf1, cbBlock, NULL);547 if (RT_FAILURE(rc))548 break;549 rc = RTFileRead(hFile2, pbBuf2, cbBlock, NULL);550 if (RT_FAILURE(rc))551 break;552 553 /* compare */554 if (memcmp(pbBuf1, pbBuf2, cbBlock))555 {556 rc = VERR_NOT_EQUAL;557 break;558 }559 560 /* advance */561 off += cbBlock;562 if (pfnProgress && offNextPercent < off)563 {564 while (offNextPercent < off)565 {566 uPercentage++;567 offNextPercent += cbPercent;568 }569 rc = pfnProgress(uPercentage, pvUser);570 if (RT_FAILURE(rc))571 break;572 }573 }574 575 #if 0576 /*577 * Compare OS specific data (EAs and stuff).578 */579 if (RT_SUCCESS(rc))580 rc = rtFileCompareOSStuff(hFile1, hFile2);581 #endif582 583 /* 100% */584 if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc))585 rc = pfnProgress(100, pvUser);586 }587 }588 }589 else590 rc = VERR_NO_MEMORY;591 RTMemTmpFree(pbBuf2Free);592 RTMemTmpFree(pbBuf1Free);593 594 return rc;595 }596 -
trunk/src/VBox/Runtime/generic/RTFileCopyEx-generic.cpp
r77822 r77825 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - File I/O.3 * IPRT - RTFileCopyEx, generic implementation. 4 4 */ 5 5 … … 32 32 #include <iprt/file.h> 33 33 34 #include <iprt/mem.h>35 34 #include <iprt/assert.h> 36 #include <iprt/alloca.h> 37 #include <iprt/string.h> 38 #include <iprt/err.h> 39 #include "internal/file.h" 40 41 42 /********************************************************************************************************************************* 43 * Global Variables * 44 *********************************************************************************************************************************/ 45 /** Set of forced set open flags for files opened read-only. */ 46 static unsigned g_fOpenReadSet = 0; 47 48 /** Set of forced cleared open flags for files opened read-only. */ 49 static unsigned g_fOpenReadMask = 0; 50 51 /** Set of forced set open flags for files opened write-only. */ 52 static unsigned g_fOpenWriteSet = 0; 53 54 /** Set of forced cleared open flags for files opened write-only. */ 55 static unsigned g_fOpenWriteMask = 0; 56 57 /** Set of forced set open flags for files opened read-write. */ 58 static unsigned g_fOpenReadWriteSet = 0; 59 60 /** Set of forced cleared open flags for files opened read-write. */ 61 static unsigned g_fOpenReadWriteMask = 0; 62 63 64 /** 65 * Force the use of open flags for all files opened after the setting is 66 * changed. The caller is responsible for not causing races with RTFileOpen(). 67 * 68 * @returns iprt status code. 69 * @param fOpenForAccess Access mode to which the set/mask settings apply. 70 * @param fSet Open flags to be forced set. 71 * @param fMask Open flags to be masked out. 72 */ 73 RTR3DECL(int) RTFileSetForceFlags(unsigned fOpenForAccess, unsigned fSet, unsigned fMask) 74 { 75 /* 76 * For now allow only RTFILE_O_WRITE_THROUGH. The other flags either 77 * make no sense in this context or are not useful to apply to all files. 78 */ 79 if ((fSet | fMask) & ~RTFILE_O_WRITE_THROUGH) 80 return VERR_INVALID_PARAMETER; 81 switch (fOpenForAccess) 82 { 83 case RTFILE_O_READ: 84 g_fOpenReadSet = fSet; 85 g_fOpenReadMask = fMask; 86 break; 87 case RTFILE_O_WRITE: 88 g_fOpenWriteSet = fSet; 89 g_fOpenWriteMask = fMask; 90 break; 91 case RTFILE_O_READWRITE: 92 g_fOpenReadWriteSet = fSet; 93 g_fOpenReadWriteMask = fMask; 94 break; 95 default: 96 AssertMsgFailed(("Invalid access mode %d\n", fOpenForAccess)); 97 return VERR_INVALID_PARAMETER; 98 } 99 return VINF_SUCCESS; 100 } 101 102 103 /** 104 * Adjusts and validates the flags. 105 * 106 * The adjustments are made according to the wishes specified using the RTFileSetForceFlags API. 107 * 108 * @returns IPRT status code. 109 * @param pfOpen Pointer to the user specified flags on input. 110 * Updated on successful return. 111 * @internal 112 */ 113 int rtFileRecalcAndValidateFlags(uint64_t *pfOpen) 114 { 115 /* 116 * Recalc. 117 */ 118 uint32_t fOpen = *pfOpen; 119 switch (fOpen & RTFILE_O_ACCESS_MASK) 120 { 121 case RTFILE_O_READ: 122 fOpen |= g_fOpenReadSet; 123 fOpen &= ~g_fOpenReadMask; 124 break; 125 case RTFILE_O_WRITE: 126 fOpen |= g_fOpenWriteSet; 127 fOpen &= ~g_fOpenWriteMask; 128 break; 129 case RTFILE_O_READWRITE: 130 fOpen |= g_fOpenReadWriteSet; 131 fOpen &= ~g_fOpenReadWriteMask; 132 break; 133 #ifdef RT_OS_WINDOWS 134 case RTFILE_O_ATTR_ONLY: 135 if (fOpen & RTFILE_O_ACCESS_ATTR_MASK) 136 break; 137 #endif 138 default: 139 AssertMsgFailed(("Invalid access mode value, fOpen=%#llx\n", fOpen)); 140 return VERR_INVALID_PARAMETER; 141 } 142 143 /* 144 * Validate . 145 */ 146 #ifdef RT_OS_WINDOWS 147 AssertMsgReturn((fOpen & RTFILE_O_ACCESS_MASK) || (fOpen & RTFILE_O_ACCESS_ATTR_MASK), 148 ("Missing RTFILE_O_READ/WRITE/ACCESS_ATTR: fOpen=%#llx\n", fOpen), VERR_INVALID_PARAMETER); 149 #else 150 AssertMsgReturn(fOpen & RTFILE_O_ACCESS_MASK, ("Missing RTFILE_O_READ/WRITE: fOpen=%#llx\n", fOpen), VERR_INVALID_PARAMETER); 151 #endif 152 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) 153 AssertMsgReturn(!(fOpen & (~(uint64_t)RTFILE_O_VALID_MASK | RTFILE_O_NON_BLOCK)), ("%#llx\n", fOpen), VERR_INVALID_PARAMETER); 154 #else 155 AssertMsgReturn(!(fOpen & ~(uint64_t)RTFILE_O_VALID_MASK), ("%#llx\n", fOpen), VERR_INVALID_PARAMETER); 156 #endif 157 AssertMsgReturn((fOpen & (RTFILE_O_TRUNCATE | RTFILE_O_WRITE)) != RTFILE_O_TRUNCATE, ("%#llx\n", fOpen), VERR_INVALID_PARAMETER); 158 159 switch (fOpen & RTFILE_O_ACTION_MASK) 160 { 161 case 0: /* temporarily */ 162 AssertMsgFailed(("Missing RTFILE_O_OPEN/CREATE*! (continuable assertion)\n")); 163 fOpen |= RTFILE_O_OPEN; 164 break; 165 case RTFILE_O_OPEN: 166 AssertMsgReturn(!(RTFILE_O_NOT_CONTENT_INDEXED & fOpen), ("%#llx\n", fOpen), VERR_INVALID_PARAMETER); 167 case RTFILE_O_OPEN_CREATE: 168 case RTFILE_O_CREATE: 169 case RTFILE_O_CREATE_REPLACE: 170 break; 171 default: 172 AssertMsgFailed(("Invalid action value: fOpen=%#llx\n", fOpen)); 173 return VERR_INVALID_PARAMETER; 174 } 175 176 switch (fOpen & RTFILE_O_DENY_MASK) 177 { 178 case 0: /* temporarily */ 179 AssertMsgFailed(("Missing RTFILE_O_DENY_*! (continuable assertion)\n")); 180 fOpen |= RTFILE_O_DENY_NONE; 181 break; 182 case RTFILE_O_DENY_NONE: 183 case RTFILE_O_DENY_READ: 184 case RTFILE_O_DENY_WRITE: 185 case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ: 186 case RTFILE_O_DENY_NOT_DELETE: 187 case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_READ: 188 case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_WRITE: 189 case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ: 190 break; 191 default: 192 AssertMsgFailed(("Invalid deny value: fOpen=%#llx\n", fOpen)); 193 return VERR_INVALID_PARAMETER; 194 } 195 196 /* done */ 197 *pfOpen = fOpen; 198 return VINF_SUCCESS; 199 } 200 201 202 /** 203 * Gets the current file position. 204 * 205 * @returns File offset. 206 * @returns ~0UUL on failure. 207 * @param File File handle. 208 */ 209 RTR3DECL(uint64_t) RTFileTell(RTFILE File) 210 { 211 /* 212 * Call the seek api to query the stuff. 213 */ 214 uint64_t off = 0; 215 int rc = RTFileSeek(File, 0, RTFILE_SEEK_CURRENT, &off); 216 if (RT_SUCCESS(rc)) 217 return off; 218 AssertMsgFailed(("RTFileSeek(%d) -> %d\n", File, rc)); 219 return ~0ULL; 220 } 221 222 223 /** 224 * Determine the maximum file size. 225 * 226 * @returns The max size of the file. 227 * -1 on failure, the file position is undefined. 228 * @param File Handle to the file. 229 * @see RTFileGetMaxSizeEx. 230 */ 231 RTR3DECL(RTFOFF) RTFileGetMaxSize(RTFILE File) 232 { 233 RTFOFF cbMax; 234 int rc = RTFileGetMaxSizeEx(File, &cbMax); 235 return RT_SUCCESS(rc) ? cbMax : -1; 236 } 237 238 239 RTDECL(int) RTFileCopyByHandles(RTFILE FileSrc, RTFILE FileDst) 240 { 241 return RTFileCopyByHandlesEx(FileSrc, FileDst, NULL, NULL); 242 } 35 #include <iprt/errcore.h> 243 36 244 37 … … 293 86 } 294 87 295 296 RTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser)297 {298 /*299 * Validate input.300 */301 AssertMsgReturn(RTFileIsValid(FileSrc), ("FileSrc=%RTfile\n", FileSrc), VERR_INVALID_PARAMETER);302 AssertMsgReturn(RTFileIsValid(FileDst), ("FileDst=%RTfile\n", FileDst), VERR_INVALID_PARAMETER);303 AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);304 305 /*306 * Save file offset.307 */308 RTFOFF offSrcSaved;309 int rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_CURRENT, (uint64_t *)&offSrcSaved);310 if (RT_FAILURE(rc))311 return rc;312 313 /*314 * Get the file size.315 */316 RTFOFF cbSrc;317 rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_END, (uint64_t *)&cbSrc);318 if (RT_FAILURE(rc))319 return rc;320 321 /*322 * Allocate buffer.323 */324 size_t cbBuf;325 uint8_t *pbBufFree = NULL;326 uint8_t *pbBuf;327 if (cbSrc < _512K)328 {329 cbBuf = 8*_1K;330 pbBuf = (uint8_t *)alloca(cbBuf);331 }332 else333 {334 cbBuf = _128K;335 pbBuf = pbBufFree = (uint8_t *)RTMemTmpAlloc(cbBuf);336 }337 if (pbBuf)338 {339 /*340 * Seek to the start of each file341 * and set the size of the destination file.342 */343 rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_BEGIN, NULL);344 if (RT_SUCCESS(rc))345 {346 rc = RTFileSeek(FileDst, 0, RTFILE_SEEK_BEGIN, NULL);347 if (RT_SUCCESS(rc))348 rc = RTFileSetSize(FileDst, cbSrc);349 if (RT_SUCCESS(rc) && pfnProgress)350 rc = pfnProgress(0, pvUser);351 if (RT_SUCCESS(rc))352 {353 /*354 * Copy loop.355 */356 unsigned uPercentage = 0;357 RTFOFF off = 0;358 RTFOFF cbPercent = cbSrc / 100;359 RTFOFF offNextPercent = cbPercent;360 while (off < cbSrc)361 {362 /* copy block */363 RTFOFF cbLeft = cbSrc - off;364 size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft;365 rc = RTFileRead(FileSrc, pbBuf, cbBlock, NULL);366 if (RT_FAILURE(rc))367 break;368 rc = RTFileWrite(FileDst, pbBuf, cbBlock, NULL);369 if (RT_FAILURE(rc))370 break;371 372 /* advance */373 off += cbBlock;374 if (pfnProgress && offNextPercent < off && uPercentage < 100)375 {376 do377 {378 uPercentage++;379 offNextPercent += cbPercent;380 } while (offNextPercent < off && uPercentage < 100);381 rc = pfnProgress(uPercentage, pvUser);382 if (RT_FAILURE(rc))383 break;384 }385 }386 387 #if 0388 /*389 * Copy OS specific data (EAs and stuff).390 */391 rtFileCopyOSStuff(FileSrc, FileDst);392 #endif393 394 /* 100% */395 if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc))396 rc = pfnProgress(100, pvUser);397 }398 }399 RTMemTmpFree(pbBufFree);400 }401 else402 rc = VERR_NO_MEMORY;403 404 /*405 * Restore source position.406 */407 RTFileSeek(FileSrc, offSrcSaved, RTFILE_SEEK_BEGIN, NULL);408 409 return rc;410 }411 412 413 RTDECL(int) RTFileCompare(const char *pszFile1, const char *pszFile2)414 {415 return RTFileCompareEx(pszFile1, pszFile2, 0 /*fFlags*/, NULL, NULL);416 }417 418 419 RTDECL(int) RTFileCompareByHandles(RTFILE hFile1, RTFILE hFile2)420 {421 return RTFileCompareByHandlesEx(hFile1, hFile2, 0 /*fFlags*/, NULL, NULL);422 }423 424 425 RTDECL(int) RTFileCompareEx(const char *pszFile1, const char *pszFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)426 {427 /*428 * Validate input.429 */430 AssertPtrReturn(pszFile1, VERR_INVALID_POINTER);431 AssertReturn(*pszFile1, VERR_INVALID_PARAMETER);432 AssertPtrReturn(pszFile2, VERR_INVALID_POINTER);433 AssertReturn(*pszFile2, VERR_INVALID_PARAMETER);434 AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);435 AssertMsgReturn(!(fFlags & ~RTFILECOMP_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);436 437 /*438 * Open the files.439 */440 RTFILE hFile1;441 int rc = RTFileOpen(&hFile1, pszFile1,442 RTFILE_O_READ | RTFILE_O_OPEN443 | (fFlags & RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE1 ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));444 if (RT_SUCCESS(rc))445 {446 RTFILE hFile2;447 rc = RTFileOpen(&hFile2, pszFile2,448 RTFILE_O_READ | RTFILE_O_OPEN449 | (fFlags & RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE2 ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));450 if (RT_SUCCESS(rc))451 {452 /*453 * Call the ByHandles version and let it do the job.454 */455 rc = RTFileCompareByHandlesEx(hFile1, hFile2, fFlags, pfnProgress, pvUser);456 457 /* Clean up */458 int rc2 = RTFileClose(hFile2);459 AssertRC(rc2);460 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))461 rc = rc2;462 }463 464 int rc2 = RTFileClose(hFile1);465 AssertRC(rc2);466 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))467 rc = rc2;468 }469 return rc;470 }471 472 473 RTDECL(int) RTFileCompareByHandlesEx(RTFILE hFile1, RTFILE hFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)474 {475 /*476 * Validate input.477 */478 AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE);479 AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE);480 AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);481 AssertMsgReturn(!(fFlags & ~RTFILECOMP_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);482 483 /*484 * Compare the file sizes first.485 */486 uint64_t cbFile1;487 int rc = RTFileGetSize(hFile1, &cbFile1);488 if (RT_FAILURE(rc))489 return rc;490 491 uint64_t cbFile2;492 rc = RTFileGetSize(hFile1, &cbFile2);493 if (RT_FAILURE(rc))494 return rc;495 496 if (cbFile1 != cbFile2)497 return VERR_NOT_EQUAL;498 499 500 /*501 * Allocate buffer.502 */503 size_t cbBuf;504 uint8_t *pbBuf1Free = NULL;505 uint8_t *pbBuf1;506 uint8_t *pbBuf2Free = NULL;507 uint8_t *pbBuf2;508 if (cbFile1 < _512K)509 {510 cbBuf = 8*_1K;511 pbBuf1 = (uint8_t *)alloca(cbBuf);512 pbBuf2 = (uint8_t *)alloca(cbBuf);513 }514 else515 {516 cbBuf = _128K;517 pbBuf1 = pbBuf1Free = (uint8_t *)RTMemTmpAlloc(cbBuf);518 pbBuf2 = pbBuf2Free = (uint8_t *)RTMemTmpAlloc(cbBuf);519 }520 if (pbBuf1 && pbBuf2)521 {522 /*523 * Seek to the start of each file524 * and set the size of the destination file.525 */526 rc = RTFileSeek(hFile1, 0, RTFILE_SEEK_BEGIN, NULL);527 if (RT_SUCCESS(rc))528 {529 rc = RTFileSeek(hFile2, 0, RTFILE_SEEK_BEGIN, NULL);530 if (RT_SUCCESS(rc) && pfnProgress)531 rc = pfnProgress(0, pvUser);532 if (RT_SUCCESS(rc))533 {534 /*535 * Compare loop.536 */537 unsigned uPercentage = 0;538 RTFOFF off = 0;539 RTFOFF cbPercent = cbFile1 / 100;540 RTFOFF offNextPercent = cbPercent;541 while (off < (RTFOFF)cbFile1)542 {543 /* read the blocks */544 RTFOFF cbLeft = cbFile1 - off;545 size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft;546 rc = RTFileRead(hFile1, pbBuf1, cbBlock, NULL);547 if (RT_FAILURE(rc))548 break;549 rc = RTFileRead(hFile2, pbBuf2, cbBlock, NULL);550 if (RT_FAILURE(rc))551 break;552 553 /* compare */554 if (memcmp(pbBuf1, pbBuf2, cbBlock))555 {556 rc = VERR_NOT_EQUAL;557 break;558 }559 560 /* advance */561 off += cbBlock;562 if (pfnProgress && offNextPercent < off)563 {564 while (offNextPercent < off)565 {566 uPercentage++;567 offNextPercent += cbPercent;568 }569 rc = pfnProgress(uPercentage, pvUser);570 if (RT_FAILURE(rc))571 break;572 }573 }574 575 #if 0576 /*577 * Compare OS specific data (EAs and stuff).578 */579 if (RT_SUCCESS(rc))580 rc = rtFileCompareOSStuff(hFile1, hFile2);581 #endif582 583 /* 100% */584 if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc))585 rc = pfnProgress(100, pvUser);586 }587 }588 }589 else590 rc = VERR_NO_MEMORY;591 RTMemTmpFree(pbBuf2Free);592 RTMemTmpFree(pbBuf1Free);593 594 return rc;595 }596 -
trunk/src/VBox/Runtime/r3/fileio.cpp
r77209 r77825 240 240 { 241 241 return RTFileCopyByHandlesEx(FileSrc, FileDst, NULL, NULL); 242 }243 244 245 RTDECL(int) RTFileCopyEx(const char *pszSrc, const char *pszDst, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser)246 {247 /*248 * Validate input.249 */250 AssertMsgReturn(VALID_PTR(pszSrc), ("pszSrc=%p\n", pszSrc), VERR_INVALID_PARAMETER);251 AssertMsgReturn(*pszSrc, ("pszSrc=%p\n", pszSrc), VERR_INVALID_PARAMETER);252 AssertMsgReturn(VALID_PTR(pszDst), ("pszDst=%p\n", pszDst), VERR_INVALID_PARAMETER);253 AssertMsgReturn(*pszDst, ("pszDst=%p\n", pszDst), VERR_INVALID_PARAMETER);254 AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);255 AssertMsgReturn(!(fFlags & ~RTFILECOPY_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);256 257 /*258 * Open the files.259 */260 RTFILE FileSrc;261 int rc = RTFileOpen(&FileSrc, pszSrc,262 RTFILE_O_READ | RTFILE_O_OPEN263 | (fFlags & RTFILECOPY_FLAGS_NO_SRC_DENY_WRITE ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));264 if (RT_SUCCESS(rc))265 {266 RTFILE FileDst;267 rc = RTFileOpen(&FileDst, pszDst,268 RTFILE_O_WRITE | RTFILE_O_CREATE269 | (fFlags & RTFILECOPY_FLAGS_NO_DST_DENY_WRITE ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE));270 if (RT_SUCCESS(rc))271 {272 /*273 * Call the ByHandles version and let it do the job.274 */275 rc = RTFileCopyByHandlesEx(FileSrc, FileDst, pfnProgress, pvUser);276 277 /*278 * Close the files regardless of the result.279 * Don't bother cleaning up or anything like that.280 */281 int rc2 = RTFileClose(FileDst);282 AssertRC(rc2);283 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))284 rc = rc2;285 }286 287 int rc2 = RTFileClose(FileSrc);288 AssertRC(rc2);289 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))290 rc = rc2;291 }292 return rc;293 }294 295 296 RTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser)297 {298 /*299 * Validate input.300 */301 AssertMsgReturn(RTFileIsValid(FileSrc), ("FileSrc=%RTfile\n", FileSrc), VERR_INVALID_PARAMETER);302 AssertMsgReturn(RTFileIsValid(FileDst), ("FileDst=%RTfile\n", FileDst), VERR_INVALID_PARAMETER);303 AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER);304 305 /*306 * Save file offset.307 */308 RTFOFF offSrcSaved;309 int rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_CURRENT, (uint64_t *)&offSrcSaved);310 if (RT_FAILURE(rc))311 return rc;312 313 /*314 * Get the file size.315 */316 RTFOFF cbSrc;317 rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_END, (uint64_t *)&cbSrc);318 if (RT_FAILURE(rc))319 return rc;320 321 /*322 * Allocate buffer.323 */324 size_t cbBuf;325 uint8_t *pbBufFree = NULL;326 uint8_t *pbBuf;327 if (cbSrc < _512K)328 {329 cbBuf = 8*_1K;330 pbBuf = (uint8_t *)alloca(cbBuf);331 }332 else333 {334 cbBuf = _128K;335 pbBuf = pbBufFree = (uint8_t *)RTMemTmpAlloc(cbBuf);336 }337 if (pbBuf)338 {339 /*340 * Seek to the start of each file341 * and set the size of the destination file.342 */343 rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_BEGIN, NULL);344 if (RT_SUCCESS(rc))345 {346 rc = RTFileSeek(FileDst, 0, RTFILE_SEEK_BEGIN, NULL);347 if (RT_SUCCESS(rc))348 rc = RTFileSetSize(FileDst, cbSrc);349 if (RT_SUCCESS(rc) && pfnProgress)350 rc = pfnProgress(0, pvUser);351 if (RT_SUCCESS(rc))352 {353 /*354 * Copy loop.355 */356 unsigned uPercentage = 0;357 RTFOFF off = 0;358 RTFOFF cbPercent = cbSrc / 100;359 RTFOFF offNextPercent = cbPercent;360 while (off < cbSrc)361 {362 /* copy block */363 RTFOFF cbLeft = cbSrc - off;364 size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft;365 rc = RTFileRead(FileSrc, pbBuf, cbBlock, NULL);366 if (RT_FAILURE(rc))367 break;368 rc = RTFileWrite(FileDst, pbBuf, cbBlock, NULL);369 if (RT_FAILURE(rc))370 break;371 372 /* advance */373 off += cbBlock;374 if (pfnProgress && offNextPercent < off && uPercentage < 100)375 {376 do377 {378 uPercentage++;379 offNextPercent += cbPercent;380 } while (offNextPercent < off && uPercentage < 100);381 rc = pfnProgress(uPercentage, pvUser);382 if (RT_FAILURE(rc))383 break;384 }385 }386 387 #if 0388 /*389 * Copy OS specific data (EAs and stuff).390 */391 rtFileCopyOSStuff(FileSrc, FileDst);392 #endif393 394 /* 100% */395 if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc))396 rc = pfnProgress(100, pvUser);397 }398 }399 RTMemTmpFree(pbBufFree);400 }401 else402 rc = VERR_NO_MEMORY;403 404 /*405 * Restore source position.406 */407 RTFileSeek(FileSrc, offSrcSaved, RTFILE_SEEK_BEGIN, NULL);408 409 return rc;410 242 } 411 243
Note:
See TracChangeset
for help on using the changeset viewer.