- Timestamp:
- Oct 1, 2013 2:18:49 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 5 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/err.h
r46971 r48780 1789 1789 /** @} */ 1790 1790 1791 /** @name RTZipXar status codes. 1792 * @{ */ 1793 /** Wrong magic value. */ 1794 #define VERR_XAR_WRONG_MAGIC (-22700) 1795 /** Bad header size. */ 1796 #define VERR_XAR_BAD_HDR_SIZE (-22701) 1797 /** Unsupported version. */ 1798 #define VERR_XAR_UNSUPPORTED_VERSION (-22702) 1799 /** Unsupported hashing function. */ 1800 #define VERR_XAR_UNSUPPORTED_HASH_FUNCTION (-22703) 1801 /** The table of content (TOC) is too small and therefore can't be valid. */ 1802 #define VERR_XAR_TOC_TOO_SMALL (-22704) 1803 /** The table of content (TOC) is too big. */ 1804 #define VERR_XAR_TOC_TOO_BIG (-22705) 1805 /** The compressed table of content is too big. */ 1806 #define VERR_XAR_TOC_TOO_BIG_COMPRESSED (-22706) 1807 /** The uncompressed table of content size in the header didn't match what 1808 * ZLib returned. */ 1809 #define VERR_XAR_TOC_UNCOMP_SIZE_MISMATCH (-22707) 1810 /** The table of content string length didn't match the size specified in the 1811 * header. */ 1812 #define VERR_XAR_TOC_STRLEN_MISMATCH (-22708) 1813 /** The table of content isn't valid UTF-8. */ 1814 #define VERR_XAR_TOC_UTF8_ENCODING (-22709) 1815 /** XML error while parsing the table of content. */ 1816 #define VERR_XAR_TOC_XML_PARSE_ERROR (-22710) 1817 /** The table of content XML document does not have a toc element. */ 1818 #define VERR_XML_TOC_ELEMENT_MISSING (-22711) 1819 /** The table of content XML element (toc) has sibilings, we expected it to be 1820 * an only child or the root element (xar). */ 1821 #define VERR_XML_TOC_ELEMENT_HAS_SIBLINGS (-22712) 1822 /** The XAR table of content digest doesn't match. */ 1823 #define VERR_XAR_TOC_DIGEST_MISMATCH (-22713) 1824 /** Bad or missing XAR checksum element. */ 1825 #define VERR_XAR_BAD_CHECKSUM_ELEMENT (-22714) 1826 /** The hash function in the header doesn't match the one in the table of 1827 * content. */ 1828 #define VERR_XAR_HASH_FUNCTION_MISMATCH (-22715) 1829 /** Bad digest length encountered in the table of content. */ 1830 #define VERR_XAR_BAD_DIGEST_LENGTH (-22716) 1831 /** The order of elements in the XAR file does not lend it self to expansion 1832 * from via an I/O stream. */ 1833 #define VERR_XAR_NOT_STREAMBLE_ELEMENT_ORDER (-22717) 1834 /** Missing offset element in table of content sub-element. */ 1835 #define VERR_XAR_MISSING_OFFSET_ELEMENT (-22718) 1836 /** Bad offset element in table of content sub-element. */ 1837 #define VERR_XAR_BAD_OFFSET_ELEMENT (-22719) 1838 /** Missing size element in table of content sub-element. */ 1839 #define VERR_XAR_MISSING_SIZE_ELEMENT (-22720) 1840 /** Bad size element in table of content sub-element. */ 1841 #define VERR_XAR_BAD_SIZE_ELEMENT (-22721) 1842 /** @} */ 1843 1791 1844 1792 1845 /* SED-END */ -
trunk/include/iprt/zip.h
r47516 r48780 271 271 RTDECL(RTEXITCODE) RTZipTarCmd(unsigned cArgs, char **papszArgs); 272 272 273 /** 274 * Opens a XAR filesystem stream. 275 * 276 * This is used to extract, list or check a XAR archive. 277 * 278 * @returns IPRT status code. 279 * 280 * @param hVfsIosIn The compressed input stream. The reference is 281 * not consumed, instead another one is retained. 282 * @param fFlags Flags, MBZ. 283 * @param phVfsFss Where to return the handle to the XAR filesystem 284 * stream. 285 */ 286 RTDECL(int) RTZipXarFsStreamFromIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss); 287 273 288 /** @} */ 274 289 -
trunk/src/VBox/Runtime/Makefile.kmk
r48768 r48780 1290 1290 VBoxRT_INST = $(INST_DLL) $(INST_TESTCASE) 1291 1291 endif 1292 VBoxRT_DEFS := $(filter-out RT_NO_GIP,$(RuntimeR3_DEFS)) IN_SUP_R3 IN_SUP_R3 1292 VBoxRT_DEFS := $(filter-out RT_NO_GIP,$(RuntimeR3_DEFS)) IN_SUP_R3 IN_SUP_R3 IPRT_WITH_XAR 1293 1293 ifn1of ($(KBUILD_TARGET_ARCH), amd64 x86) 1294 1294 VBoxRT_DEFS += RT_NO_GIP … … 1303 1303 $(filter-out common/checksum/crc32.cpp, $(RuntimeR3_SOURCES)) \ 1304 1304 common/checksum/crc32-zlib.cpp \ 1305 common/misc/aiomgr.cpp 1305 common/misc/aiomgr.cpp \ 1306 common/zip/xarvfs.cpp 1306 1307 ifdef VBOX_WITH_LIBCURL 1307 1308 VBoxRT_SOURCES += common/misc/s3.cpp -
trunk/src/VBox/Runtime/common/zip/tarcmd.cpp
r47359 r48780 60 60 #define RTZIPTARCMD_OPT_DIR_MODE_AND_MASK 1007 61 61 #define RTZIPTARCMD_OPT_DIR_MODE_OR_MASK 1008 62 #define RTZIPTARCMD_OPT_FORMAT 1009 63 64 /** File format. */ 65 typedef enum RTZIPTARFORMAT 66 { 67 RTZIPTARFORMAT_INVALID = 0, 68 /** Autodetect if possible, defaulting to TAR. */ 69 RTZIPTARFORMAT_AUTO_DEFAULT, 70 /** TAR. */ 71 RTZIPTARFORMAT_TAR, 72 /** XAR. */ 73 RTZIPTARFORMAT_XAR 74 } RTZIPTARFORMAT; 62 75 63 76 … … 70 83 typedef struct RTZIPTARCMDOPS 71 84 { 85 /** The file format. */ 86 RTZIPTARFORMAT enmFormat; 87 72 88 /** The operation (Acdrtux or RTZIPTARCMD_OPT_DELETE). */ 73 89 int iOperation; … … 247 263 248 264 /* 249 * Open the tar filesystem stream. 250 */ 251 rc = RTZipTarFsStreamFromIoStream(hVfsIos, 0/*fFlags*/, phVfsFss); 265 * Open the filesystem stream. 266 */ 267 if (pOpts->enmFormat == RTZIPTARFORMAT_TAR) 268 rc = RTZipTarFsStreamFromIoStream(hVfsIos, 0/*fFlags*/, phVfsFss); 269 else if (pOpts->enmFormat == RTZIPTARFORMAT_XAR) 270 #ifdef IPRT_WITH_XAR /* Requires C++ and XML, so only in some configruation of IPRT. */ 271 rc = RTZipXarFsStreamFromIoStream(hVfsIos, 0/*fFlags*/, phVfsFss); 272 #else 273 rc = VERR_NOT_SUPPORTED; 274 #endif 275 else /** @todo make RTZipTarFsStreamFromIoStream fail if not tar file! */ 276 rc = RTZipTarFsStreamFromIoStream(hVfsIos, 0/*fFlags*/, phVfsFss); 252 277 RTVfsIoStrmRelease(hVfsIos); 253 278 if (RT_FAILURE(rc)) … … 950 975 { "--owner", RTZIPTARCMD_OPT_OWNER, RTGETOPT_REQ_STRING }, 951 976 { "--group", RTZIPTARCMD_OPT_GROUP, RTGETOPT_REQ_STRING }, 952 { "--utc", RTZIPTARCMD_OPT_UTC, RTGETOPT_REQ_NOTHING },977 { "--utc", RTZIPTARCMD_OPT_UTC, RTGETOPT_REQ_NOTHING }, 953 978 954 979 /* IPRT extensions */ … … 958 983 { "--dir-mode-and-mask", RTZIPTARCMD_OPT_DIR_MODE_AND_MASK, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_OCT }, 959 984 { "--dir-mode-or-mask", RTZIPTARCMD_OPT_DIR_MODE_OR_MASK, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_OCT }, 985 { "--format", RTZIPTARCMD_OPT_FORMAT, RTGETOPT_REQ_STRING }, 960 986 }; 961 987 … … 968 994 RTZIPTARCMDOPS Opts; 969 995 RT_ZERO(Opts); 996 Opts.enmFormat = RTZIPTARFORMAT_AUTO_DEFAULT; 970 997 Opts.uidOwner = NIL_RTUID; 971 998 Opts.gidGroup = NIL_RTUID; … … 1094 1121 break; 1095 1122 1123 case RTZIPTARCMD_OPT_FORMAT: 1124 if (!strcmp(ValueUnion.psz, "auto") || !strcmp(ValueUnion.psz, "default")) 1125 Opts.enmFormat = RTZIPTARFORMAT_AUTO_DEFAULT; 1126 else if (!strcmp(ValueUnion.psz, "tar")) 1127 Opts.enmFormat = RTZIPTARFORMAT_TAR; 1128 else if (!strcmp(ValueUnion.psz, "xar")) 1129 Opts.enmFormat = RTZIPTARFORMAT_XAR; 1130 else 1131 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Unknown archive format: '%s'", ValueUnion.psz); 1132 break; 1096 1133 1097 1134 /* Standard bits. */ -
trunk/src/VBox/Runtime/common/zip/xarvfs.cpp
r48757 r48780 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - TAR Virtual Filesystem.3 * IPRT - XAR Virtual Filesystem. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2010-201 1Oracle Corporation7 * Copyright (C) 2010-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 36 36 #include <iprt/ctype.h> 37 37 #include <iprt/err.h> 38 #include <iprt/md5.h> 38 39 #include <iprt/poll.h> 39 40 #include <iprt/file.h> 41 #include <iprt/sha.h> 40 42 #include <iprt/string.h> 41 43 #include <iprt/vfs.h> 42 44 #include <iprt/vfslowlevel.h> 43 44 #include "tar.h" 45 #include <iprt/formats/xar.h> 46 #include <iprt/cpp/xml.h> 47 45 48 46 49 … … 49 52 *******************************************************************************/ 50 53 /** 51 * TAR reader state machine states. 52 */ 53 typedef enum RTZIPTARREADERSTATE 54 { 55 /** Invalid state. */ 56 RTZIPTARREADERSTATE_INVALID = 0, 57 /** Expecting the next file/dir/whatever entry. */ 58 RTZIPTARREADERSTATE_FIRST, 59 /** Expecting more zero headers or the end of the stream. */ 60 RTZIPTARREADERSTATE_ZERO, 61 /** Expecting a GNU long name. */ 62 RTZIPTARREADERSTATE_GNU_LONGNAME, 63 /** Expecting a GNU long link. */ 64 RTZIPTARREADERSTATE_GNU_LONGLINK, 65 /** Expecting a normal header or another GNU specific one. */ 66 RTZIPTARREADERSTATE_GNU_NEXT, 67 /** End of valid states (not included). */ 68 RTZIPTARREADERSTATE_END 69 } RTZIPTARREADERSTATE; 70 71 /** 72 * Tar reader instance data. 73 */ 74 typedef struct RTZIPTARREADER 75 { 76 /** Zero header counter. */ 77 uint32_t cZeroHdrs; 78 /** The state machine state. */ 79 RTZIPTARREADERSTATE enmState; 80 /** The type of the previous TAR header. */ 81 RTZIPTARTYPE enmPrevType; 82 /** The type of the current TAR header. */ 83 RTZIPTARTYPE enmType; 84 /** The current header. */ 85 RTZIPTARHDR Hdr; 86 /** The expected long name/link length (GNU). */ 87 uint32_t cbGnuLongExpect; 88 /** The current long name/link length (GNU). */ 89 uint32_t offGnuLongCur; 90 /** The name of the current object. 91 * This is for handling GNU and PAX long names. */ 92 char szName[RTPATH_MAX]; 93 /** The current link target if symlink or hardlink. */ 94 char szTarget[RTPATH_MAX]; 95 } RTZIPTARREADER; 96 /** Pointer to the TAR reader instance data. */ 97 typedef RTZIPTARREADER *PRTZIPTARREADER; 98 99 /** 100 * Tar directory, character device, block device, fifo socket or symbolic link. 101 */ 102 typedef struct RTZIPTARBASEOBJ 54 * Hash digest value union for the supported XAR hash functions. 55 */ 56 typedef union RTZIPXARHASHDIGEST 57 { 58 uint8_t abMd5[RTMD5_HASH_SIZE]; 59 uint8_t abSha1[RTSHA1_HASH_SIZE]; 60 } RTZIPXARHASHDIGEST; 61 /** Pointer to a XAR hash digest union. */ 62 typedef RTZIPXARHASHDIGEST *PRTZIPXARHASHDIGEST; 63 /** Pointer to a const XAR hash digest union. */ 64 typedef RTZIPXARHASHDIGEST *PCRTZIPXARHASHDIGEST; 65 66 /** 67 * XAR reader instance data. 68 */ 69 typedef struct RTZIPXARREADER 70 { 71 /** The TOC XML element. */ 72 xml::ElementNode const *pToc; 73 /** The TOC XML document. */ 74 xml::Document *pDoc; 75 /** The current file ID. */ 76 uint32_t idCurFile; 77 } RTZIPXARREADER; 78 /** Pointer to the XAR reader instance data. */ 79 typedef RTZIPXARREADER *PRTZIPXARREADER; 80 81 /** 82 * Xar directory, character device, block device, fifo socket or symbolic link. 83 */ 84 typedef struct RTZIPXARBASEOBJ 103 85 { 104 86 /** The stream offset of the (first) header. */ … … 107 89 * stream). 108 90 * @todo Fix this so it won't go stale... Back ref from this obj to fss? */ 109 PRTZIP TARREADER pTarReader;91 PRTZIPXARREADER pXarReader; 110 92 /** The object info with unix attributes. */ 111 93 RTFSOBJINFO ObjInfo; 112 } RTZIP TARBASEOBJ;113 /** Pointer to a TAR filesystem stream base object. */114 typedef RTZIP TARBASEOBJ *PRTZIPTARBASEOBJ;115 116 117 /** 118 * Tar file represented as a VFS I/O stream.119 */ 120 typedef struct RTZIP TARIOSTREAM121 { 122 /** The basic TAR object data. */123 RTZIP TARBASEOBJ BaseObj;94 } RTZIPXARBASEOBJ; 95 /** Pointer to a XAR filesystem stream base object. */ 96 typedef RTZIPXARBASEOBJ *PRTZIPXARBASEOBJ; 97 98 99 /** 100 * Xar file represented as a VFS I/O stream. 101 */ 102 typedef struct RTZIPXARIOSTREAM 103 { 104 /** The basic XAR object data. */ 105 RTZIPXARBASEOBJ BaseObj; 124 106 /** The number of bytes in the file. */ 125 107 RTFOFF cbFile; … … 132 114 /** The input I/O stream. */ 133 115 RTVFSIOSTREAM hVfsIos; 134 } RTZIP TARIOSTREAM;135 /** Pointer to a the private data of a TAR file I/O stream. */136 typedef RTZIP TARIOSTREAM *PRTZIPTARIOSTREAM;137 138 139 /** 140 * Tar filesystem stream private data.141 */ 142 typedef struct RTZIP TARFSSTREAM116 } RTZIPXARIOSTREAM; 117 /** Pointer to a the private data of a XAR file I/O stream. */ 118 typedef RTZIPXARIOSTREAM *PRTZIPXARIOSTREAM; 119 120 121 /** 122 * Xar filesystem stream private data. 123 */ 124 typedef struct RTZIPXARFSSTREAM 143 125 { 144 126 /** The input I/O stream. */ 145 127 RTVFSIOSTREAM hVfsIos; 128 /** The input file, if the stream is actually a file. */ 129 RTVFSFILE hVfsFile; 146 130 147 131 /** The current object (referenced). */ 148 132 RTVFSOBJ hVfsCurObj; 149 133 /** Pointer to the private data if hVfsCurObj is representing a file. */ 150 PRTZIP TARIOSTREAM pCurIosData;151 152 /** The start offset . */134 PRTZIPXARIOSTREAM pCurIosData; 135 136 /** The start offset in the input I/O stream. */ 153 137 RTFOFF offStart; 154 /** The offset of the next header. */ 155 RTFOFF offNextHdr; 138 /** The zero offset in the file which all others are relative to. */ 139 RTFOFF offZero; 140 141 /** The hash function we're using (XAR_HASH_XXX). */ 142 uint8_t uHashFunction; 143 /** The size of the digest produced by the hash function we're using. */ 144 uint8_t cbHashDigest; 156 145 157 146 /** Set if we've reached the end of the stream. */ … … 160 149 int rcFatal; 161 150 162 /** The TAR reader instance data. */ 163 RTZIPTARREADER TarReader;164 } RTZIPTARFSSTREAM;165 /** Pointer to a the private data of a TAR filesystem stream. */ 166 typedef RTZIPTARFSSTREAM *PRTZIPTARFSSTREAM; 167 168 169 170 /** 171 * Converts a numeric header field to the C native type.151 152 /** The XAR reader instance data. */ 153 RTZIPXARREADER XarReader; 154 } RTZIPXARFSSTREAM; 155 /** Pointer to a the private data of a XAR filesystem stream. */ 156 typedef RTZIPXARFSSTREAM *PRTZIPXARFSSTREAM; 157 158 159 /** 160 * Hashes a block of data. 172 161 * 173 * @returns IPRT status code. 174 * 175 * @param pszField The TAR header field. 176 * @param cchField The length of the field. 177 * @param fOctalOnly Must be octal. 178 * @param pi64 Where to store the value. 179 */ 180 static int rtZipTarHdrFieldToNum(const char *pszField, size_t cchField, bool fOctalOnly, int64_t *pi64) 181 { 182 unsigned char const *puchField = (unsigned char const *)pszField; 183 size_t const cchFieldOrg = cchField; 184 if ( fOctalOnly 185 || !(*puchField & 0x80)) 186 { 187 /* 188 * Skip leading spaces. Include zeros to save a few slower loops below. 189 */ 190 unsigned char ch; 191 while (cchField > 0 && ((ch = *puchField) == ' '|| ch == '0')) 192 cchField--, puchField++; 193 194 /* 195 * Convert octal digits. 196 */ 197 int64_t i64 = 0; 198 while (cchField > 0) 199 { 200 unsigned char uDigit = *puchField - '0'; 201 if (uDigit >= 8) 202 break; 203 i64 <<= 3; 204 i64 |= uDigit; 205 206 puchField++; 207 cchField--; 208 } 209 *pi64 = i64; 210 211 /* 212 * Was it terminated correctly? 213 */ 214 while (cchField > 0) 215 { 216 ch = *puchField++; 217 if (ch != 0 && ch != ' ') 218 return cchField < cchFieldOrg 219 ? VERR_TAR_BAD_NUM_FIELD_TERM 220 : VERR_TAR_BAD_NUM_FIELD; 221 cchField--; 222 } 223 } 224 else 225 { 226 /* 227 * The first byte has the bit 7 set to indicate base-256, while bit 6 228 * is the signed bit. Bits 5:0 are the most significant value bits. 229 */ 230 int64_t i64 = !(0x40 & *puchField) ? 0 : -1; 231 i64 = (i64 << 6) | (*puchField & 0x3f); 232 cchField--; 233 puchField++; 234 235 /* 236 * The remaining bytes are used in full. 237 */ 238 while (cchField-- > 0) 239 { 240 if (RT_UNLIKELY(i64 > INT64_MAX / 256)) 241 return VERR_TAR_NUM_VALUE_TOO_LARGE; 242 if (RT_UNLIKELY(i64 < INT64_MIN / 256)) 243 return VERR_TAR_NUM_VALUE_TOO_LARGE; 244 i64 = (i64 << 8) | *puchField++; 245 } 246 *pi64 = i64; 247 } 162 * @param uHashFunction The hash function to use. 163 * @param pvSrc The data to hash. 164 * @param cbSrc The size of the data to hash. 165 * @param pHashDigest Where to return the hash digest. 166 */ 167 static void rtZipXarCalcHash(uint32_t uHashFunction, void const *pvSrc, size_t cbSrc, PRTZIPXARHASHDIGEST pHashDigest) 168 { 169 switch (uHashFunction) 170 { 171 case XAR_HASH_SHA1: 172 RTSha1(pvSrc, cbSrc, pHashDigest->abSha1); 173 break; 174 case XAR_HASH_MD5: 175 RTMd5(pvSrc, cbSrc, pHashDigest->abMd5); 176 break; 177 default: 178 RT_ZERO(*pHashDigest); 179 break; 180 } 181 } 182 183 184 static int rtZipXarGetOffsetSizeFromElem(xml::ElementNode const *pElement, PRTFOFF poff, uint64_t *pcb) 185 { 186 /* 187 * The offset. 188 */ 189 xml::ElementNode const *pElem = pElement->findChildElement("offset"); 190 if (!pElem) 191 return VERR_XAR_MISSING_OFFSET_ELEMENT; 192 const char *pszValue = pElem->getValue(); 193 if (!pszValue) 194 return VERR_XAR_BAD_OFFSET_ELEMENT; 195 196 int rc = RTStrToInt64Full(pszValue, 0, poff); 197 if ( RT_FAILURE(rc) 198 || rc == VWRN_NUMBER_TOO_BIG 199 || *poff > RTFOFF_MAX / 2 /* make sure to not overflow calculating offsets. */ 200 || *poff < 0) 201 return VERR_XAR_BAD_OFFSET_ELEMENT; 202 203 /* 204 * The size. 205 */ 206 pElem = pElement->findChildElement("size"); 207 if (!pElem) 208 return VERR_XAR_MISSING_SIZE_ELEMENT; 209 210 pszValue = pElem->getValue(); 211 if (!pszValue) 212 return VERR_XAR_BAD_SIZE_ELEMENT; 213 214 rc = RTStrToUInt64Full(pszValue, 0, pcb); 215 if ( RT_FAILURE(rc) 216 || rc == VWRN_NUMBER_TOO_BIG 217 || *pcb > UINT64_MAX / 2 /* prevent overflow should be use it for calcuations later. */) 218 return VERR_XAR_BAD_SIZE_ELEMENT; 248 219 249 220 return VINF_SUCCESS; … … 252 223 253 224 /** 254 * Calculates the TAR header checksums and detects if it's all zeros. 255 * 256 * @returns true if all zeros, false if not. 257 * @param pHdr The header to checksum. 258 * @param pi32Unsigned Where to store the checksum calculated using 259 * unsigned chars. This is the one POSIX 260 * specifies. 261 * @param pi32Signed Where to store the checksum calculated using 262 * signed chars. 263 * 264 * @remarks The reason why we calculate the checksum as both signed and unsigned 265 * has to do with various the char C type being signed on some hosts 266 * and unsigned on others. 267 */ 268 static bool rtZipTarCalcChkSum(PCRTZIPTARHDR pHdr, int32_t *pi32Unsigned, int32_t *pi32Signed) 269 { 270 int32_t i32Unsigned = 0; 271 int32_t i32Signed = 0; 272 273 /* 274 * Sum up the entire header. 275 */ 276 const char *pch = (const char *)pHdr; 277 const char *pchEnd = pch + sizeof(*pHdr); 278 do 279 { 280 i32Unsigned += *(unsigned char *)pch; 281 i32Signed += *(signed char *)pch; 282 } while (++pch != pchEnd); 283 284 /* 285 * Check if it's all zeros and replace the chksum field with spaces. 286 */ 287 bool const fZeroHdr = i32Unsigned == 0; 288 289 pch = pHdr->Common.chksum; 290 pchEnd = pch + sizeof(pHdr->Common.chksum); 291 do 292 { 293 i32Unsigned -= *(unsigned char *)pch; 294 i32Signed -= *(signed char *)pch; 295 } while (++pch != pchEnd); 296 297 i32Unsigned += (unsigned char)' ' * sizeof(pHdr->Common.chksum); 298 i32Signed += (signed char)' ' * sizeof(pHdr->Common.chksum); 299 300 *pi32Unsigned = i32Unsigned; 301 if (pi32Signed) 302 *pi32Signed = i32Signed; 303 return fZeroHdr; 304 } 305 306 307 /** 308 * Validates the TAR header. 309 * 310 * @returns VINF_SUCCESS if valid, VERR_TAR_ZERO_HEADER if all zeros, and 311 * the appropriate VERR_TAR_XXX otherwise. 312 * @param pTar The TAR header. 313 * @param penmType Where to return the type of header on success. 314 */ 315 static int rtZipTarHdrValidate(PCRTZIPTARHDR pTar, PRTZIPTARTYPE penmType) 316 { 317 /* 318 * Calc the checksum first since this enables us to detect zero headers. 319 */ 320 int32_t i32ChkSum; 321 int32_t i32ChkSumSignedAlt; 322 if (rtZipTarCalcChkSum(pTar, &i32ChkSum, &i32ChkSumSignedAlt)) 323 return VERR_TAR_ZERO_HEADER; 324 325 /* 326 * Read the checksum field and match the checksums. 327 */ 328 int64_t i64HdrChkSum; 329 int rc = rtZipTarHdrFieldToNum(pTar->Common.chksum, sizeof(pTar->Common.chksum), true /*fOctalOnly*/, &i64HdrChkSum); 330 if (RT_FAILURE(rc)) 331 return VERR_TAR_BAD_CHKSUM_FIELD; 332 if ( i32ChkSum != i64HdrChkSum 333 && i32ChkSumSignedAlt != i64HdrChkSum) /** @todo test this */ 334 return VERR_TAR_CHKSUM_MISMATCH; 335 336 /* 337 * Detect the TAR type. 338 */ 339 RTZIPTARTYPE enmType; 340 if ( pTar->Common.magic[0] == 'u' 341 && pTar->Common.magic[1] == 's' 342 && pTar->Common.magic[2] == 't' 343 && pTar->Common.magic[3] == 'a' 344 && pTar->Common.magic[4] == 'r') 345 { 346 /** @todo detect star headers */ 347 if ( pTar->Common.magic[5] == '\0' 348 && pTar->Common.version[0] == '0' 349 && pTar->Common.version[1] == '0') 350 enmType = RTZIPTARTYPE_POSIX; 351 else if ( pTar->Common.magic[5] == ' ' 352 && pTar->Common.version[0] == ' ' 353 && pTar->Common.version[1] == '\0') 354 enmType = RTZIPTARTYPE_GNU; 355 else 356 return VERR_TAR_NOT_USTAR_V00; 357 } 358 else 359 enmType = RTZIPTARTYPE_ANCIENT; 360 *penmType = enmType; 361 362 /* 363 * Perform some basic checks. 364 */ 365 switch (enmType) 366 { 367 case RTZIPTARTYPE_POSIX: 368 if ( !RT_C_IS_ALNUM(pTar->Common.typeflag) 369 && !pTar->Common.typeflag == '\0') 370 return VERR_TAR_UNKNOWN_TYPE_FLAG; 371 break; 372 373 case RTZIPTARTYPE_GNU: 374 switch (pTar->Common.typeflag) 375 { 376 case RTZIPTAR_TF_OLDNORMAL: 377 case RTZIPTAR_TF_NORMAL: 378 case RTZIPTAR_TF_CONTIG: 379 case RTZIPTAR_TF_DIR: 380 case RTZIPTAR_TF_CHR: 381 case RTZIPTAR_TF_BLK: 382 case RTZIPTAR_TF_LINK: 383 case RTZIPTAR_TF_SYMLINK: 384 case RTZIPTAR_TF_FIFO: 385 break; 386 387 case RTZIPTAR_TF_GNU_LONGLINK: 388 case RTZIPTAR_TF_GNU_LONGNAME: 389 break; 390 391 case RTZIPTAR_TF_GNU_DUMPDIR: 392 case RTZIPTAR_TF_GNU_MULTIVOL: 393 case RTZIPTAR_TF_GNU_SPARSE: 394 case RTZIPTAR_TF_GNU_VOLDHR: 395 /** @todo Implement full GNU TAR support. .*/ 396 return VERR_TAR_UNSUPPORTED_GNU_HDR_TYPE; 397 398 default: 399 return VERR_TAR_UNKNOWN_TYPE_FLAG; 400 } 401 break; 402 403 case RTZIPTARTYPE_ANCIENT: 404 switch (pTar->Common.typeflag) 405 { 406 case RTZIPTAR_TF_OLDNORMAL: 407 case RTZIPTAR_TF_NORMAL: 408 case RTZIPTAR_TF_CONTIG: 409 case RTZIPTAR_TF_DIR: 410 case RTZIPTAR_TF_LINK: 411 case RTZIPTAR_TF_SYMLINK: 412 case RTZIPTAR_TF_FIFO: 413 break; 414 default: 415 return VERR_TAR_UNKNOWN_TYPE_FLAG; 416 } 417 break; 418 default: /* shut up gcc */ 419 AssertFailedReturn(VERR_INTERNAL_ERROR_3); 420 } 421 422 return VINF_SUCCESS; 423 } 424 425 426 /** 427 * Parses and validates the first TAR header of a archive/file/dir/whatever. 428 * 429 * @returns IPRT status code. 430 * @param pThis The TAR reader stat. 431 * @param pTar The TAR header that has been read. 432 * @param fFirst Set if this is the first header, otherwise 433 * clear. 434 */ 435 static int rtZipTarReaderParseNextHeader(PRTZIPTARREADER pThis, PCRTZIPTARHDR pHdr, bool fFirst) 436 { 437 int rc; 438 439 /* 440 * Basic header validation and detection first. 441 */ 442 RTZIPTARTYPE enmType; 443 rc = rtZipTarHdrValidate(pHdr, &enmType); 444 if (RT_FAILURE_NP(rc)) 445 { 446 if (rc == VERR_TAR_ZERO_HEADER) 447 { 448 pThis->cZeroHdrs = 1; 449 pThis->enmState = RTZIPTARREADERSTATE_ZERO; 450 return VINF_SUCCESS; 451 } 452 return rc; 453 } 454 if (fFirst) 455 pThis->enmType = enmType; 456 457 /* 458 * Handle the header by type. 459 */ 460 switch (pHdr->Common.typeflag) 461 { 462 case RTZIPTAR_TF_OLDNORMAL: 463 case RTZIPTAR_TF_NORMAL: 464 case RTZIPTAR_TF_CONTIG: 465 case RTZIPTAR_TF_LINK: 466 case RTZIPTAR_TF_SYMLINK: 467 case RTZIPTAR_TF_CHR: 468 case RTZIPTAR_TF_BLK: 469 case RTZIPTAR_TF_FIFO: 470 case RTZIPTAR_TF_DIR: 471 /* 472 * Extract the name first. 473 */ 474 if (!pHdr->Common.name[0]) 475 return VERR_TAR_EMPTY_NAME; 476 if (pThis->enmType == RTZIPTARTYPE_POSIX) 477 { 478 Assert(pThis->offGnuLongCur == 0); Assert(pThis->szName[0] == '\0'); 479 pThis->szName[0] = '\0'; 480 if (pHdr->Posix.prefix[0]) 481 { 482 rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Posix.prefix, sizeof(pHdr->Posix.prefix)); 483 AssertRC(rc); /* shall not fail */ 484 rc = RTStrCat(pThis->szName, sizeof(pThis->szName), "/"); 485 AssertRC(rc); /* ditto */ 486 } 487 rc = RTStrCatEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name)); 488 AssertRCReturn(rc, rc); 489 } 490 else if (pThis->enmType == RTZIPTARTYPE_GNU) 491 { 492 if (!pThis->szName[0]) 493 { 494 rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name)); 495 AssertRCReturn(rc, rc); 496 } 497 } 498 else 499 { 500 /* Old TAR */ 501 Assert(pThis->offGnuLongCur == 0); Assert(pThis->szName[0] == '\0'); 502 rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name)); 503 AssertRCReturn(rc, rc); 504 } 505 506 /* 507 * Extract the link target. 508 */ 509 if ( pHdr->Common.typeflag == RTZIPTAR_TF_LINK 510 || pHdr->Common.typeflag == RTZIPTAR_TF_SYMLINK) 511 { 512 if ( pThis->enmType == RTZIPTARTYPE_POSIX 513 || pThis->enmType == RTZIPTARTYPE_ANCIENT 514 || (pThis->enmType == RTZIPTARTYPE_GNU && pThis->szTarget[0] == '\0') 515 ) 516 { 517 Assert(pThis->szTarget[0] == '\0'); 518 rc = RTStrCopyEx(pThis->szTarget, sizeof(pThis->szTarget), 519 pHdr->Common.linkname, sizeof(pHdr->Common.linkname)); 520 AssertRCReturn(rc, rc); 521 } 522 } 523 else 524 pThis->szTarget[0] = '\0'; 525 526 pThis->Hdr = *pHdr; 527 break; 528 529 case RTZIPTAR_TF_X_HDR: 530 case RTZIPTAR_TF_X_GLOBAL: 531 /** @todo implement PAX */ 532 return VERR_TAR_UNSUPPORTED_PAX_TYPE; 533 534 case RTZIPTAR_TF_SOLARIS_XHDR: 535 /** @todo implement solaris / pax attribute lists. */ 536 return VERR_TAR_UNSUPPORTED_SOLARIS_HDR_TYPE; 537 538 539 /* 540 * A GNU long name or long link is a dummy record followed by one or 541 * more 512 byte string blocks holding the long name/link. The name 542 * lenght is encoded in the size field, null terminator included. If 543 * it is a symlink or hard link the long name may be followed by a 544 * long link sequence. 545 */ 546 case RTZIPTAR_TF_GNU_LONGNAME: 547 case RTZIPTAR_TF_GNU_LONGLINK: 548 { 549 if (strcmp(pHdr->Gnu.name, "././@LongLink")) 550 return VERR_TAR_MALFORMED_GNU_LONGXXXX; 551 552 int64_t cb64; 553 rc = rtZipTarHdrFieldToNum(pHdr->Gnu.size, sizeof(pHdr->Gnu.size), false /*fOctalOnly*/, &cb64); 554 if (RT_FAILURE(rc) || cb64 < 0 || cb64 > _1M) 555 return VERR_TAR_MALFORMED_GNU_LONGXXXX; 556 uint32_t cb = (uint32_t)cb64; 557 if (cb >= sizeof(pThis->szName)) 558 return VERR_TAR_NAME_TOO_LONG; 559 560 pThis->cbGnuLongExpect = cb; 561 pThis->offGnuLongCur = 0; 562 pThis->enmState = pHdr->Common.typeflag == RTZIPTAR_TF_GNU_LONGNAME 563 ? RTZIPTARREADERSTATE_GNU_LONGNAME 564 : RTZIPTARREADERSTATE_GNU_LONGLINK; 565 break; 566 } 567 568 case RTZIPTAR_TF_GNU_DUMPDIR: 569 case RTZIPTAR_TF_GNU_MULTIVOL: 570 case RTZIPTAR_TF_GNU_SPARSE: 571 case RTZIPTAR_TF_GNU_VOLDHR: 572 /** @todo Implement or skip GNU headers */ 573 return VERR_TAR_UNSUPPORTED_GNU_HDR_TYPE; 574 575 default: 576 return VERR_TAR_UNKNOWN_TYPE_FLAG; 577 } 578 579 return VINF_SUCCESS; 580 } 581 582 583 /** 584 * Parses and validates a TAR header. 585 * 586 * @returns IPRT status code. 587 * @param pThis The TAR reader stat. 588 * @param pTar The TAR header that has been read. 589 */ 590 static int rtZipTarReaderParseHeader(PRTZIPTARREADER pThis, PCRTZIPTARHDR pHdr) 591 { 592 switch (pThis->enmState) 593 { 594 /* 595 * The first record for a file/directory/whatever. 596 */ 597 case RTZIPTARREADERSTATE_FIRST: 598 pThis->Hdr.Common.typeflag = 0x7f; 599 pThis->enmPrevType = pThis->enmType; 600 pThis->enmType = RTZIPTARTYPE_INVALID; 601 pThis->offGnuLongCur = 0; 602 pThis->cbGnuLongExpect = 0; 603 pThis->szName[0] = '\0'; 604 pThis->szTarget[0] = '\0'; 605 return rtZipTarReaderParseNextHeader(pThis, pHdr, true /*fFirst*/); 606 607 /* 608 * There should only be so many zero headers at the end of the file as 609 * it is a function of the block size used when writing. Don't go on 610 * reading them forever in case someone points us to /dev/zero. 611 */ 612 case RTZIPTARREADERSTATE_ZERO: 613 if (ASMMemIsAllU32(pHdr, sizeof(*pHdr), 0) != NULL) 614 return VERR_TAR_ZERO_HEADER; 615 pThis->cZeroHdrs++; 616 if (pThis->cZeroHdrs <= _64K / 512 + 2) 617 return VINF_SUCCESS; 618 return VERR_TAR_ZERO_HEADER; 619 620 case RTZIPTARREADERSTATE_GNU_LONGNAME: 621 case RTZIPTARREADERSTATE_GNU_LONGLINK: 622 { 623 size_t cbIncoming = RTStrNLen((const char *)pHdr->ab, sizeof(*pHdr)); 624 if (cbIncoming < sizeof(*pHdr)) 625 cbIncoming += 1; 626 627 if (cbIncoming + pThis->offGnuLongCur > pThis->cbGnuLongExpect) 628 return VERR_TAR_MALFORMED_GNU_LONGXXXX; 629 if ( cbIncoming < sizeof(*pHdr) 630 && cbIncoming + pThis->offGnuLongCur != pThis->cbGnuLongExpect) 631 return VERR_TAR_MALFORMED_GNU_LONGXXXX; 632 633 char *pszDst = pThis->enmState == RTZIPTARREADERSTATE_GNU_LONGNAME ? pThis->szName : pThis->szTarget; 634 pszDst += pThis->offGnuLongCur; 635 memcpy(pszDst, pHdr->ab, cbIncoming); 636 637 pThis->offGnuLongCur += (uint32_t)cbIncoming; 638 if (pThis->offGnuLongCur == pThis->cbGnuLongExpect) 639 pThis->enmState = RTZIPTARREADERSTATE_GNU_NEXT; 640 return VINF_SUCCESS; 641 } 642 643 case RTZIPTARREADERSTATE_GNU_NEXT: 644 pThis->enmState = RTZIPTARREADERSTATE_FIRST; 645 return rtZipTarReaderParseNextHeader(pThis, pHdr, false /*fFirst*/); 646 647 default: 648 return VERR_INTERNAL_ERROR_5; 649 } 650 } 651 652 653 /** 654 * Translate a TAR header to an IPRT object info structure with additional UNIX 225 * Translate a XAR header to an IPRT object info structure with additional UNIX 655 226 * attributes. 656 227 * 657 * This completes the validation done by rtZip TarHdrValidate.228 * This completes the validation done by rtZipXarHdrValidate. 658 229 * 659 * @returns VINF_SUCCESS if valid, appropriate VERR_ TAR_XXX if not.660 * @param pThis The TAR reader instance.230 * @returns VINF_SUCCESS if valid, appropriate VERR_XAR_XXX if not. 231 * @param pThis The XAR reader instance. 661 232 * @param pObjInfo The object info structure (output). 662 233 */ 663 static int rtZip TarReaderGetFsObjInfo(PRTZIPTARREADER pThis, PRTFSOBJINFO pObjInfo)234 static int rtZipXarReaderGetFsObjInfo(PRTZIPXARREADER pThis, PRTFSOBJINFO pObjInfo) 664 235 { 665 236 /* … … 668 239 RT_ZERO(*pObjInfo); 669 240 670 /* 671 * Convert the TAR field in RTFSOBJINFO order. 241 #if 0 242 /* 243 * Convert the XAR field in RTFSOBJINFO order. 672 244 */ 673 245 int rc; 674 246 int64_t i64Tmp; 675 #define GET_ TAR_NUMERIC_FIELD_RET(a_Var, a_Field) \247 #define GET_XAR_NUMERIC_FIELD_RET(a_Var, a_Field) \ 676 248 do { \ 677 rc = rtZip TarHdrFieldToNum(a_Field, sizeof(a_Field), false /*fOctalOnly*/, &i64Tmp); \249 rc = rtZipXarHdrFieldToNum(a_Field, sizeof(a_Field), false /*fOctalOnly*/, &i64Tmp); \ 678 250 if (RT_FAILURE(rc)) \ 679 251 return rc; \ 680 252 (a_Var) = i64Tmp; \ 681 253 if ((a_Var) != i64Tmp) \ 682 return VERR_ TAR_NUM_VALUE_TOO_LARGE; \254 return VERR_XAR_NUM_VALUE_TOO_LARGE; \ 683 255 } while (0) 684 256 685 GET_ TAR_NUMERIC_FIELD_RET(pObjInfo->cbObject, pThis->Hdr.Common.size);257 GET_XAR_NUMERIC_FIELD_RET(pObjInfo->cbObject, pThis->Hdr.Common.size); 686 258 pObjInfo->cbAllocated = RT_ALIGN_64(pObjInfo->cbObject, 512); 687 259 int64_t c64SecModTime; 688 GET_ TAR_NUMERIC_FIELD_RET(c64SecModTime, pThis->Hdr.Common.mtime);260 GET_XAR_NUMERIC_FIELD_RET(c64SecModTime, pThis->Hdr.Common.mtime); 689 261 RTTimeSpecSetSeconds(&pObjInfo->ChangeTime, c64SecModTime); 690 262 RTTimeSpecSetSeconds(&pObjInfo->ModificationTime, c64SecModTime); … … 692 264 RTTimeSpecSetSeconds(&pObjInfo->BirthTime, c64SecModTime); 693 265 if (c64SecModTime != RTTimeSpecGetSeconds(&pObjInfo->ModificationTime)) 694 return VERR_ TAR_NUM_VALUE_TOO_LARGE;695 GET_ TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.fMode, pThis->Hdr.Common.mode);266 return VERR_XAR_NUM_VALUE_TOO_LARGE; 267 GET_XAR_NUMERIC_FIELD_RET(pObjInfo->Attr.fMode, pThis->Hdr.Common.mode); 696 268 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX; 697 GET_ TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.uid, pThis->Hdr.Common.uid);698 GET_ TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.gid, pThis->Hdr.Common.gid);269 GET_XAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.uid, pThis->Hdr.Common.uid); 270 GET_XAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.gid, pThis->Hdr.Common.gid); 699 271 pObjInfo->Attr.u.Unix.cHardlinks = 1; 700 272 pObjInfo->Attr.u.Unix.INodeIdDevice = 0; … … 705 277 switch (pThis->enmType) 706 278 { 707 case RTZIP TARTYPE_POSIX:708 case RTZIP TARTYPE_GNU:709 if ( pThis->Hdr.Common.typeflag == RTZIP TAR_TF_CHR710 || pThis->Hdr.Common.typeflag == RTZIP TAR_TF_BLK)279 case RTZIPXARTYPE_POSIX: 280 case RTZIPXARTYPE_GNU: 281 if ( pThis->Hdr.Common.typeflag == RTZIPXAR_TF_CHR 282 || pThis->Hdr.Common.typeflag == RTZIPXAR_TF_BLK) 711 283 { 712 284 uint32_t uMajor, uMinor; 713 GET_ TAR_NUMERIC_FIELD_RET(uMajor, pThis->Hdr.Common.devmajor);714 GET_ TAR_NUMERIC_FIELD_RET(uMinor, pThis->Hdr.Common.devminor);285 GET_XAR_NUMERIC_FIELD_RET(uMajor, pThis->Hdr.Common.devmajor); 286 GET_XAR_NUMERIC_FIELD_RET(uMinor, pThis->Hdr.Common.devminor); 715 287 pObjInfo->Attr.u.Unix.Device = RTDEV_MAKE(uMajor, uMinor); 716 288 if ( uMajor != RTDEV_MAJOR(pObjInfo->Attr.u.Unix.Device) 717 289 || uMinor != RTDEV_MINOR(pObjInfo->Attr.u.Unix.Device)) 718 return VERR_ TAR_DEV_VALUE_TOO_LARGE;290 return VERR_XAR_DEV_VALUE_TOO_LARGE; 719 291 } 720 292 break; 721 293 722 294 default: 723 if ( pThis->Hdr.Common.typeflag == RTZIP TAR_TF_CHR724 || pThis->Hdr.Common.typeflag == RTZIP TAR_TF_BLK)725 return VERR_ TAR_UNKNOWN_TYPE_FLAG;726 } 727 728 #undef GET_ TAR_NUMERIC_FIELD_RET295 if ( pThis->Hdr.Common.typeflag == RTZIPXAR_TF_CHR 296 || pThis->Hdr.Common.typeflag == RTZIPXAR_TF_BLK) 297 return VERR_XAR_UNKNOWN_TYPE_FLAG; 298 } 299 300 #undef GET_XAR_NUMERIC_FIELD_RET 729 301 730 302 /* … … 733 305 */ 734 306 if ( (pObjInfo->Attr.fMode & ~RTFS_UNIX_MASK) 735 && pThis->enmType == RTZIP TARTYPE_POSIX)736 return VERR_ TAR_BAD_MODE_FIELD;307 && pThis->enmType == RTZIPXARTYPE_POSIX) 308 return VERR_XAR_BAD_MODE_FIELD; 737 309 pObjInfo->Attr.fMode &= RTFS_UNIX_MASK; 738 310 … … 740 312 switch (pThis->Hdr.Common.typeflag) 741 313 { 742 case RTZIP TAR_TF_OLDNORMAL:743 case RTZIP TAR_TF_NORMAL:744 case RTZIP TAR_TF_CONTIG:314 case RTZIPXAR_TF_OLDNORMAL: 315 case RTZIPXAR_TF_NORMAL: 316 case RTZIPXAR_TF_CONTIG: 745 317 { 746 318 const char *pszEnd = strchr(pThis->szName, '\0'); … … 752 324 } 753 325 754 case RTZIP TAR_TF_LINK:326 case RTZIPXAR_TF_LINK: 755 327 if (pObjInfo->cbObject != 0) 756 328 #if 0 /* too strict */ 757 return VERR_ TAR_SIZE_NOT_ZERO;329 return VERR_XAR_SIZE_NOT_ZERO; 758 330 #else 759 331 pObjInfo->cbObject = pObjInfo->cbAllocated = 0; … … 762 334 break; 763 335 764 case RTZIP TAR_TF_SYMLINK:336 case RTZIPXAR_TF_SYMLINK: 765 337 fModeType |= RTFS_TYPE_SYMLINK; 766 338 break; 767 339 768 case RTZIP TAR_TF_CHR:340 case RTZIPXAR_TF_CHR: 769 341 fModeType |= RTFS_TYPE_DEV_CHAR; 770 342 break; 771 343 772 case RTZIP TAR_TF_BLK:344 case RTZIPXAR_TF_BLK: 773 345 fModeType |= RTFS_TYPE_DEV_BLOCK; 774 346 break; 775 347 776 case RTZIP TAR_TF_DIR:348 case RTZIPXAR_TF_DIR: 777 349 fModeType |= RTFS_TYPE_DIRECTORY; 778 350 break; 779 351 780 case RTZIP TAR_TF_FIFO:352 case RTZIPXAR_TF_FIFO: 781 353 fModeType |= RTFS_TYPE_FIFO; 782 354 break; 783 355 784 case RTZIP TAR_TF_GNU_LONGLINK:785 case RTZIP TAR_TF_GNU_LONGNAME:356 case RTZIPXAR_TF_GNU_LONGLINK: 357 case RTZIPXAR_TF_GNU_LONGNAME: 786 358 /* ASSUMES RTFS_TYPE_XXX uses the same values as GNU stored in the mode field. */ 787 359 fModeType = pObjInfo->Attr.fMode & RTFS_TYPE_MASK; … … 798 370 default: 799 371 case 0: 800 return VERR_ TAR_UNKNOWN_TYPE_FLAG; /** @todo new status code */372 return VERR_XAR_UNKNOWN_TYPE_FLAG; /** @todo new status code */ 801 373 } 802 374 803 375 default: 804 return VERR_ TAR_UNKNOWN_TYPE_FLAG; /* Should've been caught in validate. */376 return VERR_XAR_UNKNOWN_TYPE_FLAG; /* Should've been caught in validate. */ 805 377 } 806 378 if ( (pObjInfo->Attr.fMode & RTFS_TYPE_MASK) 807 379 && (pObjInfo->Attr.fMode & RTFS_TYPE_MASK) != fModeType) 808 return VERR_ TAR_MODE_WITH_TYPE;380 return VERR_XAR_MODE_WITH_TYPE; 809 381 pObjInfo->Attr.fMode &= ~RTFS_TYPE_MASK; 810 382 pObjInfo->Attr.fMode |= fModeType; … … 812 384 switch (pThis->Hdr.Common.typeflag) 813 385 { 814 case RTZIP TAR_TF_CHR:815 case RTZIP TAR_TF_BLK:816 case RTZIP TAR_TF_DIR:817 case RTZIP TAR_TF_FIFO:386 case RTZIPXAR_TF_CHR: 387 case RTZIPXAR_TF_BLK: 388 case RTZIPXAR_TF_DIR: 389 case RTZIPXAR_TF_FIFO: 818 390 pObjInfo->cbObject = 0; 819 391 pObjInfo->cbAllocated = 0; 820 392 break; 821 393 } 394 #endif 822 395 823 396 return VINF_SUCCESS; 824 397 } 825 398 826 827 /**828 * Checks if the reader is expecting more headers.829 *830 * @returns true / false.831 * @param pThis The TAR reader instance.832 */833 static bool rtZipTarReaderExpectingMoreHeaders(PRTZIPTARREADER pThis)834 {835 return pThis->enmState != RTZIPTARREADERSTATE_FIRST;836 }837 838 839 /**840 * Checks if we're at the end of the TAR file.841 *842 * @returns true / false.843 * @param pThis The TAR reader instance.844 */845 static bool rtZipTarReaderIsAtEnd(PRTZIPTARREADER pThis)846 {847 if (!pThis->cZeroHdrs)848 return false;849 850 /* Here is a kludge to try deal with archivers not putting at least two851 zero headers at the end. Afraid it may require further relaxing852 later on, but let's try be strict about things for now. */853 return pThis->cZeroHdrs >= (pThis->enmPrevType == RTZIPTARTYPE_POSIX ? 2U : 1U);854 }855 856 857 /**858 * Checks if the current TAR object is a hard link or not.859 *860 * @returns true if it is, false if not.861 * @param pThis The TAR reader instance.862 */863 static bool rtZipTarReaderIsHardlink(PRTZIPTARREADER pThis)864 {865 return pThis->Hdr.Common.typeflag == RTZIPTAR_TF_LINK;866 }867 868 869 /**870 * Checks if the TAR header includes a POSIX or GNU user name field.871 *872 * @returns true / false.873 * @param pThis The TAR reader instance.874 */875 DECLINLINE(bool) rtZipTarReaderHasUserName(PRTZIPTARREADER pThis)876 {877 return pThis->Hdr.Common.uname[0] != '\0'878 && ( pThis->enmType == RTZIPTARTYPE_POSIX879 || pThis->enmType == RTZIPTARTYPE_GNU);880 }881 882 883 /**884 * Checks if the TAR header includes a POSIX or GNU group name field.885 *886 * @returns true / false.887 * @param pThis The TAR reader instance.888 */889 DECLINLINE(bool) rtZipTarReaderHasGroupName(PRTZIPTARREADER pThis)890 {891 return pThis->Hdr.Common.gname[0] != '\0'892 && ( pThis->enmType == RTZIPTARTYPE_POSIX893 || pThis->enmType == RTZIPTARTYPE_GNU);894 }895 399 896 400 … … 906 410 * @interface_method_impl{RTVFSOBJOPS,pfnClose} 907 411 */ 908 static DECLCALLBACK(int) rtZip TarFssBaseObj_Close(void *pvThis)909 { 910 PRTZIP TARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis;412 static DECLCALLBACK(int) rtZipXarFssBaseObj_Close(void *pvThis) 413 { 414 PRTZIPXARBASEOBJ pThis = (PRTZIPXARBASEOBJ)pvThis; 911 415 912 416 /* Currently there is nothing we really have to do here. */ … … 920 424 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo} 921 425 */ 922 static DECLCALLBACK(int) rtZipTarFssBaseObj_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr) 923 { 924 PRTZIPTARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis; 925 426 static DECLCALLBACK(int) rtZipXarFssBaseObj_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr) 427 { 428 PRTZIPXARBASEOBJ pThis = (PRTZIPXARBASEOBJ)pvThis; 429 430 #if 0 926 431 /* 927 432 * Copy the desired data. … … 939 444 pObjInfo->Attr.u.UnixOwner.uid = pThis->ObjInfo.Attr.u.Unix.uid; 940 445 pObjInfo->Attr.u.UnixOwner.szName[0] = '\0'; 941 if (rtZip TarReaderHasUserName(pThis->pTarReader))446 if (rtZipXarReaderHasUserName(pThis->pXarReader)) 942 447 RTStrCopy(pObjInfo->Attr.u.UnixOwner.szName, sizeof(pObjInfo->Attr.u.UnixOwner.szName), 943 pThis->p TarReader->Hdr.Common.uname);448 pThis->pXarReader->Hdr.Common.uname); 944 449 break; 945 450 … … 949 454 pObjInfo->Attr.u.UnixGroup.gid = pThis->ObjInfo.Attr.u.Unix.gid; 950 455 pObjInfo->Attr.u.UnixGroup.szName[0] = '\0'; 951 if (rtZip TarReaderHasGroupName(pThis->pTarReader))456 if (rtZipXarReaderHasGroupName(pThis->pXarReader)) 952 457 RTStrCopy(pObjInfo->Attr.u.UnixGroup.szName, sizeof(pObjInfo->Attr.u.UnixGroup.szName), 953 pThis->p TarReader->Hdr.Common.gname);458 pThis->pXarReader->Hdr.Common.gname); 954 459 break; 955 460 … … 963 468 return VERR_NOT_SUPPORTED; 964 469 } 470 #endif 965 471 966 472 return VINF_SUCCESS; … … 969 475 970 476 /** 971 * Tar filesystem base object operations.972 */ 973 static const RTVFSOBJOPS g_rtZip TarFssBaseObjOps =477 * Xar filesystem base object operations. 478 */ 479 static const RTVFSOBJOPS g_rtZipXarFssBaseObjOps = 974 480 { 975 481 RTVFSOBJOPS_VERSION, 976 482 RTVFSOBJTYPE_BASE, 977 " TarFsStream::Obj",978 rtZip TarFssBaseObj_Close,979 rtZip TarFssBaseObj_QueryInfo,483 "XarFsStream::Obj", 484 rtZipXarFssBaseObj_Close, 485 rtZipXarFssBaseObj_QueryInfo, 980 486 RTVFSOBJOPS_VERSION 981 487 }; … … 985 491 * @interface_method_impl{RTVFSOBJOPS,pfnClose} 986 492 */ 987 static DECLCALLBACK(int) rtZip TarFssIos_Close(void *pvThis)988 { 989 PRTZIP TARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;493 static DECLCALLBACK(int) rtZipXarFssIos_Close(void *pvThis) 494 { 495 PRTZIPXARIOSTREAM pThis = (PRTZIPXARIOSTREAM)pvThis; 990 496 991 497 RTVfsIoStrmRelease(pThis->hVfsIos); 992 498 pThis->hVfsIos = NIL_RTVFSIOSTREAM; 993 499 994 return rtZip TarFssBaseObj_Close(&pThis->BaseObj);500 return rtZipXarFssBaseObj_Close(&pThis->BaseObj); 995 501 } 996 502 … … 999 505 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo} 1000 506 */ 1001 static DECLCALLBACK(int) rtZip TarFssIos_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)1002 { 1003 PRTZIP TARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;1004 return rtZip TarFssBaseObj_QueryInfo(&pThis->BaseObj, pObjInfo, enmAddAttr);507 static DECLCALLBACK(int) rtZipXarFssIos_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr) 508 { 509 PRTZIPXARIOSTREAM pThis = (PRTZIPXARIOSTREAM)pvThis; 510 return rtZipXarFssBaseObj_QueryInfo(&pThis->BaseObj, pObjInfo, enmAddAttr); 1005 511 } 1006 512 … … 1016 522 * @param pcbRead Where to store the number of bytes actually read. 1017 523 */ 1018 static int rtZip TarFssIos_ReadOneSeg(PRTZIPTARIOSTREAM pThis, void *pvBuf, size_t cbToRead, bool fBlocking, size_t *pcbRead)524 static int rtZipXarFssIos_ReadOneSeg(PRTZIPXARIOSTREAM pThis, void *pvBuf, size_t cbToRead, bool fBlocking, size_t *pcbRead) 1019 525 { 1020 526 /* … … 1055 561 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead} 1056 562 */ 1057 static DECLCALLBACK(int) rtZip TarFssIos_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)1058 { 1059 PRTZIP TARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;563 static DECLCALLBACK(int) rtZipXarFssIos_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead) 564 { 565 PRTZIPXARIOSTREAM pThis = (PRTZIPXARIOSTREAM)pvThis; 1060 566 int rc; 1061 567 AssertReturn(off == -1, VERR_INVALID_PARAMETER); 1062 568 1063 569 if (pSgBuf->cSegs == 1) 1064 rc = rtZip TarFssIos_ReadOneSeg(pThis, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, fBlocking, pcbRead);570 rc = rtZipXarFssIos_ReadOneSeg(pThis, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, fBlocking, pcbRead); 1065 571 else 1066 572 { … … 1072 578 { 1073 579 cbReadSeg = 0; 1074 rc = rtZip TarFssIos_ReadOneSeg(pThis, pSgBuf->paSegs[iSeg].pvSeg, pSgBuf->paSegs[iSeg].cbSeg, fBlocking, pcbReadSeg);580 rc = rtZipXarFssIos_ReadOneSeg(pThis, pSgBuf->paSegs[iSeg].pvSeg, pSgBuf->paSegs[iSeg].cbSeg, fBlocking, pcbReadSeg); 1075 581 if (RT_FAILURE(rc)) 1076 582 break; … … 1093 599 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite} 1094 600 */ 1095 static DECLCALLBACK(int) rtZip TarFssIos_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)601 static DECLCALLBACK(int) rtZipXarFssIos_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten) 1096 602 { 1097 603 /* Cannot write to a read-only I/O stream. */ … … 1104 610 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush} 1105 611 */ 1106 static DECLCALLBACK(int) rtZip TarFssIos_Flush(void *pvThis)612 static DECLCALLBACK(int) rtZipXarFssIos_Flush(void *pvThis) 1107 613 { 1108 614 /* It's a read only stream, nothing dirty to flush. */ … … 1115 621 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnPollOne} 1116 622 */ 1117 static DECLCALLBACK(int) rtZip TarFssIos_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,623 static DECLCALLBACK(int) rtZipXarFssIos_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr, 1118 624 uint32_t *pfRetEvents) 1119 625 { 1120 PRTZIP TARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;626 PRTZIPXARIOSTREAM pThis = (PRTZIPXARIOSTREAM)pvThis; 1121 627 1122 628 /* When we've reached the end, read will be set to indicate it. */ … … 1139 645 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell} 1140 646 */ 1141 static DECLCALLBACK(int) rtZip TarFssIos_Tell(void *pvThis, PRTFOFF poffActual)1142 { 1143 PRTZIP TARIOSTREAM pThis = (PRTZIPTARIOSTREAM)pvThis;647 static DECLCALLBACK(int) rtZipXarFssIos_Tell(void *pvThis, PRTFOFF poffActual) 648 { 649 PRTZIPXARIOSTREAM pThis = (PRTZIPXARIOSTREAM)pvThis; 1144 650 *poffActual = pThis->offFile; 1145 651 return VINF_SUCCESS; … … 1148 654 1149 655 /** 1150 * Tar I/O stream operations.1151 */ 1152 static const RTVFSIOSTREAMOPS g_rtZip TarFssIosOps =656 * Xar I/O stream operations. 657 */ 658 static const RTVFSIOSTREAMOPS g_rtZipXarFssIosOps = 1153 659 { 1154 660 { /* Obj */ 1155 661 RTVFSOBJOPS_VERSION, 1156 662 RTVFSOBJTYPE_IO_STREAM, 1157 " TarFsStream::IoStream",1158 rtZip TarFssIos_Close,1159 rtZip TarFssIos_QueryInfo,663 "XarFsStream::IoStream", 664 rtZipXarFssIos_Close, 665 rtZipXarFssIos_QueryInfo, 1160 666 RTVFSOBJOPS_VERSION 1161 667 }, 1162 668 RTVFSIOSTREAMOPS_VERSION, 1163 669 0, 1164 rtZip TarFssIos_Read,1165 rtZip TarFssIos_Write,1166 rtZip TarFssIos_Flush,1167 rtZip TarFssIos_PollOne,1168 rtZip TarFssIos_Tell,670 rtZipXarFssIos_Read, 671 rtZipXarFssIos_Write, 672 rtZipXarFssIos_Flush, 673 rtZipXarFssIos_PollOne, 674 rtZipXarFssIos_Tell, 1169 675 NULL /*Skip*/, 1170 676 NULL /*ZeroFill*/, … … 1176 682 * @interface_method_impl{RTVFSOBJOPS,pfnClose} 1177 683 */ 1178 static DECLCALLBACK(int) rtZip TarFssSym_Close(void *pvThis)1179 { 1180 PRTZIP TARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis;1181 return rtZip TarFssBaseObj_Close(pThis);684 static DECLCALLBACK(int) rtZipXarFssSym_Close(void *pvThis) 685 { 686 PRTZIPXARBASEOBJ pThis = (PRTZIPXARBASEOBJ)pvThis; 687 return rtZipXarFssBaseObj_Close(pThis); 1182 688 } 1183 689 … … 1186 692 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo} 1187 693 */ 1188 static DECLCALLBACK(int) rtZip TarFssSym_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)1189 { 1190 PRTZIP TARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis;1191 return rtZip TarFssBaseObj_QueryInfo(pThis, pObjInfo, enmAddAttr);694 static DECLCALLBACK(int) rtZipXarFssSym_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr) 695 { 696 PRTZIPXARBASEOBJ pThis = (PRTZIPXARBASEOBJ)pvThis; 697 return rtZipXarFssBaseObj_QueryInfo(pThis, pObjInfo, enmAddAttr); 1192 698 } 1193 699 … … 1195 701 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode} 1196 702 */ 1197 static DECLCALLBACK(int) rtZip TarFssSym_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)703 static DECLCALLBACK(int) rtZipXarFssSym_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask) 1198 704 { 1199 705 NOREF(pvThis); NOREF(fMode); NOREF(fMask); … … 1205 711 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes} 1206 712 */ 1207 static DECLCALLBACK(int) rtZip TarFssSym_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,713 static DECLCALLBACK(int) rtZipXarFssSym_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime, 1208 714 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime) 1209 715 { … … 1216 722 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner} 1217 723 */ 1218 static DECLCALLBACK(int) rtZip TarFssSym_SetOwner(void *pvThis, RTUID uid, RTGID gid)724 static DECLCALLBACK(int) rtZipXarFssSym_SetOwner(void *pvThis, RTUID uid, RTGID gid) 1219 725 { 1220 726 NOREF(pvThis); NOREF(uid); NOREF(gid); … … 1226 732 * @interface_method_impl{RTVFSSYMLINKOPS,pfnRead} 1227 733 */ 1228 static DECLCALLBACK(int) rtZipTarFssSym_Read(void *pvThis, char *pszTarget, size_t cbTarget) 1229 { 1230 PRTZIPTARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis; 1231 return RTStrCopy(pszTarget, cbTarget, pThis->pTarReader->szTarget); 1232 } 1233 1234 1235 /** 1236 * Tar symbolic (and hardlink) operations. 1237 */ 1238 static const RTVFSSYMLINKOPS g_rtZipTarFssSymOps = 734 static DECLCALLBACK(int) rtZipXarFssSym_Read(void *pvThis, char *pszTarget, size_t cbXarget) 735 { 736 PRTZIPXARBASEOBJ pThis = (PRTZIPXARBASEOBJ)pvThis; 737 #if 0 738 return RTStrCopy(pszTarget, cbXarget, pThis->pXarReader->szTarget); 739 #else 740 return VERR_NOT_IMPLEMENTED; 741 #endif 742 } 743 744 745 /** 746 * Xar symbolic (and hardlink) operations. 747 */ 748 static const RTVFSSYMLINKOPS g_rtZipXarFssSymOps = 1239 749 { 1240 750 { /* Obj */ 1241 751 RTVFSOBJOPS_VERSION, 1242 752 RTVFSOBJTYPE_SYMLINK, 1243 " TarFsStream::Symlink",1244 rtZip TarFssSym_Close,1245 rtZip TarFssSym_QueryInfo,753 "XarFsStream::Symlink", 754 rtZipXarFssSym_Close, 755 rtZipXarFssSym_QueryInfo, 1246 756 RTVFSOBJOPS_VERSION 1247 757 }, … … 1251 761 RTVFSOBJSETOPS_VERSION, 1252 762 RT_OFFSETOF(RTVFSSYMLINKOPS, Obj) - RT_OFFSETOF(RTVFSSYMLINKOPS, ObjSet), 1253 rtZip TarFssSym_SetMode,1254 rtZip TarFssSym_SetTimes,1255 rtZip TarFssSym_SetOwner,763 rtZipXarFssSym_SetMode, 764 rtZipXarFssSym_SetTimes, 765 rtZipXarFssSym_SetOwner, 1256 766 RTVFSOBJSETOPS_VERSION 1257 767 }, 1258 rtZip TarFssSym_Read,768 rtZipXarFssSym_Read, 1259 769 RTVFSSYMLINKOPS_VERSION 1260 770 }; … … 1264 774 * @interface_method_impl{RTVFSOBJOPS,pfnClose} 1265 775 */ 1266 static DECLCALLBACK(int) rtZip TarFss_Close(void *pvThis)1267 { 1268 PRTZIP TARFSSTREAM pThis = (PRTZIPTARFSSTREAM)pvThis;776 static DECLCALLBACK(int) rtZipXarFss_Close(void *pvThis) 777 { 778 PRTZIPXARFSSTREAM pThis = (PRTZIPXARFSSTREAM)pvThis; 1269 779 1270 780 RTVfsObjRelease(pThis->hVfsCurObj); … … 1282 792 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo} 1283 793 */ 1284 static DECLCALLBACK(int) rtZip TarFss_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)1285 { 1286 PRTZIP TARFSSTREAM pThis = (PRTZIPTARFSSTREAM)pvThis;794 static DECLCALLBACK(int) rtZipXarFss_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr) 795 { 796 PRTZIPXARFSSTREAM pThis = (PRTZIPXARFSSTREAM)pvThis; 1287 797 /* Take the lazy approach here, with the sideffect of providing some info 1288 798 that is actually kind of useful. */ … … 1294 804 * @interface_method_impl{RTVFSFSSTREAMOPS,pfnNext} 1295 805 */ 1296 static DECLCALLBACK(int) rtZip TarFss_Next(void *pvThis, char **ppszName, RTVFSOBJTYPE *penmType, PRTVFSOBJ phVfsObj)1297 { 1298 PRTZIP TARFSSTREAM pThis = (PRTZIPTARFSSTREAM)pvThis;806 static DECLCALLBACK(int) rtZipXarFss_Next(void *pvThis, char **ppszName, RTVFSOBJTYPE *penmType, PRTVFSOBJ phVfsObj) 807 { 808 PRTZIPXARFSSTREAM pThis = (PRTZIPXARFSSTREAM)pvThis; 1299 809 1300 810 /* … … 1322 832 return pThis->rcFatal; 1323 833 834 #if 0 1324 835 /* 1325 836 * Make sure the input stream is in the right place. … … 1345 856 1346 857 /* 1347 * Consume TAR headers.858 * Consume XAR headers. 1348 859 */ 1349 860 size_t cbHdrs = 0; … … 1354 865 * Read the next header. 1355 866 */ 1356 RTZIP TARHDR Hdr;867 RTZIPXARHDR Hdr; 1357 868 size_t cbRead; 1358 869 rc = RTVfsIoStrmRead(pThis->hVfsIos, &Hdr, sizeof(Hdr), true /*fBlocking*/, &cbRead); … … 1362 873 { 1363 874 pThis->fEndOfStream = true; 1364 return rtZip TarReaderIsAtEnd(&pThis->TarReader) ? VERR_EOF : VERR_TAR_UNEXPECTED_EOS;875 return rtZipXarReaderIsAtEnd(&pThis->XarReader) ? VERR_EOF : VERR_XAR_UNEXPECTED_EOS; 1365 876 } 1366 877 if (cbRead != sizeof(Hdr)) 1367 return pThis->rcFatal = VERR_ TAR_UNEXPECTED_EOS;878 return pThis->rcFatal = VERR_XAR_UNEXPECTED_EOS; 1368 879 1369 880 cbHdrs += sizeof(Hdr); … … 1372 883 * Parse the it. 1373 884 */ 1374 rc = rtZip TarReaderParseHeader(&pThis->TarReader, &Hdr);885 rc = rtZipXarReaderParseHeader(&pThis->XarReader, &Hdr); 1375 886 if (RT_FAILURE(rc)) 1376 887 return pThis->rcFatal = rc; 1377 } while (rtZip TarReaderExpectingMoreHeaders(&pThis->TarReader));888 } while (rtZipXarReaderExpectingMoreHeaders(&pThis->XarReader)); 1378 889 1379 890 pThis->offNextHdr = offHdr + cbHdrs; 1380 891 1381 892 /* 1382 * Fill an object info structure from the current TAR state.893 * Fill an object info structure from the current XAR state. 1383 894 */ 1384 895 RTFSOBJINFO Info; 1385 rc = rtZip TarReaderGetFsObjInfo(&pThis->TarReader, &Info);896 rc = rtZipXarReaderGetFsObjInfo(&pThis->XarReader, &Info); 1386 897 if (RT_FAILURE(rc)) 1387 898 return pThis->rcFatal = rc; … … 1393 904 RTVFSOBJ hVfsObj; 1394 905 RTFMODE fType = Info.Attr.fMode & RTFS_TYPE_MASK; 1395 if (rtZip TarReaderIsHardlink(&pThis->TarReader))906 if (rtZipXarReaderIsHardlink(&pThis->XarReader)) 1396 907 fType = RTFS_TYPE_SYMLINK; 1397 908 switch (fType) … … 1403 914 { 1404 915 RTVFSIOSTREAM hVfsIos; 1405 PRTZIP TARIOSTREAM pIosData;1406 rc = RTVfsNewIoStream(&g_rtZip TarFssIosOps,916 PRTZIPXARIOSTREAM pIosData; 917 rc = RTVfsNewIoStream(&g_rtZipXarFssIosOps, 1407 918 sizeof(*pIosData), 1408 919 RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, … … 1415 926 1416 927 pIosData->BaseObj.offHdr = offHdr; 1417 pIosData->BaseObj.p TarReader= &pThis->TarReader;928 pIosData->BaseObj.pXarReader= &pThis->XarReader; 1418 929 pIosData->BaseObj.ObjInfo = Info; 1419 930 pIosData->cbFile = Info.cbObject; … … 1435 946 /* 1436 947 * We represent hard links using a symbolic link object. This fits 1437 * best with the way TAR stores it and there is currently no better948 * best with the way XAR stores it and there is currently no better 1438 949 * fitting VFS type alternative. 1439 950 */ … … 1441 952 { 1442 953 RTVFSSYMLINK hVfsSym; 1443 PRTZIP TARBASEOBJ pBaseObjData;1444 rc = RTVfsNewSymlink(&g_rtZip TarFssSymOps,954 PRTZIPXARBASEOBJ pBaseObjData; 955 rc = RTVfsNewSymlink(&g_rtZipXarFssSymOps, 1445 956 sizeof(*pBaseObjData), 1446 957 NIL_RTVFS, … … 1452 963 1453 964 pBaseObjData->offHdr = offHdr; 1454 pBaseObjData->p TarReader= &pThis->TarReader;965 pBaseObjData->pXarReader= &pThis->XarReader; 1455 966 pBaseObjData->ObjInfo = Info; 1456 967 … … 1463 974 /* 1464 975 * All other objects are repesented using a VFS base object since they 1465 * carry no data streams (unless some TAR extension implements extended976 * carry no data streams (unless some XAR extension implements extended 1466 977 * attributes / alternative streams). 1467 978 */ … … 1471 982 case RTFS_TYPE_FIFO: 1472 983 { 1473 PRTZIP TARBASEOBJ pBaseObjData;1474 rc = RTVfsNewBaseObj(&g_rtZip TarFssBaseObjOps,984 PRTZIPXARBASEOBJ pBaseObjData; 985 rc = RTVfsNewBaseObj(&g_rtZipXarFssBaseObjOps, 1475 986 sizeof(*pBaseObjData), 1476 987 NIL_RTVFS, … … 1482 993 1483 994 pBaseObjData->offHdr = offHdr; 1484 pBaseObjData->p TarReader= &pThis->TarReader;995 pBaseObjData->pXarReader= &pThis->XarReader; 1485 996 pBaseObjData->ObjInfo = Info; 1486 997 … … 1500 1011 if (ppszName) 1501 1012 { 1502 rc = RTStrDupEx(ppszName, pThis-> TarReader.szName);1013 rc = RTStrDupEx(ppszName, pThis->XarReader.szName); 1503 1014 if (RT_FAILURE(rc)) 1504 1015 return rc; … … 1513 1024 if (penmType) 1514 1025 *penmType = enmType; 1026 #endif 1515 1027 1516 1028 return VINF_SUCCESS; … … 1520 1032 1521 1033 /** 1522 * Tar filesystem stream operations.1523 */ 1524 static const RTVFSFSSTREAMOPS rtZip TarFssOps =1034 * Xar filesystem stream operations. 1035 */ 1036 static const RTVFSFSSTREAMOPS rtZipXarFssOps = 1525 1037 { 1526 1038 { /* Obj */ 1527 1039 RTVFSOBJOPS_VERSION, 1528 1040 RTVFSOBJTYPE_FS_STREAM, 1529 " TarFsStream",1530 rtZip TarFss_Close,1531 rtZip TarFss_QueryInfo,1041 "XarFsStream", 1042 rtZipXarFss_Close, 1043 rtZipXarFss_QueryInfo, 1532 1044 RTVFSOBJOPS_VERSION 1533 1045 }, 1534 1046 RTVFSFSSTREAMOPS_VERSION, 1535 1047 0, 1536 rtZip TarFss_Next,1048 rtZipXarFss_Next, 1537 1049 RTVFSFSSTREAMOPS_VERSION 1538 1050 }; 1539 1051 1540 1052 1541 RTDECL(int) RTZipTarFsStreamFromIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss) 1053 1054 /** 1055 * TOC validation part 2. 1056 * 1057 * Will advance the input stream past the TOC hash and signature data. 1058 * 1059 * @returns IPRT status code. 1060 * @param pThis The FS stream instance being created. 1061 * @param pXarHdr The XAR header. 1062 * @param pTocDigest The TOC input data digest. 1063 */ 1064 static int rtZipXarValidateTocPart2(PRTZIPXARFSSTREAM pThis, PCXARHEADER pXarHdr, PCRTZIPXARHASHDIGEST pTocDigest) 1065 { 1066 int rc; 1067 1068 /* 1069 * Check that the hash function in the TOC matches the one in the XAR header. 1070 */ 1071 const xml::ElementNode *pChecksumElem = pThis->XarReader.pToc->findChildElement("checksum"); 1072 if (pChecksumElem) 1073 { 1074 const xml::AttributeNode *pAttr = pChecksumElem->findAttribute("style"); 1075 if (!pAttr) 1076 return VERR_XAR_BAD_CHECKSUM_ELEMENT; 1077 1078 const char *pszStyle = pAttr->getValue(); 1079 if (!pszStyle) 1080 return VERR_XAR_BAD_CHECKSUM_ELEMENT; 1081 1082 uint8_t uHashFunction; 1083 if (!strcmp(pszStyle, "sha1")) 1084 uHashFunction = XAR_HASH_SHA1; 1085 else if (!strcmp(pszStyle, "md5")) 1086 uHashFunction = XAR_HASH_MD5; 1087 else if (!strcmp(pszStyle, "none")) 1088 uHashFunction = XAR_HASH_NONE; 1089 else 1090 return VERR_XAR_BAD_CHECKSUM_ELEMENT; 1091 if (uHashFunction != pThis->uHashFunction) 1092 return VERR_XAR_HASH_FUNCTION_MISMATCH; 1093 1094 /* 1095 * Verify the checksum if we got one. 1096 */ 1097 if (pThis->uHashFunction != XAR_HASH_NONE) 1098 { 1099 RTFOFF offChecksum; 1100 uint64_t cbChecksum; 1101 rc = rtZipXarGetOffsetSizeFromElem(pChecksumElem, &offChecksum, &cbChecksum); 1102 if (RT_FAILURE(rc)) 1103 return rc; 1104 if (cbChecksum != pThis->cbHashDigest) 1105 return VERR_XAR_BAD_DIGEST_LENGTH; 1106 if (offChecksum != 0 && pThis->hVfsFile == NIL_RTVFSFILE) 1107 return VERR_XAR_NOT_STREAMBLE_ELEMENT_ORDER; 1108 1109 RTZIPXARHASHDIGEST StoredDigest; 1110 rc = RTVfsIoStrmReadAt(pThis->hVfsIos, pThis->offZero + offChecksum, &StoredDigest, cbChecksum, 1111 true /*fBlocking*/, NULL /*pcbRead*/); 1112 if (RT_FAILURE(rc)) 1113 return rc; 1114 if (memcmp(&StoredDigest, pTocDigest, pThis->cbHashDigest)) 1115 return VERR_XAR_TOC_DIGEST_MISMATCH; 1116 } 1117 } 1118 else if (pThis->uHashFunction != XAR_HASH_NONE) 1119 return VERR_XAR_BAD_CHECKSUM_ELEMENT; 1120 1121 /* 1122 * Check the signature, if we got one. 1123 */ 1124 /** @todo signing. */ 1125 1126 return VINF_SUCCESS; 1127 } 1128 1129 1130 /** 1131 * Reads and validates the table of content. 1132 * 1133 * @returns IPRT status code. 1134 * @param hVfsIosIn The input stream. 1135 * @param pXarHdr The XAR header. 1136 * @param pDoc The TOC XML document. 1137 * @param ppTocElem Where to return the pointer to the TOC element on 1138 * success. 1139 * @param pTocDigest Where to return the TOC digest on success. 1140 */ 1141 static int rtZipXarReadAndValidateToc(RTVFSIOSTREAM hVfsIosIn, PCXARHEADER pXarHdr, 1142 xml::Document *pDoc, xml::ElementNode const **ppTocElem, PRTZIPXARHASHDIGEST pTocDigest) 1143 { 1144 /* 1145 * Decompress it, calculating the hash while doing so. 1146 */ 1147 char *pszOutput = (char *)RTMemTmpAlloc(pXarHdr->cbTocUncompressed + 1); 1148 if (!pszOutput) 1149 return VERR_NO_TMP_MEMORY; 1150 int rc = VERR_NO_TMP_MEMORY; 1151 void *pvInput = RTMemTmpAlloc(pXarHdr->cbTocCompressed); 1152 if (pvInput) 1153 { 1154 rc = RTVfsIoStrmRead(hVfsIosIn, pvInput, pXarHdr->cbTocCompressed, true /*fBlocking*/, NULL); 1155 if (RT_SUCCESS(rc)) 1156 { 1157 rtZipXarCalcHash(pXarHdr->uHashFunction, pvInput, pXarHdr->cbTocCompressed, pTocDigest); 1158 1159 size_t cbActual; 1160 rc = RTZipBlockDecompress(RTZIPTYPE_ZLIB, 0 /*fFlags*/, 1161 pvInput, pXarHdr->cbTocCompressed, NULL, 1162 pszOutput, pXarHdr->cbTocUncompressed, &cbActual); 1163 if (RT_SUCCESS(rc) && cbActual != pXarHdr->cbTocUncompressed) 1164 rc = VERR_XAR_TOC_UNCOMP_SIZE_MISMATCH; 1165 } 1166 RTMemTmpFree(pvInput); 1167 } 1168 if (RT_SUCCESS(rc)) 1169 { 1170 pszOutput[pXarHdr->cbTocUncompressed] = '\0'; 1171 1172 /* 1173 * Parse the TOC (XML document) and do some basic validations. 1174 */ 1175 size_t cchToc = strlen(pszOutput); 1176 if ( cchToc == pXarHdr->cbTocUncompressed 1177 || cchToc + 1 == pXarHdr->cbTocUncompressed) 1178 { 1179 rc = RTStrValidateEncoding(pszOutput); 1180 if (RT_SUCCESS(rc)) 1181 { 1182 xml::XmlMemParser Parser; 1183 try 1184 { 1185 Parser.read(pszOutput, cchToc, RTCString("xar-toc.xml"), *pDoc); 1186 } 1187 catch (xml::XmlError Err) 1188 { 1189 rc = VERR_XAR_TOC_XML_PARSE_ERROR; 1190 } 1191 catch (...) 1192 { 1193 rc = VERR_NO_MEMORY; 1194 } 1195 if (RT_SUCCESS(rc)) 1196 { 1197 xml::ElementNode const *pRootElem = pDoc->getRootElement(); 1198 xml::ElementNode const *pTocElem = NULL; 1199 if (pRootElem && pRootElem->nameEquals("xar")) 1200 pTocElem = pRootElem ? pRootElem->findChildElement(NULL, "toc") : NULL; 1201 if (pTocElem) 1202 { 1203 #ifndef USE_STD_LIST_FOR_CHILDREN 1204 Assert(pRootElem->getParent() == NULL); 1205 Assert(pTocElem->getParent() == pRootElem); 1206 if ( !pTocElem->getNextSibiling() 1207 && !pTocElem->getPrevSibiling()) 1208 #endif 1209 { 1210 /* 1211 * Further parsing and validation is done after the 1212 * caller has created an file system stream instance. 1213 */ 1214 *ppTocElem = pTocElem; 1215 1216 RTMemTmpFree(pszOutput); 1217 return VINF_SUCCESS; 1218 } 1219 1220 rc = VERR_XML_TOC_ELEMENT_HAS_SIBLINGS; 1221 } 1222 else 1223 rc = VERR_XML_TOC_ELEMENT_MISSING; 1224 } 1225 } 1226 else 1227 rc = VERR_XAR_TOC_UTF8_ENCODING; 1228 } 1229 else 1230 rc = VERR_XAR_TOC_STRLEN_MISMATCH; 1231 } 1232 1233 RTMemTmpFree(pszOutput); 1234 return rc; 1235 } 1236 1237 1238 /** 1239 * Reads and validates the XAR header. 1240 * 1241 * @returns IPRT status code. 1242 * @param hVfsIosIn The input stream. 1243 * @param pXarHdr Where to return the XAR header in host byte order. 1244 */ 1245 static int rtZipXarReadAndValidateHeader(RTVFSIOSTREAM hVfsIosIn, PXARHEADER pXarHdr) 1246 { 1247 /* 1248 * Read it and check the signature. 1249 */ 1250 int rc = RTVfsIoStrmRead(hVfsIosIn, pXarHdr, sizeof(*pXarHdr), true /*fBlocking*/, NULL); 1251 if (RT_FAILURE(rc)) 1252 return rc; 1253 if (pXarHdr->u32Magic != XAR_HEADER_MAGIC) 1254 return VERR_XAR_WRONG_MAGIC; 1255 1256 /* 1257 * Correct the byte order. 1258 */ 1259 pXarHdr->cbHeader = RT_BE2H_U16(pXarHdr->cbHeader); 1260 pXarHdr->uVersion = RT_BE2H_U16(pXarHdr->uVersion); 1261 pXarHdr->cbTocCompressed = RT_BE2H_U64(pXarHdr->cbTocCompressed); 1262 pXarHdr->cbTocUncompressed = RT_BE2H_U64(pXarHdr->cbTocUncompressed); 1263 pXarHdr->uHashFunction = RT_BE2H_U32(pXarHdr->uHashFunction); 1264 1265 /* 1266 * Validate the header. 1267 */ 1268 if (pXarHdr->uVersion > XAR_HEADER_VERSION) 1269 return VERR_XAR_UNSUPPORTED_VERSION; 1270 if (pXarHdr->cbHeader < sizeof(XARHEADER)) 1271 return VERR_XAR_BAD_HDR_SIZE; 1272 if (pXarHdr->uHashFunction > XAR_HASH_MAX) 1273 return VERR_XAR_UNSUPPORTED_HASH_FUNCTION; 1274 if (pXarHdr->cbTocUncompressed < 16) 1275 return VERR_XAR_TOC_TOO_SMALL; 1276 if (pXarHdr->cbTocUncompressed > _4M) 1277 return VERR_XAR_TOC_TOO_BIG; 1278 if (pXarHdr->cbTocCompressed > _4M) 1279 return VERR_XAR_TOC_TOO_BIG_COMPRESSED; 1280 1281 /* 1282 * Skip over bytes we don't understand (could be padding). 1283 */ 1284 if (pXarHdr->cbHeader > sizeof(XARHEADER)) 1285 { 1286 rc = RTVfsIoStrmSkip(hVfsIosIn, pXarHdr->cbHeader - sizeof(XARHEADER)); 1287 if (RT_FAILURE(rc)) 1288 return rc; 1289 } 1290 1291 return VINF_SUCCESS; 1292 } 1293 1294 1295 RTDECL(int) RTZipXarFsStreamFromIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss) 1542 1296 { 1543 1297 /* … … 1556 1310 1557 1311 /* 1558 * Retain the input stream and create a new filesystem stream handle. 1559 */ 1560 PRTZIPTARFSSTREAM pThis; 1561 RTVFSFSSTREAM hVfsFss; 1562 int rc = RTVfsNewFsStream(&rtZipTarFssOps, sizeof(*pThis), NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFss, (void **)&pThis); 1312 * Read and validate the header, then uncompress the TOC. 1313 */ 1314 XARHEADER XarHdr; 1315 int rc = rtZipXarReadAndValidateHeader(hVfsIosIn, &XarHdr); 1563 1316 if (RT_SUCCESS(rc)) 1564 1317 { 1565 pThis->hVfsIos = hVfsIosIn; 1566 pThis->hVfsCurObj = NIL_RTVFSOBJ; 1567 pThis->pCurIosData = NULL; 1568 pThis->offStart = offStart; 1569 pThis->offNextHdr = offStart; 1570 pThis->fEndOfStream = false; 1571 pThis->rcFatal = VINF_SUCCESS; 1572 pThis->TarReader.enmPrevType= RTZIPTARTYPE_INVALID; 1573 pThis->TarReader.enmType = RTZIPTARTYPE_INVALID; 1574 pThis->TarReader.enmState = RTZIPTARREADERSTATE_FIRST; 1575 1576 /* Don't check if it's a TAR stream here, do that in the 1577 rtZipTarFss_Next. */ 1578 1579 *phVfsFss = hVfsFss; 1580 return VINF_SUCCESS; 1318 xml::Document *pDoc = NULL; 1319 try { pDoc = new xml::Document(); } 1320 catch (...) { } 1321 if (pDoc) 1322 { 1323 RTZIPXARHASHDIGEST TocDigest; 1324 xml::ElementNode const *pTocElem = NULL; 1325 rc = rtZipXarReadAndValidateToc(hVfsIosIn, &XarHdr, pDoc, &pTocElem, &TocDigest); 1326 if (RT_SUCCESS(rc)) 1327 { 1328 size_t offZero = RTVfsIoStrmTell(hVfsIosIn); 1329 if (offZero > 0) 1330 { 1331 /* 1332 * Create a file system stream before we continue the parsing. 1333 */ 1334 PRTZIPXARFSSTREAM pThis; 1335 RTVFSFSSTREAM hVfsFss; 1336 rc = RTVfsNewFsStream(&rtZipXarFssOps, sizeof(*pThis), NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFss, (void **)&pThis); 1337 if (RT_SUCCESS(rc)) 1338 { 1339 pThis->hVfsIos = hVfsIosIn; 1340 pThis->hVfsFile = RTVfsIoStrmToFile(hVfsIosIn); 1341 pThis->hVfsCurObj = NIL_RTVFSOBJ; 1342 pThis->pCurIosData = NULL; 1343 pThis->offStart = offStart; 1344 pThis->offZero = offZero; 1345 pThis->uHashFunction = (uint8_t)XarHdr.uHashFunction; 1346 switch (pThis->uHashFunction) 1347 { 1348 case XAR_HASH_MD5: pThis->cbHashDigest = sizeof(TocDigest.abMd5); break; 1349 case XAR_HASH_SHA1: pThis->cbHashDigest = sizeof(TocDigest.abSha1); break; 1350 default: pThis->cbHashDigest = 0; break; 1351 } 1352 pThis->fEndOfStream = false; 1353 pThis->rcFatal = VINF_SUCCESS; 1354 pThis->XarReader.pDoc = pDoc; 1355 pThis->XarReader.pToc = pTocElem; 1356 pThis->XarReader.idCurFile = 0; /* Assuming the ID numbering is from 1. */ 1357 1358 /* 1359 * Next validation step. 1360 */ 1361 rc = rtZipXarValidateTocPart2(pThis, &XarHdr, &TocDigest); 1362 if (RT_SUCCESS(rc)) 1363 { 1364 *phVfsFss = hVfsFss; 1365 return VINF_SUCCESS; 1366 } 1367 1368 RTVfsFsStrmRelease(hVfsFss); 1369 return rc; 1370 } 1371 } 1372 else 1373 rc = (int)offZero; 1374 } 1375 delete pDoc; 1376 } 1377 else 1378 rc = VERR_NO_MEMORY; 1581 1379 } 1582 1380 -
trunk/src/VBox/Runtime/common/zip/zip.cpp
r47516 r48780 1917 1917 1918 1918 case RTZIPTYPE_ZLIB: 1919 { 1920 #ifdef RTZIP_USE_ZLIB 1921 AssertReturn(cbSrc == (uInt)cbSrc, VERR_TOO_MUCH_DATA); 1922 AssertReturn(cbDst == (uInt)cbDst, VERR_OUT_OF_RANGE); 1923 1924 z_stream ZStrm; 1925 RT_ZERO(ZStrm); 1926 ZStrm.next_in = (Bytef *)pvSrc; 1927 ZStrm.avail_in = (uInt)cbSrc; 1928 ZStrm.next_out = (Bytef *)pvDst; 1929 ZStrm.avail_out = (uInt)cbDst; 1930 1931 int rc = inflateInit(&ZStrm); 1932 if (RT_UNLIKELY(rc != Z_OK)) 1933 return zipErrConvertFromZlib(rc, false /*fCompressing*/); 1934 rc = inflate(&ZStrm, Z_FINISH); 1935 if (rc != Z_STREAM_END) 1936 { 1937 inflateEnd(&ZStrm); 1938 if ((rc == Z_BUF_ERROR && ZStrm.avail_in == 0) || rc == Z_NEED_DICT) 1939 return VERR_ZIP_CORRUPTED; 1940 if (rc == Z_BUF_ERROR) 1941 return VERR_BUFFER_OVERFLOW; 1942 AssertReturn(rc < Z_OK, VERR_GENERAL_FAILURE); 1943 return zipErrConvertFromZlib(rc, false /*fCompressing*/); 1944 } 1945 rc = inflateEnd(&ZStrm); 1946 if (rc != Z_OK) 1947 return zipErrConvertFromZlib(rc, false /*fCompressing*/); 1948 1949 if (pcbSrcActual) 1950 *pcbSrcActual = ZStrm.avail_in - cbSrc; 1951 if (pcbDstActual) 1952 *pcbDstActual = ZStrm.total_out; 1953 break; 1954 #else 1955 return VERR_NOT_SUPPORTED; 1956 #endif 1957 } 1958 1919 1959 case RTZIPTYPE_BZLIB: 1920 1960 return VERR_NOT_SUPPORTED;
Note:
See TracChangeset
for help on using the changeset viewer.