Exemple #1
0
off64_t zip_find_end_of_central_directory(ar_stream *stream)
{
    uint8_t data[512];
    off64_t filesize;
    int fromend = 0;
    int count, i;

    if (!ar_seek(stream, 0, SEEK_END))
        return -1;
    filesize = ar_tell(stream);

    while (fromend < UINT16_MAX + ZIP_END_OF_CENTRAL_DIR_SIZE && fromend < filesize) {
        count = (int)(filesize - fromend < sizeof(data) ? filesize - fromend : sizeof(data));
        fromend += count;
        if (count < ZIP_END_OF_CENTRAL_DIR_SIZE)
            return -1;
        if (!ar_seek(stream, -fromend, SEEK_END))
            return -1;
        if (ar_read(stream, data, count) != (size_t)count)
            return -1;
        for (i = count - ZIP_END_OF_CENTRAL_DIR_SIZE; i >= 0; i--) {
            if (uint32le(data + i) == SIG_END_OF_CENTRAL_DIRECTORY)
                return filesize - fromend + i;
        }
        fromend -= ZIP_END_OF_CENTRAL_DIR_SIZE - 1;
    }

    return -1;
}
Exemple #2
0
bool zip_parse_directory_entry(ar_archive_zip *zip, struct zip_entry *entry)
{
    uint8_t data[ZIP_DIR_ENTRY_FIXED_SIZE];

    if (ar_read(zip->super.stream, data, sizeof(data)) != sizeof(data))
        return false;

    entry->signature = uint32le(data + 0);
    entry->version = uint16le(data + 4);
    entry->min_version = uint16le(data + 6);
    entry->flags = uint16le(data + 8);
    entry->method = uint16le(data + 10);
    entry->dosdate = uint32le(data + 12);
    entry->crc = uint32le(data + 16);
    entry->datasize = uint32le(data + 20);
    entry->uncompressed = uint32le(data + 24);
    entry->namelen = uint16le(data + 28);
    entry->extralen = uint16le(data + 30);
    entry->commentlen = uint16le(data + 32);
    entry->disk = uint16le(data + 34);
    entry->attr_internal = uint16le(data + 36);
    entry->attr_external = uint32le(data + 38);
    entry->header_offset = uint32le(data + 42);

    if (entry->signature != SIG_CENTRAL_DIRECTORY)
        return false;

    return zip_parse_extra_fields(zip, entry);
}
Exemple #3
0
int
buf_fill(void)
{
	int cnt;
	static int fini = 0;

	if (fini)
		return(0);

	for (;;) {
		/*
		 * try to fill the buffer. on error the next archive volume is
		 * opened and we try again.
		 */
		if ((cnt = ar_read(buf, blksz)) > 0) {
			bufpt = buf;
			bufend = buf + cnt;
			rdcnt += cnt;
			return(cnt);
		}

		/*
		 * errors require resync, EOF goes to next archive
		 */
		if (cnt < 0)
			break;
		if (ar_next() < 0) {
			fini = 1;
			return(0);
		}
		rdcnt = 0;
	}
	exit_val = 1;
	return(-1);
}
Exemple #4
0
int
rd_sync(void)
{
	int errcnt = 0;
	int res;

	/*
	 * if the user says bail out on first fault, we are out of here...
	 */
	if (maxflt == 0)
		return(-1);
	if (act == APPND) {
		paxwarn(1, "Unable to append when there are archive read errors.");
		return(-1);
	}

	/*
	 * poke at device and try to get past media error
	 */
	if (ar_rdsync() < 0) {
		if (ar_next() < 0)
			return(-1);
		else
			rdcnt = 0;
	}

	for (;;) {
		if ((res = ar_read(buf, blksz)) > 0) {
			/*
			 * All right! got some data, fill that buffer
			 */
			bufpt = buf;
			bufend = buf + res;
			rdcnt += res;
			return(0);
		}

		/*
		 * Oh well, yet another failed read...
		 * if error limit reached, ditch. o.w. poke device to move past
		 * bad media and try again. if media is badly damaged, we ask
		 * the poor (and upset user at this point) for the next archive
		 * volume. remember the goal on reads is to get the most we
		 * can extract out of the archive.
		 */
		if ((maxflt > 0) && (++errcnt > maxflt))
			paxwarn(0,"Archive read error limit (%d) reached",maxflt);
		else if (ar_rdsync() == 0)
			continue;
		if (ar_next() < 0)
			break;
		rdcnt = 0;
		errcnt = 0;
	}
	return(-1);
}
Exemple #5
0
off64_t zip_find_next_local_file_entry(ar_stream *stream, off64_t offset)
{
    uint8_t data[512];
    int count, i;

    if (!ar_seek(stream, offset, SEEK_SET))
        return false;
    count = (int)ar_read(stream, data, sizeof(data));

    while (count >= ZIP_LOCAL_ENTRY_FIXED_SIZE) {
        for (i = 0; i < count - 4; i++) {
            if (uint32le(data + i) == SIG_LOCAL_FILE_HEADER)
                return offset + i;
        }
        memmove(data, data + count - 4, count);
        offset += count - 4;
        count = (int)ar_read(stream, data + 4, sizeof(data) - 4) + 4;
    }

    return -1;
}
Exemple #6
0
static bool tar_uncompress(ar_archive *ar, void *buffer, size_t count)
{
    ar_archive_tar *tar = (ar_archive_tar *)ar;
    if (count > ar->entry_size_uncompressed - tar->bytes_done) {
        warn("Requesting too much data (%" PRIuPTR " < %" PRIuPTR ")", ar->entry_size_uncompressed - tar->bytes_done, count);
        return false;
    }
    if (ar_read(ar->stream, buffer, count) != count) {
        warn("Unexpected EOF in stored data");
        return false;
    }
    tar->bytes_done += count;
    return true;
}
Exemple #7
0
static bool rar_copy_stored(ar_archive_rar *rar, void *buffer, size_t count)
{
    if (count > rar->progr.data_left) {
        warn("Requesting too much data (%" PRIuPTR " < %" PRIuPTR ")", rar->progr.data_left, count);
        return false;
    }
    if (ar_read(rar->super.stream, buffer, count) != count) {
        warn("Unexpected EOF in stored data");
        return false;
    }
    rar->progr.data_left -= count;
    rar->progr.bytes_done += count;
    return true;
}
Exemple #8
0
static bool rar_copy_stored(ar_archive_rar *rar, void *buffer, size_t count)
{
    if (count > rar->progress.data_left) {
        warn("Unexpected EOS in stored data");
        return false;
    }
    if (ar_read(rar->super.stream, buffer, count) != count) {
        warn("Unexpected EOF in stored data");
        return false;
    }
    rar->progress.data_left -= count;
    rar->progress.bytes_done += count;
    return true;
}
Exemple #9
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;
}
Exemple #10
0
ar_archive *ar_open_rar_archive(ar_stream *stream)
{
    char signature[7];
    if (ar_read(stream, signature, sizeof(signature)) != sizeof(signature))
        return NULL;
    if (memcmp(signature, "Rar!\x1A\x07\x00", 7) != 0) {
        if (memcmp(signature, "Rar!\x1A\x07\x01", 7) == 0)
            warn("RAR 5 format isn't supported");
        else if (memcmp(signature, "RE~^", 4) == 0)
            warn("Ancient RAR format isn't supported");
        else if (memcmp(signature, "MZ", 2) == 0 || memcmp(signature, "\x7F\x45LF", 4) == 0)
            warn("SFX archives aren't supported");
        return NULL;
    }

    return ar_open_archive(stream, sizeof(ar_archive_rar), rar_close, rar_parse_entry, rar_get_name, rar_get_name_w, rar_uncompress);
}
Exemple #11
0
off64_t zip_find_end_of_last_directory_entry(ar_stream *stream, struct zip_eocd64 *eocd)
{
    uint8_t data[ZIP_DIR_ENTRY_FIXED_SIZE];
    uint64_t i;

    if (!ar_seek(stream, eocd->dir_offset, SEEK_SET))
        return -1;
    for (i = 0; i < eocd->numentries; i++) {
        if (ar_read(stream, data, sizeof(data)) != sizeof(data))
            return -1;
        if (uint32le(data + 0) != SIG_CENTRAL_DIRECTORY)
            return -1;
        if (!ar_skip(stream, uint16le(data + 28) + uint16le(data + 30) + uint16le(data + 32)))
            return -1;
    }

    return ar_tell(stream);
}
Exemple #12
0
static bool zip_parse_extra_fields(ar_archive_zip *zip, struct zip_entry *entry)
{
    uint8_t *extra;
    uint16_t idx;

    if (!entry->extralen)
        return true;

    /* read ZIP64 values where needed */
    if (!ar_skip(zip->super.stream, entry->namelen))
        return false;
    extra = malloc(entry->extralen);
    if (!extra || ar_read(zip->super.stream, extra, entry->extralen) != entry->extralen) {
        free(extra);
        return false;
    }
    for (idx = 0; idx + 4 < entry->extralen; idx += 4 + uint16le(&extra[idx + 2])) {
        if (uint16le(&extra[idx]) == 0x0001) {
            uint16_t size = uint16le(&extra[idx + 2]);
            uint16_t offset = 0;
            if (entry->uncompressed == UINT32_MAX && offset + 8 <= size) {
                entry->uncompressed = uint64le(&extra[idx + 4 + offset]);
                offset += 8;
            }
            if (entry->datasize == UINT32_MAX && offset + 8 <= size) {
                entry->datasize = uint64le(&extra[idx + 4 + offset]);
                offset += 8;
            }
            if (entry->header_offset == UINT32_MAX && offset + 8 <= size) {
                entry->header_offset = (off64_t)uint64le(&extra[idx + 4 + offset]);
                offset += 8;
            }
            if (entry->disk == UINT16_MAX && offset + 4 <= size) {
                entry->disk = uint32le(&extra[idx + 4 + offset]);
                offset += 4;
            }
            break;
        }
    }
    free(extra);

    return true;
}
Exemple #13
0
bool zip_parse_local_file_entry(ar_archive_zip *zip, struct zip_entry *entry)
{
    uint8_t data[ZIP_LOCAL_ENTRY_FIXED_SIZE];

    if (ar_read(zip->super.stream, data, sizeof(data)) != sizeof(data))
        return false;

    memset(entry, 0, sizeof(*entry));
    entry->signature = uint32le(data + 0);
    entry->version = uint16le(data + 4);
    entry->flags = uint16le(data + 6);
    entry->method = uint16le(data + 8);
    entry->dosdate = uint32le(data + 10);
    entry->crc = uint32le(data + 14);
    entry->datasize = uint32le(data + 18);
    entry->uncompressed = uint32le(data + 22);
    entry->namelen = uint16le(data + 26);
    entry->extralen = uint16le(data + 28);

    if (entry->signature != SIG_LOCAL_FILE_HEADER)
        return false;

    return zip_parse_extra_fields(zip, entry);
}
Exemple #14
0
int ar_read_int(int fd){
    int val = 0;
    ar_read(fd, (char *)&val, sizeof(int));
    return val;
}
Exemple #15
0
static SRes CSeekStream_Read(void *p, void *data, size_t *size)
{
    struct CSeekStream *stm = p;
    *size = ar_read(stm->stream, data, *size);
    return SZ_OK;
}
Exemple #16
0
int
appnd_start(off_t skcnt)
{
	int res;
	off_t cnt;

	if (exit_val != 0) {
		paxwarn(0, "Cannot append to an archive that may have flaws.");
		return(-1);
	}
	/*
	 * if the user did not specify a write blocksize, inherit the size used
	 * in the last archive volume read. (If a is set we still use rdblksz
	 * until next volume, cannot shift sizes within a single volume).
	 */
	if (!wrblksz)
		wrblksz = blksz = rdblksz;
	else
		blksz = rdblksz;

	/*
	 * make sure that this volume allows appends
	 */
	if (ar_app_ok() < 0)
		return(-1);

	/*
	 * Calculate bytes to move back and move in front of record where we
	 * need to start writing from. Remember we have to add in any padding
	 * that might be in the buffer after the trailer in the last block. We
	 * travel skcnt + padding ROUNDED UP to blksize.
	 */
	skcnt += bufend - bufpt;
	if ((cnt = (skcnt/blksz) * blksz) < skcnt)
		cnt += blksz;
	if (ar_rev((off_t)cnt) < 0)
		goto out;

	/*
	 * We may have gone too far if there is valid data in the block we are
	 * now in front of, read up the block and position the pointer after
	 * the valid data.
	 */
	if ((cnt -= skcnt) > 0) {
		/*
		 * watch out for stupid tape drives. ar_rev() will set rdblksz
		 * to be real physical blocksize so we must loop until we get
		 * the old rdblksz (now in blksz). If ar_rev() fouls up the
		 * determination of the physical block size, we will fail.
		 */
		bufpt = buf;
		bufend = buf + blksz;
		while (bufpt < bufend) {
			if ((res = ar_read(bufpt, rdblksz)) <= 0)
				goto out;
			bufpt += res;
		}
		if (ar_rev((off_t)(bufpt - buf)) < 0)
			goto out;
		bufpt = buf + cnt;
		bufend = buf + blksz;
	} else {
		/*
		 * buffer is empty
		 */
		bufend = buf + blksz;
		bufpt = buf;
	}
	rdblksz = blksz;
	rdcnt -= skcnt;
	wrcnt = 0;

	/*
	 * At this point we are ready to write. If the device requires special
	 * handling to write at a point were previously recorded data resides,
	 * that is handled in ar_set_wr(). From now on we operate under normal
	 * ARCHIVE mode (write) conditions
	 */
	if (ar_set_wr() < 0)
		return(-1);
	act = ARCHIVE;
	return(0);

    out:
	paxwarn(1, "Unable to rewrite archive trailer, cannot append.");
	return(-1);
}
/**
 * Read sound to buffer with size of buffer by using Read function of AudioRecord class
 *
 * @param  void* 		buffer
 * @param  int			size
 *
 * @return int
 */
