Example #1
0
File: tar.cpp Project: mcenirm/vbox
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;
}
Example #2
0
/**
 * 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;
}