static int rtTarCreateHeaderRecord(PRTTARRECORD pRecord, const char *pszSrcName, uint64_t cbSize, RTUID uid, RTGID gid, RTFMODE fmode, int64_t mtime) { /** @todo check for field overflows. */ /* Fill the header record */ // RT_ZERO(pRecord); - done by the caller. /** @todo use RTStrCopy */ size_t cb = RTStrPrintf(pRecord->h.name, sizeof(pRecord->h.name), "%s", pszSrcName); if (cb < strlen(pszSrcName)) return VERR_BUFFER_OVERFLOW; RTStrPrintf(pRecord->h.mode, sizeof(pRecord->h.mode), "%0.7o", fmode); RTStrPrintf(pRecord->h.uid, sizeof(pRecord->h.uid), "%0.7o", uid); RTStrPrintf(pRecord->h.gid, sizeof(pRecord->h.gid), "%0.7o", gid); rtTarSizeToRec(pRecord, cbSize); RTStrPrintf(pRecord->h.mtime, sizeof(pRecord->h.mtime), "%0.11llo", mtime); RTStrPrintf(pRecord->h.magic, sizeof(pRecord->h.magic), "ustar "); RTStrPrintf(pRecord->h.uname, sizeof(pRecord->h.uname), "someone"); RTStrPrintf(pRecord->h.gname, sizeof(pRecord->h.gname), "someone"); pRecord->h.linkflag = LF_NORMAL; /* Create the checksum out of the new header */ int32_t iUnsignedChksum, iSignedChksum; if (rtZipTarCalcChkSum((PCRTZIPTARHDR)pRecord, &iUnsignedChksum, &iSignedChksum)) return VERR_TAR_END_OF_FILE; /* Format the checksum */ RTStrPrintf(pRecord->h.chksum, sizeof(pRecord->h.chksum), "%0.7o", iUnsignedChksum); return VINF_SUCCESS; }
/** * Validates the TAR header. * * @returns VINF_SUCCESS if valid, VERR_TAR_ZERO_HEADER if all zeros, and * the appropriate VERR_TAR_XXX otherwise. * @param pTar The TAR header. * @param penmType Where to return the type of header on success. */ static int rtZipTarHdrValidate(PCRTZIPTARHDR pTar, PRTZIPTARTYPE penmType) { /* * Calc the checksum first since this enables us to detect zero headers. */ int32_t i32ChkSum; int32_t i32ChkSumSignedAlt; if (rtZipTarCalcChkSum(pTar, &i32ChkSum, &i32ChkSumSignedAlt)) return VERR_TAR_ZERO_HEADER; /* * Read the checksum field and match the checksums. */ int64_t i64HdrChkSum; int rc = rtZipTarHdrFieldToNum(pTar->Common.chksum, sizeof(pTar->Common.chksum), true /*fOctalOnly*/, &i64HdrChkSum); if (RT_FAILURE(rc)) return VERR_TAR_BAD_CHKSUM_FIELD; if ( i32ChkSum != i64HdrChkSum && i32ChkSumSignedAlt != i64HdrChkSum) /** @todo test this */ return VERR_TAR_CHKSUM_MISMATCH; /* * Detect the TAR type. */ RTZIPTARTYPE enmType; if ( pTar->Common.magic[0] == 'u' && pTar->Common.magic[1] == 's' && pTar->Common.magic[2] == 't' && pTar->Common.magic[3] == 'a' && pTar->Common.magic[4] == 'r') { /** @todo detect star headers */ if ( pTar->Common.magic[5] == '\0' && pTar->Common.version[0] == '0' && pTar->Common.version[1] == '0') enmType = RTZIPTARTYPE_POSIX; else if ( pTar->Common.magic[5] == ' ' && pTar->Common.version[0] == ' ' && pTar->Common.version[1] == '\0') enmType = RTZIPTARTYPE_GNU; else return VERR_TAR_NOT_USTAR_V00; } else enmType = RTZIPTARTYPE_ANCIENT; *penmType = enmType; /* * Perform some basic checks. */ switch (enmType) { case RTZIPTARTYPE_POSIX: if ( !RT_C_IS_ALNUM(pTar->Common.typeflag) && !pTar->Common.typeflag == '\0') return VERR_TAR_UNKNOWN_TYPE_FLAG; break; case RTZIPTARTYPE_GNU: switch (pTar->Common.typeflag) { case RTZIPTAR_TF_OLDNORMAL: case RTZIPTAR_TF_NORMAL: case RTZIPTAR_TF_CONTIG: case RTZIPTAR_TF_DIR: case RTZIPTAR_TF_CHR: case RTZIPTAR_TF_BLK: case RTZIPTAR_TF_LINK: case RTZIPTAR_TF_SYMLINK: case RTZIPTAR_TF_FIFO: break; case RTZIPTAR_TF_GNU_LONGLINK: case RTZIPTAR_TF_GNU_LONGNAME: break; case RTZIPTAR_TF_GNU_DUMPDIR: case RTZIPTAR_TF_GNU_MULTIVOL: case RTZIPTAR_TF_GNU_SPARSE: case RTZIPTAR_TF_GNU_VOLDHR: /** @todo Implement full GNU TAR support. .*/ return VERR_TAR_UNSUPPORTED_GNU_HDR_TYPE; default: return VERR_TAR_UNKNOWN_TYPE_FLAG; } break; case RTZIPTARTYPE_ANCIENT: switch (pTar->Common.typeflag) { case RTZIPTAR_TF_OLDNORMAL: case RTZIPTAR_TF_NORMAL: case RTZIPTAR_TF_CONTIG: case RTZIPTAR_TF_DIR: case RTZIPTAR_TF_LINK: case RTZIPTAR_TF_SYMLINK: case RTZIPTAR_TF_FIFO: break; default: return VERR_TAR_UNKNOWN_TYPE_FLAG; } break; default: /* shut up gcc */ AssertFailedReturn(VERR_INTERNAL_ERROR_3); } return VINF_SUCCESS; }