def read(self, size=None):
        """
        Reads `size` bytes from current directory entry. If `size` is empty,
        it'll read all data till entry's end.
        """
        if self._is_mini:
            self.seek(self._position)
        else:
            self.source.seek(self._source_position)
        if not size or size < 0:
            size = self.size - self.tell()

        data = b('')
        while len(data) < size:
            if self.tell() > self.size:
                break
            if self._sector_number == ENDOFCHAIN:
                break

            to_read = size - len(data)
            to_end = self.sector_size - self._position_in_sector
            to_do = min(to_read, to_end)
            data += self.stream.read(to_do)

            self._position += to_do
            self._source_position = self.source.tell()

            if to_read >= to_end:
                self._position_in_sector = 0

                self._sector_number = self.next_sector(self._sector_number)
                position = (self._sector_number + int(not self._is_mini)) \
                    << self.sector_shift
                self.stream.seek(position)
            else:
                self._position_in_sector += to_do

        return data