int AndroidAudioRecord::read(void* buffer, int size) {
    if (mAudioRecord && ar_read) {
	return ar_read(mAudioRecord, buffer, size);
    }
    return 0;
}
Exemple #18
0
bool zip_parse_end_of_central_directory(ar_stream *stream, struct zip_eocd64 *eocd)
{
    uint8_t data[56];
    if (ar_read(stream, data, ZIP_END_OF_CENTRAL_DIR_SIZE) != ZIP_END_OF_CENTRAL_DIR_SIZE)
        return false;

    eocd->signature = uint32le(data + 0);
    eocd->diskno = uint16le(data + 4);
    eocd->diskno_dir = uint16le(data + 6);
    eocd->numentries_disk = uint16le(data + 8);
    eocd->numentries = uint16le(data + 10);
    eocd->dir_size = uint32le(data + 12);
    eocd->dir_offset = uint32le(data + 16);
    eocd->commentlen = uint16le(data + 20);

    if (eocd->signature != SIG_END_OF_CENTRAL_DIRECTORY)
        return false;

    /* try to locate the ZIP64 end of central directory */
    if (!ar_skip(stream, -42))
        return eocd->dir_size < 20;
    if (ar_read(stream, data, 20) != 20)
        return false;
    if (uint32le(data + 0) != SIG_END_OF_CENTRAL_DIRECTORY_64_LOCATOR)
        return true;
    if ((eocd->diskno != UINT16_MAX && uint32le(data + 4) != eocd->diskno) || uint32le(data + 16) != 1) {
        warn("Archive spanning isn't supported");
        return false;
    }
    if (!ar_seek(stream, (off64_t)uint64le(data + 8), SEEK_SET))
        return false;
    if (ar_read(stream, data, 56) != 56)
        return false;

    /* use data from ZIP64 end of central directory (when necessary) */
    eocd->signature = uint32le(data + 0);
    eocd->version = uint16le(data + 12);
    eocd->min_version = uint16le(data + 14);
    if (eocd->diskno == UINT16_MAX)
        eocd->diskno = uint32le(data + 16);
    if (eocd->diskno_dir == UINT16_MAX)
        eocd->diskno_dir = uint32le(data + 20);
    if (eocd->numentries_disk == UINT16_MAX)
        eocd->numentries_disk = uint64le(data + 24);
    if (eocd->numentries == UINT16_MAX)
        eocd->numentries = uint64le(data + 32);
    if (eocd->dir_size == UINT32_MAX)
        eocd->dir_size = uint64le(data + 40);
    if (eocd->dir_offset == UINT32_MAX)
        eocd->dir_offset = (off64_t)uint64le(data + 48);

    if (eocd->signature != SIG_END_OF_CENTRAL_DIRECTORY_64)
        return false;
    if (eocd->diskno != eocd->diskno_dir || eocd->numentries != eocd->numentries_disk) {
        warn("Archive spanning isn't supported");
        return false;
    }
    if (uint64le(data + 4) > 44)
        log("ZIP64 extensible data sector present @" PRIi64, ar_tell(stream));

    return true;
}
Exemple #19
0
int ar_read_short(int fd){
    short val = 0;

    ar_read(fd, (char *)&val, sizeof(short));
    return val;
}