Exemplo n.º 1
0
const char *zip_get_name(ar_archive *ar)
{
    ar_archive_zip *zip = (ar_archive_zip *)ar;
    if (!zip->entry.name) {
        struct zip_entry entry;
        char *name;

        if (zip->dir.end_offset >= 0) {
            if (!ar_seek(ar->stream, ar->entry_offset, SEEK_SET))
                return NULL;
            if (!zip_parse_directory_entry(zip, &entry))
                return NULL;
            if (!ar_seek(ar->stream, ar->entry_offset + ZIP_DIR_ENTRY_FIXED_SIZE, SEEK_SET))
                return NULL;
        }
        else {
            if (!ar_seek(ar->stream, zip->entry.offset, SEEK_SET))
                return NULL;
            if (!zip_parse_local_file_entry(zip, &entry))
                return NULL;
            if (!ar_seek(ar->stream, ar->entry_offset + ZIP_LOCAL_ENTRY_FIXED_SIZE, SEEK_SET))
                return NULL;
        }

        name = malloc(entry.namelen + 1);
        if (!name || ar_read(ar->stream, name, entry.namelen) != entry.namelen) {
            free(name);
            return NULL;
        }
        name[entry.namelen] = '\0';

        if ((entry.flags & (1 << 11))) {
            zip->entry.name = name;
        }
        else {
            zip->entry.name = ar_conv_dos_to_utf8(name);
            free(name);
        }
        /* normalize path separators */
        if (zip->entry.name) {
            char *p = zip->entry.name;
            while ((p = strchr(p, '\\')) != NULL) {
                *p = '/';
            }
        }
    }
    return zip->entry.name;
}
Exemplo n.º 2
0
static bool tar_parse_entry(ar_archive *ar, off64_t offset)
{
    ar_archive_tar *tar = (ar_archive_tar *)ar;
    char *longname;

    if (!ar_seek(ar->stream, offset, SEEK_SET)) {
        warn("Couldn't seek to offset %" PRIi64, offset);
        return false;
    }
    if (!tar_parse_header(tar)) {
        warn("Invalid tar header data @%" PRIi64, offset);
        return false;
    }
    if (!tar->entry.checksum) {
        ar->at_eof = true;
        return false;
    }

    ar->entry_offset = offset;
    ar->entry_offset_next = offset + TAR_BLOCK_SIZE + (tar->entry.filesize + TAR_BLOCK_SIZE - 1) / TAR_BLOCK_SIZE * TAR_BLOCK_SIZE;
    ar->entry_size_uncompressed = tar->entry.filesize;
    ar->entry_filetime = tar->entry.mtime;
    tar->bytes_done = 0;

    switch (tar->entry.filetype) {
    case TYPE_FILE:
    case TYPE_FILE_OLD:
        return true;
    case TYPE_DIRECTORY:
        log("Skipping directory entry \"%s\"", tar_get_name(ar));
        return tar_parse_entry(ar, ar->entry_offset_next);
    case TYPE_LONGNAME:
        longname = malloc(tar->entry.filesize + 1);
        if (!longname) {
            log("Falling back to the short filename on OOM");
            return tar_parse_entry(ar, ar->entry_offset_next);
        }
        if (!ar_entry_uncompress(ar, longname, tar->entry.filesize)) {
            free(longname);
            return false;
        }
        longname[tar->entry.filesize] = '\0';
        if (!tar_parse_entry(ar, ar->entry_offset_next)) {
            free(longname);
            return false;
        }
        ar->entry_offset = offset;
        /* name could be in any encoding, assume UTF-8 or whatever (DOS) */
        if (ar_is_valid_utf8(longname)) {
            tar->entry.name = longname;
        }
        else {
            tar->entry.name = ar_conv_dos_to_utf8(longname);
            free(longname);
        }
        return true;
    default:
        warn("Unknown entry type '%c'", tar->entry.filetype);
        return true;
    }
}