// caller should free static int desr_read_header(const cdsl_deserializer_t* self, cdsl_serializeHeader_t* header) { if(self == NULL) { return ERR_INV_PARAM; } file_deserializer_t* desr = container_of(self, file_deserializer_t, handle); uint16_t sof = 0; if(desr->fd <= 0) { return ERR_INV_PARAM; } do { if(F_READ(desr->fd, &sof, sizeof(uint16_t)) <= 0) { // fail to find start of file desr->is_eos_reached = TRUE; return ERR_RD_OP_FAIL; } } while(sof != SERIALIZER_START_OF_FILE); struct deserializer_header desr_header; if(F_READ(desr->fd, &desr_header, sizeof(struct deserializer_header)) <= 0) { // fail to read header desr->is_eos_reached = TRUE; return ERR_RD_OP_FAIL; } desr->has_next = (desr_header.has_next == HAS_NEXT); MEMCPY(header, &desr_header, sizeof(cdsl_serializeHeader_t)); return OK; }
static void* desr_get_next(const cdsl_deserializer_t* self, cdsl_serializeNode_t* nodep, size_t nsz, const cdsl_memoryMngt_t* m_mngt) { if(self == NULL || m_mngt == NULL) { return NULL; } file_deserializer_t* desr = container_of(self, file_deserializer_t, handle); if(desr->fd < 0) { desr->is_eos_reached = TRUE; return NULL; } if(F_READ(desr->fd, nodep, nsz) < 0) { desr->is_eos_reached = TRUE; return NULL; } size_t node_hole_size = 0; // if serialized data doesn't contain space which tree node struct is inserted into, \ then allocate more size for that purpose if(!(nodep->flags & EMBEDDED_MSK)) { node_hole_size = nsz; } void* data = NULL; if(nodep->d_size > 0) { uint8_t ext_sz = nodep->d_offset + offsetof(cdsl_serializeNode_t, flags) - nsz; if(ext_sz > 0) { uint8_t _readout_buffer[ext_sz]; if(F_READ(desr->fd, _readout_buffer, ext_sz) < 0) { desr->is_eos_reached = TRUE; return NULL; } } data = m_mngt->alloc(nodep->d_size + node_hole_size); if (F_READ(desr->fd, &data[node_hole_size], nodep->d_size) < 0) { desr->is_eos_reached = TRUE; goto FREE_AND_RETURN_NULL; } } struct deserializer_delim node_delim; if(F_READ(desr->fd, &node_delim, sizeof(struct deserializer_delim)) < 0) { desr->is_eos_reached = TRUE; goto FREE_AND_RETURN_NULL; } if(node_delim.ser_delim.delim != SERIALIZER_DELIM) { goto FREE_AND_RETURN_NULL; } if(node_delim.ser_delim.node_chs != serializer_calcNodeChecksum(nodep, data)) { goto FREE_AND_RETURN_NULL; } desr->has_next = (node_delim.has_next == HAS_NEXT); return data; FREE_AND_RETURN_NULL: if(data) m_mngt->free(data); return NULL; }
static int desr_read_tail(const cdsl_deserializer_t* self, cdsl_serializeTail_t* tailp) { if(!self || !tailp) { return ERR_INV_PARAM; } file_deserializer_t* desr = container_of(self, file_deserializer_t, handle); if(desr->fd <= 0) { return ERR_INV_PARAM; } if(F_READ(desr->fd, tailp, sizeof(cdsl_serializeTail_t))) { return ERR_RD_OP_FAIL; } return OK; }
/* =========================================================================== Read a byte from a gz_stream; update next_in and avail_in. Return EOF for end of file. IN assertion: the stream s has been sucessfully opened for reading. */ static int get_byte( gz_stream *s) { if (s->z_eof) return EOF; if (s->stream.avail_in == 0) { s->stream.avail_in = F_READ(s->inbuf, 1, Z_BUFSIZE, s->file); if (s->stream.avail_in == 0) { s->z_eof = 1; if (F_ERROR(s->file)) s->z_err = Z_ERRNO; return EOF; } s->stream.next_in = s->inbuf; } s->stream.avail_in--; return *(s->stream.next_in)++; }
/* =========================================================================== Reads the given number of uncompressed bytes from the compressed file. lib_gzread returns the number of bytes actually read (0 for end of file). */ int lib_gzread (gzFile file, voidp buf, size_t len) { gz_stream *s = (gz_stream*)file; Bytef *start = (Bytef*)buf; /* starting point for crc computation */ Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; if (s->z_err == Z_STREAM_END) return 0; /* EOF */ next_out = (Byte*)buf; s->stream.next_out = (Bytef*)buf; s->stream.avail_out = (uInt)len; while (s->stream.avail_out != 0) { if (s->transparent) { /* Copy first the lookahead bytes: */ uInt n = s->stream.avail_in; if (n > s->stream.avail_out) n = s->stream.avail_out; if (n > 0) { sysMemCpy(s->stream.next_out, s->stream.next_in, n); next_out += n; s->stream.next_out = next_out; s->stream.next_in += n; s->stream.avail_out -= n; s->stream.avail_in -= n; } if (s->stream.avail_out > 0) { s->stream.avail_out -= F_READ(next_out, 1, s->stream.avail_out, s->file); } len -= s->stream.avail_out; s->stream.total_in += (uLong)len; s->stream.total_out += (uLong)len; if (len == 0) s->z_eof = 1; return (int)len; } if (s->stream.avail_in == 0 && !s->z_eof) { s->stream.avail_in = F_READ(s->inbuf, 1, Z_BUFSIZE, s->file); if (s->stream.avail_in == 0) { s->z_eof = 1; if (F_ERROR(s->file)) { s->z_err = Z_ERRNO; break; } } s->stream.next_in = s->inbuf; } s->z_err = inflate(&(s->stream), Z_NO_FLUSH); if (s->z_err == Z_STREAM_END) { /* Check CRC and original size */ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); start = s->stream.next_out; if (getLong(s) != s->crc) { s->z_err = Z_DATA_ERROR; } else { (void)getLong(s); /* The uncompressed length returned by above getlong() may * be different from s->stream.total_out) in case of * concatenated .gz files. Check for such files: */ check_header(s); if (s->z_err == Z_OK) { uLong total_in = s->stream.total_in; uLong total_out = s->stream.total_out; inflateReset(&(s->stream)); s->stream.total_in = total_in; s->stream.total_out = total_out; s->crc = crc32(0L, Z_NULL, 0); } } } if (s->z_err != Z_OK || s->z_eof) break; } s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); return (int)(len - s->stream.avail_out); }
xb_rstream_result_t xb_stream_read_chunk(xb_rstream_t *stream, xb_rstream_chunk_t *chunk) { uchar tmpbuf[16]; uchar *ptr = tmpbuf; uint pathlen; size_t tlen; size_t tbytes; ulonglong ullval; ulong checksum_exp; ulong checksum;; File fd = stream->fd; xb_ad(sizeof(tmpbuf) >= CHUNK_HEADER_CONSTANT_LEN); /* This is the only place where we expect EOF, so read with my_read() rather than F_READ() */ tlen = CHUNK_HEADER_CONSTANT_LEN; while (tlen > 0) { tbytes = my_read(fd, ptr, tlen, MYF(MY_WME)); if (tbytes == 0) { break; } ptr += tbytes; tlen -= tbytes; } if (tlen == CHUNK_HEADER_CONSTANT_LEN) { return XB_STREAM_READ_EOF; } else if (tlen > 0) { msg("xb_stream_read_chunk(): unexpected end of stream at " "offset 0x%llx.\n", stream->offset); goto err; } ptr = tmpbuf; /* Chunk magic value */ if (memcmp(tmpbuf, XB_STREAM_CHUNK_MAGIC, 8)) { msg("xb_stream_read_chunk(): wrong chunk magic at offset " "0x%llx.\n", (ulonglong) stream->offset); goto err; } ptr += 8; stream->offset += 8; /* Chunk flags */ chunk->flags = *ptr++; stream->offset++; /* Chunk type, ignore unknown ones if ignorable flag is set */ chunk->type = validate_chunk_type(*ptr); if (chunk->type == XB_CHUNK_TYPE_UNKNOWN && !(chunk->flags & XB_STREAM_FLAG_IGNORABLE)) { msg("xb_stream_read_chunk(): unknown chunk type 0x%lu at " "offset 0x%llx.\n", (ulong) *ptr, (ulonglong) stream->offset); goto err; } ptr++; stream->offset++; /* Path length */ pathlen = uint4korr(ptr); if (pathlen >= FN_REFLEN) { msg("xb_stream_read_chunk(): path length (%lu) is too large at " "offset 0x%llx.\n", (ulong) pathlen, stream->offset); goto err; } chunk->pathlen = pathlen; stream->offset +=4; xb_ad((ptr + 4 - tmpbuf) == CHUNK_HEADER_CONSTANT_LEN); /* Path */ if (chunk->pathlen > 0) { F_READ((uchar *) chunk->path, pathlen); stream->offset += pathlen; } chunk->path[pathlen] = '\0'; if (chunk->type == XB_CHUNK_TYPE_EOF) { return XB_STREAM_READ_CHUNK; } /* Payload length */ F_READ(tmpbuf, 16); ullval = uint8korr(tmpbuf); if (ullval > (ulonglong) SIZE_T_MAX) { msg("xb_stream_read_chunk(): chunk length is too large at " "offset 0x%llx: 0x%llx.\n", (ulonglong) stream->offset, ullval); goto err; } chunk->length = (size_t) ullval; stream->offset += 8; /* Payload offset */ ullval = uint8korr(tmpbuf + 8); if (ullval > (ulonglong) MY_OFF_T_MAX) { msg("xb_stream_read_chunk(): chunk offset is too large at " "offset 0x%llx: 0x%llx.\n", (ulonglong) stream->offset, ullval); goto err; } chunk->offset = (my_off_t) ullval; stream->offset += 8; /* Reallocate the buffer if needed */ if (chunk->length > stream->buflen) { stream->buffer = my_realloc(stream->buffer, chunk->length, MYF(MY_WME)); if (stream->buffer == NULL) { msg("xb_stream_read_chunk(): failed to increase buffer " "to %lu bytes.\n", (ulong) chunk->length); goto err; } stream->buflen = chunk->length; } /* Checksum */ F_READ(tmpbuf, 4); checksum_exp = uint4korr(tmpbuf); /* Payload */ if (chunk->length > 0) { F_READ(stream->buffer, chunk->length); stream->offset += chunk->length; } checksum = crc32(0, stream->buffer, chunk->length); if (checksum != checksum_exp) { msg("xb_stream_read_chunk(): invalid checksum at offset " "0x%llx: expected 0x%lx, read 0x%lx.\n", (ulonglong) stream->offset, checksum_exp, checksum); goto err; } stream->offset += 4; chunk->data = stream->buffer; chunk->checksum = checksum; return XB_STREAM_READ_CHUNK; err: return XB_STREAM_READ_ERROR; }