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; }
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); }
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); }
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); }
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; }
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; }
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; }
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; }
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; }
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); }
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); }
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; }
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); }
int ar_read_int(int fd){ int val = 0; ar_read(fd, (char *)&val, sizeof(int)); return val; }
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; }
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; }
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; }
int ar_read_short(int fd){ short val = 0; ar_read(fd, (char *)&val, sizeof(short)); return val; }