Changeset 50154 in vbox for trunk/src/VBox/Runtime/common/zip/tar.cpp
- Timestamp:
- Jan 21, 2014 7:51:00 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/zip/tar.cpp
r50153 r50154 142 142 /** The magic (RTTARFILE_MAGIC). */ 143 143 uint32_t u32Magic; 144 /** The open mode. */ 145 uint32_t fOpenMode; 144 146 /** Pointer to back to the tar file. */ 145 147 PRTTARINTERNAL pTar; … … 154 156 /** The current offset within this file. */ 155 157 uint64_t offCurrent; 156 /** The open mode. */ 157 uint32_t fOpenMode; 158 #ifndef RT_USE_TAR_VFS_FOR_ALL_READS 158 159 /** The link flag. */ 159 160 char linkflag; 161 #endif 160 162 #ifdef RT_USE_TAR_VFS_FOR_ALL_READS 161 163 /** The VFS I/O stream (only for reading atm). */ 162 164 RTVFSIOSTREAM hVfsIos; 163 /** The RTFSOBJATTR::fMode value for this VFS object. */164 RTFMODE fVfsMode;165 /** The RTFSOBJINFO::ModificationTime value for this VFS object. */166 RTTIMESPEC VfsModTime;167 165 #endif 168 166 } RTTARFILEINTERNAL; … … 465 463 466 464 pFileInt->u32Magic = RTTARFILE_MAGIC; 465 #ifndef RT_USE_TAR_VFS_FOR_ALL_READS 467 466 pFileInt->pTar = pInt; 467 #endif 468 468 pFileInt->fOpenMode = fOpen; 469 469 pFileInt->pszFilename = RTStrDup(pszFilename); … … 510 510 pNewFile->offCurrent = 0; 511 511 pNewFile->fOpenMode = fOpen; 512 pNewFile->linkflag = LF_NORMAL;513 512 pNewFile->hVfsIos = hVfsIos; 514 pNewFile->fVfsMode = ObjInfo.Attr.fMode;515 pNewFile->VfsModTime = ObjInfo.ModificationTime;516 513 517 514 uint32_t cRefs = RTVfsIoStrmRetain(hVfsIos); Assert(cRefs != UINT32_MAX); NOREF(cRefs); … … 568 565 } 569 566 } 570 571 #ifndef RT_USE_TAR_VFS_FOR_ALL_READS572 static int rtTarExtractFileToFile(RTTARFILE hFile, const char *pszTargetName, const uint64_t cbOverallSize, uint64_t &cbOverallWritten, PFNRTPROGRESS pfnProgressCallback, void *pvUser)573 {574 /* Open the target file */575 RTFILE hNewFile;576 int rc = RTFileOpen(&hNewFile, pszTargetName, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE);577 if (RT_FAILURE(rc))578 return rc;579 580 void *pvTmp = NULL;581 do582 {583 /* Allocate a temporary buffer for reading the tar content in blocks. */584 size_t cbTmp = 0;585 pvTmp = rtTarMemTmpAlloc(&cbTmp);586 if (!pvTmp)587 {588 rc = VERR_NO_MEMORY;589 break;590 }591 592 /* Get the size of the source file */593 uint64_t cbToCopy = 0;594 rc = RTTarFileGetSize(hFile, &cbToCopy);595 if (RT_FAILURE(rc))596 break;597 598 /* Copy the content from hFile over to pszTargetName. */599 uint64_t cbAllWritten = 0; /* Already copied */600 uint64_t cbRead = 0; /* Actually read in the last step */601 for (;;)602 {603 if (pfnProgressCallback)604 pfnProgressCallback((unsigned)(100.0 / cbOverallSize * cbOverallWritten), pvUser);605 606 /* Finished already? */607 if (cbAllWritten == cbToCopy)608 break;609 610 /* Read one block. */611 cbRead = RT_MIN(cbToCopy - cbAllWritten, cbTmp);612 rc = RTTarFileRead(hFile, pvTmp, cbRead, NULL);613 if (RT_FAILURE(rc))614 break;615 616 /* Write the block */617 rc = RTFileWrite(hNewFile, pvTmp, cbRead, NULL);618 if (RT_FAILURE(rc))619 break;620 621 /* Count how many bytes are written already */622 cbAllWritten += cbRead;623 cbOverallWritten += cbRead;624 }625 626 } while (0);627 628 /* Cleanup */629 if (pvTmp)630 RTMemTmpFree(pvTmp);631 632 /* Now set all file attributes */633 if (RT_SUCCESS(rc))634 {635 uint32_t mode;636 rc = RTTarFileGetMode(hFile, &mode);637 if (RT_SUCCESS(rc))638 {639 mode |= RTFS_TYPE_FILE; /* For now we support regular files only */640 /* Set the mode */641 rc = RTFileSetMode(hNewFile, mode);642 }643 }644 645 RTFileClose(hNewFile);646 647 /* Delete the freshly created file in the case of an error */648 if (RT_FAILURE(rc))649 RTFileDelete(pszTargetName);650 651 return rc;652 }653 #endif /* !RT_USE_TAR_VFS_FOR_ALL_READS */654 567 655 568 static int rtTarAppendFileFromFile(RTTAR hTar, const char *pszSrcName, const uint64_t cbOverallSize, uint64_t &cbOverallWritten, PFNRTPROGRESS pfnProgressCallback, void *pvUser) … … 1332 1245 } 1333 1246 1334 #ifndef RT_USE_TAR_VFS_FOR_ALL_READS /* only used internally */1335 RTR3DECL(int) RTTarFileGetMode(RTTARFILE hFile, uint32_t *pfMode)1336 {1337 /* Validate input */1338 AssertPtrReturn(pfMode, VERR_INVALID_POINTER);1339 1340 PRTTARFILEINTERNAL pFileInt = hFile;1341 RTTARFILE_VALID_RETURN(pFileInt);1342 1343 #ifdef RT_USE_TAR_VFS_FOR_ALL_READS1344 if ((pFileInt->fOpenMode & RTFILE_O_WRITE) != RTFILE_O_WRITE)1345 {1346 Assert(pFileInt->hVfsIos != NIL_RTVFSIOSTREAM);1347 *pfMode = pFileInt->fVfsMode;1348 return VINF_SUCCESS;1349 }1350 #endif1351 1352 /* Read the mode out of the header entry */1353 char szMode[RT_SIZEOFMEMB(RTTARRECORD, h.mode)+1];1354 int rc = RTFileReadAt(pFileInt->pTar->hTarFile,1355 pFileInt->offStart + RT_OFFSETOF(RTTARRECORD, h.mode),1356 szMode,1357 RT_SIZEOFMEMB(RTTARRECORD, h.mode),1358 NULL);1359 if (RT_FAILURE(rc))1360 return rc;1361 szMode[sizeof(szMode) - 1] = '\0';1362 1363 /* Convert it to an integer */1364 return RTStrToUInt32Full(szMode, 8, pfMode);1365 }1366 #endif1367 1368 1247 RTR3DECL(int) RTTarFileSetMode(RTTARFILE hFile, uint32_t fMode) 1369 1248 { … … 1386 1265 } 1387 1266 1388 #ifdef RT_UNUSED_API1389 RTR3DECL(int) RTTarFileGetTime(RTTARFILE hFile, PRTTIMESPEC pTime)1390 {1391 PRTTARFILEINTERNAL pFileInt = hFile;1392 RTTARFILE_VALID_RETURN(pFileInt);1393 1394 # ifdef RT_USE_TAR_VFS_FOR_ALL_READS1395 if ((pFileInt->fOpenMode & RTFILE_O_WRITE) != RTFILE_O_WRITE)1396 {1397 Assert(pFileInt->hVfsIos != NIL_RTVFSIOSTREAM);1398 *pTime = pFileInt->VfsModTime;1399 return VINF_SUCCESS;1400 }1401 # endif1402 1403 /* Read the time out of the header entry */1404 char szModTime[RT_SIZEOFMEMB(RTTARRECORD, h.mtime) + 1];1405 int rc = RTFileReadAt(pFileInt->pTar->hTarFile,1406 pFileInt->offStart + RT_OFFSETOF(RTTARRECORD, h.mtime),1407 szModTime,1408 RT_SIZEOFMEMB(RTTARRECORD, h.mtime),1409 NULL);1410 if (RT_FAILURE(rc))1411 return rc;1412 szModTime[sizeof(szModTime) - 1] = '\0';1413 1414 /* Convert it to an integer */1415 int64_t cSeconds;1416 rc = RTStrToInt64Full(szModTime, 12, &cSeconds);1417 1418 /* And back to our time structure */1419 if (RT_SUCCESS(rc))1420 RTTimeSpecSetSeconds(pTime, cSeconds);1421 1422 return rc;1423 }1424 #endif /* RT_UNUSED_API */1425 1426 1267 RTR3DECL(int) RTTarFileSetTime(RTTARFILE hFile, PRTTIMESPEC pTime) 1427 1268 { … … 1443 1284 NULL); 1444 1285 } 1445 1446 #if !defined(RT_USE_TAR_VFS_FOR_ALL_READS) && defined(RT_UNUSED_API)1447 RTR3DECL(int) RTTarFileGetOwner(RTTARFILE hFile, uint32_t *pUid, uint32_t *pGid)1448 {1449 PRTTARFILEINTERNAL pFileInt = hFile;1450 RTTARFILE_VALID_RETURN(pFileInt);1451 1452 /* Read the uid and gid out of the header entry */1453 AssertCompileAdjacentMembers(RTTARRECORD, h.uid, h.gid);1454 char szUidGid[RT_SIZEOFMEMB(RTTARRECORD, h.uid) + RT_SIZEOFMEMB(RTTARRECORD, h.gid) + 1];1455 int rc = RTFileReadAt(pFileInt->pTar->hTarFile,1456 pFileInt->offStart + RT_OFFSETOF(RTTARRECORD, h.uid),1457 szUidGid,1458 sizeof(szUidGid) - 1,1459 NULL);1460 if (RT_FAILURE(rc))1461 return rc;1462 szUidGid[sizeof(szUidGid) - 1] = '\0';1463 1464 /* Convert it to integer */1465 rc = RTStrToUInt32Full(&szUidGid[RT_SIZEOFMEMB(RTTARRECORD, h.uid)], 8, pGid);1466 if (RT_SUCCESS(rc))1467 {1468 szUidGid[RT_SIZEOFMEMB(RTTARRECORD, h.uid)] = '\0';1469 rc = RTStrToUInt32Full(szUidGid, 8, pUid);1470 }1471 return rc;1472 }1473 #endif1474 1286 1475 1287 RTR3DECL(int) RTTarFileSetOwner(RTTARFILE hFile, uint32_t uid, uint32_t gid) … … 1523 1335 * Convenience Functions * 1524 1336 ******************************************************************************/ 1525 1526 #ifndef RT_UNUSED_API1527 RTR3DECL(int) RTTarFileExists(const char *pszTarFile, const char *pszFile)1528 {1529 /* Validate input */1530 AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER);1531 AssertPtrReturn(pszFile, VERR_INVALID_POINTER);1532 1533 /* Open the tar file */1534 RTTAR hTar;1535 int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false /*fStream*/);1536 if (RT_FAILURE(rc))1537 return rc;1538 1539 /* Just try to open that file readonly. If this succeed the file exists. */1540 RTTARFILE hFile;1541 rc = RTTarFileOpen(hTar, &hFile, pszFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);1542 if (RT_SUCCESS(rc))1543 RTTarFileClose(hFile);1544 1545 RTTarClose(hTar);1546 1547 return rc;1548 }1549 #endif /* RT_UNUSED_API */1550 1337 1551 1338 RTR3DECL(int) RTTarList(const char *pszTarFile, char ***ppapszFiles, size_t *pcFiles) … … 1701 1488 } 1702 1489 1703 #if 0 /* broken, using wrong offset when reading. fix+test when _really_ need - use the TAR VFS wherever possible! */1704 RTR3DECL(int) RTTarExtractFileToBuf(const char *pszTarFile, void **ppvBuf, size_t *pcbSize, const char *pszFile,1705 PFNRTPROGRESS pfnProgressCallback, void *pvUser)1706 {1707 /*1708 * Validate input1709 */1710 AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER);1711 AssertPtrReturn(ppvBuf, VERR_INVALID_POINTER);1712 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);1713 AssertPtrReturn(pszFile, VERR_INVALID_POINTER);1714 AssertPtrNullReturn(pfnProgressCallback, VERR_INVALID_POINTER);1715 AssertPtrNullReturn(pvUser, VERR_INVALID_POINTER);1716 1717 /** @todo progress bar - is this TODO still valid? */1718 1719 int rc = VINF_SUCCESS;1720 RTTAR hTar = NIL_RTTAR;1721 RTTARFILE hFile = NIL_RTTARFILE;1722 char *pvTmp = NULL;1723 uint64_t cbToCopy= 0;1724 do /* break loop */1725 {1726 rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false /*fStream*/);1727 if (RT_FAILURE(rc))1728 break;1729 rc = RTTarFileOpen(hTar, &hFile, pszFile, RTFILE_O_OPEN | RTFILE_O_READ);1730 if (RT_FAILURE(rc))1731 break;1732 rc = RTTarFileGetSize(hFile, &cbToCopy);1733 if (RT_FAILURE(rc))1734 break;1735 1736 /* Allocate the memory for the file content. */1737 pvTmp = (char *)RTMemAlloc(cbToCopy);1738 if (!pvTmp)1739 {1740 rc = VERR_NO_MEMORY;1741 break;1742 }1743 size_t cbRead = 0;1744 size_t cbAllRead = 0;1745 for (;;)1746 {1747 if (pfnProgressCallback)1748 pfnProgressCallback((unsigned)(100.0 / cbToCopy * cbAllRead), pvUser);1749 if (cbAllRead == cbToCopy)1750 break;1751 rc = RTTarFileReadAt(hFile, 0, &pvTmp[cbAllRead], cbToCopy - cbAllRead, &cbRead);1752 if (RT_FAILURE(rc))1753 break;1754 cbAllRead += cbRead;1755 }1756 } while (0);1757 1758 /* Set output values on success */1759 if (RT_SUCCESS(rc))1760 {1761 *pcbSize = cbToCopy;1762 *ppvBuf = pvTmp;1763 }1764 1765 /* Cleanup */1766 if ( RT_FAILURE(rc)1767 && pvTmp)1768 RTMemFree(pvTmp);1769 if (hFile)1770 RTTarFileClose(hFile);1771 if (hTar)1772 RTTarClose(hTar);1773 1774 return rc;1775 }1776 #endif1777 1778 #ifndef RT_USE_TAR_VFS_FOR_ALL_READS /* Unused */1779 RTR3DECL(int) RTTarExtractFiles(const char *pszTarFile, const char *pszOutputDir, const char * const *papszFiles,1780 size_t cFiles, PFNRTPROGRESS pfnProgressCallback, void *pvUser)1781 {1782 /* Validate input */1783 AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER);1784 AssertPtrReturn(pszOutputDir, VERR_INVALID_POINTER);1785 AssertPtrReturn(papszFiles, VERR_INVALID_POINTER);1786 AssertReturn(cFiles, VERR_INVALID_PARAMETER);1787 AssertPtrNullReturn(pfnProgressCallback, VERR_INVALID_POINTER);1788 AssertPtrNullReturn(pvUser, VERR_INVALID_POINTER);1789 1790 /* Open the tar file */1791 RTTAR hTar;1792 int rc = RTTarOpen(&hTar, pszTarFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, false /*fStream*/);1793 if (RT_FAILURE(rc))1794 return rc;1795 1796 do /* break loop */1797 {1798 /* Get the overall size of all files to extract out of the tar archive1799 headers. Only necessary if there is a progress callback. */1800 uint64_t cbOverallSize = 0;1801 if (pfnProgressCallback)1802 {1803 // rc = rtTarGetFilesOverallSize(hFile, papszFiles, cFiles, &cbOverallSize);1804 // if (RT_FAILURE(rc))1805 // break;1806 }1807 1808 uint64_t cbOverallWritten = 0;1809 for (size_t i = 0; i < cFiles; ++i)1810 {1811 RTTARFILE hFile;1812 rc = RTTarFileOpen(hTar, &hFile, papszFiles[i], RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);1813 if (RT_FAILURE(rc))1814 break;1815 char *pszTargetFile = RTPathJoinA(pszOutputDir, papszFiles[i]);1816 if (pszTargetFile)1817 rc = rtTarExtractFileToFile(hFile, pszTargetFile, cbOverallSize, cbOverallWritten, pfnProgressCallback, pvUser);1818 else1819 rc = VERR_NO_STR_MEMORY;1820 RTStrFree(pszTargetFile);1821 RTTarFileClose(hFile);1822 if (RT_FAILURE(rc))1823 break;1824 }1825 } while (0);1826 1827 RTTarClose(hTar);1828 1829 return rc;1830 }1831 #endif /* !RT_USE_TAR_VFS_FOR_ALL_READS */1832 1833 #ifndef RT_USE_TAR_VFS_FOR_ALL_READS /* Unused */1834 RTR3DECL(int) RTTarExtractAll(const char *pszTarFile, const char *pszOutputDir, PFNRTPROGRESS pfnProgressCallback, void *pvUser)1835 {1836 /* Validate input */1837 AssertPtrReturn(pszTarFile, VERR_INVALID_POINTER);1838 AssertPtrReturn(pszOutputDir, VERR_INVALID_POINTER);1839 AssertPtrNullReturn(pfnProgressCallback, VERR_INVALID_POINTER);1840 AssertPtrNullReturn(pvUser, VERR_INVALID_POINTER);1841 1842 char **papszFiles;1843 size_t cFiles;1844 1845 /* First fetch the files names contained in the tar file */1846 int rc = RTTarList(pszTarFile, &papszFiles, &cFiles);1847 if (RT_FAILURE(rc))1848 return rc;1849 1850 /* Extract all files */1851 return RTTarExtractFiles(pszTarFile, pszOutputDir, papszFiles, cFiles, pfnProgressCallback, pvUser);1852 }1853 #endif /* !RT_USE_TAR_VFS_FOR_ALL_READS */1854 1855 1490 RTR3DECL(int) RTTarCreate(const char *pszTarFile, const char * const *papszFiles, size_t cFiles, PFNRTPROGRESS pfnProgressCallback, void *pvUser) 1856 1491 {
Note:
See TracChangeset
for help on using the changeset viewer.