Beispiel #1
0
// readAll read entire referenced block.
func (p *bInfo) readAll(r io.ReaderAt, checksum bool) (b []byte, err error) {
	raw := make([]byte, p.size+5)
	_, err = readFullAt(r, raw, int64(p.offset))
	if err != nil {
		return
	}

	crcb := raw[len(raw)-4:]
	raw = raw[:len(raw)-4]

	if checksum {
		sum := binary.LittleEndian.Uint32(crcb)
		sum = hash.UnmaskCRC32(sum)
		crc := hash.NewCRC32C()
		crc.Write(raw)
		if crc.Sum32() != sum {
			err = errors.ErrCorrupt("block checksum mismatch")
			return
		}
	}

	compression := raw[len(raw)-1]
	b = raw[:len(raw)-1]

	switch compression {
	case kNoCompression:
	case kSnappyCompression:
		return snappy.Decode(nil, b)
	default:
		err = errors.ErrCorrupt("bad block type")
	}

	return
}
Beispiel #2
0
func (r *Reader) read() (ret []byte, rtype uint, err error) {
retry:
	if len(r.buf) < kHeaderSize {
		if r.eof {
			if len(r.buf) > 0 {
				r.drop(len(r.buf), "truncated record at end of file")
				r.rbuf = nil
				r.buf = nil
			}
			rtype = tEof
			return
		}

		if r.rbuf == nil {
			r.rbuf = make([]byte, BlockSize)
		} else {
			r.off++
		}

		var n int
		n, err = r.r.ReadAt(r.rbuf, int64(r.off)*BlockSize)
		if err != nil {
			if err == io.EOF {
				err = nil
			} else {
				return
			}
		}
		r.buf = r.rbuf[:n]
		if n < BlockSize {
			r.eof = true
			goto retry
		}
	}

	// decode record length and type
	recLen := int(r.buf[4]) | (int(r.buf[5]) << 8)
	rtype = uint(r.buf[6])

	// check whether the header is sane
	if len(r.buf) < kHeaderSize+recLen || rtype > tLast {
		rtype = tCorrupt
		r.drop(len(r.buf), "header corrupted")
	} else if r.checksum {
		// decode the checksum
		recCrc := hash.UnmaskCRC32(binary.LittleEndian.Uint32(r.buf))
		crc := hash.NewCRC32C()
		crc.Write(r.buf[6 : kHeaderSize+recLen])
		if crc.Sum32() != recCrc {
			// Drop the rest of the buffer since "length" itself may have
			// been corrupted and if we trust it, we could find some
			// fragment of a real journal record that just happens to look
			// like a valid journal record.
			rtype = tCorrupt
			r.drop(len(r.buf), "checksum mismatch")
		}
	}

	if rtype == tCorrupt {
		// report bytes drop
		r.buf = nil
	} else {
		ret = r.buf[kHeaderSize : kHeaderSize+recLen]
		r.buf = r.buf[kHeaderSize+recLen:]
	}

	return
}