Archive-Tar-Builder

 view release on metacpan or  search on metacpan

src/b_header.c  view on Meta::CPAN

    }

    return sum;
}

static inline int is_big_endian() {
    uint16_t num = 1;

    return ((uint8_t *)&num)[1];
}

static inline void encode_base256_value(unsigned char *field, size_t len, uint64_t value) {
    size_t i;
    size_t value_size = sizeof(value);
    size_t offset     = len - value_size;

    for (i=0; i<value_size; i++) {
        int from_i = is_big_endian()? i: value_size - i - 1;

        field[offset + i] = ((uint8_t *)&value)[from_i];
    }

    /*
     * Set the uppermost bit to indicate a base256-encoded size value.
     */
    field[0] |= 0x80;
}

static inline void encode_checksum(b_header_block *block) {
    memcpy(  block->checksum, B_HEADER_EMPTY_CHECKSUM, B_HEADER_CHECKSUM_SIZE);
    snprintf(block->checksum, B_HEADER_CHECKSUM_LEN,   B_HEADER_CHECKSUM_FORMAT, checksum(block));

    block->checksum[7] = ' ';
}

size_t b_header_compute_pax_length(b_string *path, const char *record) {
    size_t len, i;
    char shortbuf[32];

    len = b_string_len(path);

    /* snprintf returns the number of characters (excluding the NUL) we would
     * have written had space been available.  Iterate three times to be sure
     * the value is stable.
     */
    for (i=0; i<3; i++) {
        len = snprintf(shortbuf, sizeof(shortbuf), "%d %s=%s\n", len, record, path->str);
    }

    return len;
}


b_header_block *b_header_encode_block(b_header_block *block, b_header *header) {
    if (header->suffix) {
        strncpy(block->suffix, header->suffix->str, 100);
    }

    snprintf(block->mode, B_HEADER_MODE_SIZE, B_HEADER_MODE_FORMAT, header->mode & S_IPERM);
    snprintf(block->uid,  B_HEADER_UID_SIZE,  B_HEADER_UID_FORMAT,  header->uid);
    snprintf(block->gid,  B_HEADER_GID_SIZE,  B_HEADER_GID_FORMAT,  header->gid);

    if (header->size >= B_HEADER_MAX_FILE_SIZE) {
        encode_base256_value(block->size, B_HEADER_SIZE_SIZE, header->size);
    } else {
        snprintf(block->size, B_HEADER_SIZE_SIZE, B_HEADER_LONG_SIZE_FORMAT, header->size);
    }

    snprintf(block->mtime, B_HEADER_MTIME_SIZE, B_HEADER_MTIME_FORMAT, header->mtime);

    block->linktype = header->linktype;

    if (header->linkdest != NULL) {
        strncpy(block->linkdest, header->linkdest->str, B_HEADER_LINKDEST_SIZE);
    }

    memcpy(block->magic, B_HEADER_MAGIC, B_HEADER_MAGIC_SIZE);

    if (header->user != NULL) {
        strncpy(block->user, header->user->str, B_HEADER_USER_SIZE);
    }

    if (header->group != NULL) {
        strncpy(block->group, header->group->str, B_HEADER_GROUP_SIZE);
    }

    if (header->major && header->minor) {
        snprintf(block->major, B_HEADER_MAJOR_SIZE, B_HEADER_MAJOR_FORMAT, header->major);
        snprintf(block->minor, B_HEADER_MINOR_SIZE, B_HEADER_MINOR_FORMAT, header->minor);
    }

    if (header->prefix) {
        strncpy(block->prefix, header->prefix->str, B_HEADER_PREFIX_SIZE);
    }

    encode_checksum(block);

    return block;
}

b_header_block *b_header_encode_longlink_block(b_header_block *block, b_string *path, int type) {
    memcpy(  block->magic,  B_HEADER_MAGIC,       B_HEADER_MAGIC_SIZE);
    snprintf(block->suffix, B_HEADER_SUFFIX_SIZE, B_HEADER_LONGLINK_PATH);
    snprintf(block->size,   B_HEADER_SIZE_SIZE,   B_HEADER_INT_SIZE_FORMAT,   b_string_len(path));

    block->linktype = type;

    encode_checksum(block);

    return block;
}

b_header_block *b_header_encode_pax_block(b_header_block *block, b_header *header, b_string *path) {
    size_t pax_len = b_header_compute_pax_length(path, "path");

    if (header->linkdest)
        pax_len += b_header_compute_pax_length(header->linkdest, "linkpath");

	b_header_encode_block(block, header);

    snprintf(block->size, B_HEADER_SIZE_SIZE, B_HEADER_LONG_SIZE_FORMAT, (unsigned long long)pax_len);



( run in 0.562 second using v1.01-cache-2.11-cpan-5735350b133 )