Exemplo n.º 1
0
static int _xd3_set_source (xd3_stream *stream, xd3_cmd cmd, _xd3_file *sfile, xd3_source *source)
{
  int ret = 0;
  usize_t i;
  xoff_t source_size = 0;
  usize_t blksize;

  XD3_ASSERT (lru == NULL);
  XD3_ASSERT (stream->src == NULL);
  XD3_ASSERT (option_srcwinsz >= XD3_MINSRCWINSZ);

  /* TODO: this code needs refactoring into FIFO, LRU, FAKE.  Yuck!
   * This is simplified from 3.0z which had issues with sizing the
   * source buffer memory allocation and the source blocksize. */

  /* LRU-specific */
  main_blklru_list_init (& lru_list);

  if ((ret = _xd3_file_open (sfile, sfile->filename, XO_READ)))
  {
    return ret;
  }

  /* If the file is regular we know it's size.  If the file turns
   * out to be externally compressed, size_known may change. */
  sfile->size_known = (_xd3_file_stat(sfile, &source_size) == 0);

  /* Note: The API requires a power-of-two blocksize and srcwinsz
   * (-B).  The logic here will use a single block if the entire file
   * is known to fit into srcwinsz. */
  option_srcwinsz = xd3_pow2_roundup (option_srcwinsz);

  /* Though called "lru", it is not LRU-specific.  We always allocate
   * a maximum number of source block buffers.  If the entire file
   * fits into srcwinsz, this buffer will stay as the only
   * (lru_size==1) source block.  Otherwise, we know that at least
   * option_srcwinsz bytes are available.  Split the source window
   * into buffers. */
  if ((lru = (main_blklru*)_xd3_alloc(NULL, MAX_LRU_SIZE,
          sizeof (main_blklru))) == NULL)
  {
    ret = ENOMEM;
    return ret;
  }

  memset (lru, 0, sizeof(lru[0]) * MAX_LRU_SIZE);

  /* Allocate the entire buffer. */
  if ((lru[0].blk = (uint8_t*)_xd3_alloc(NULL, 1, option_srcwinsz))) {
    ret = ENOMEM;
    return ret;
  }

  /* Main calls _xd3_getblk_func() once before xd3_set_source().  This
   * is the point at which external decompression may begin.  Set the
   * system for a single block. */
  lru_size = 1;
  lru[0].blkno = (xoff_t) -1;
  blksize = option_srcwinsz;
  main_blklru_list_push_back (& lru_list, & lru[0]);
  XD3_ASSERT (blksize != 0);

  /* Initialize xd3_source. */
  source->blksize  = blksize;
  source->name     = sfile->filename;
  source->ioh      = sfile;
  source->curblkno = (xoff_t) -1;
  source->curblk   = NULL;
  source->max_winsize = option_srcwinsz;

  if ((ret = _xd3_getblk_func (stream, source, 0)) != 0)
  {
    return ret;
  }

  source->onblk = lru[0].size;  /* xd3 sets onblk */

  /* If the file is smaller than a block, size is known. */
  if (!sfile->size_known && source->onblk < blksize)
  {
    source_size = source->onblk;
    sfile->size_known = 1;
  }

  /* If the size is not known or is greater than the buffer size, we
   * split the buffer across MAX_LRU_SIZE blocks (already allocated in
   * "lru"). */
  if (!sfile->size_known || source_size > option_srcwinsz)
  {
    /* Modify block 0, change blocksize. */
    blksize = option_srcwinsz / MAX_LRU_SIZE;
    source->blksize = blksize;
    source->onblk = blksize;  /* xd3 sets onblk */
    /* Note: source->max_winsize is unchanged. */
    lru[0].size = blksize;
    lru_size = MAX_LRU_SIZE;

    /* Setup rest of blocks. */
    for (i = 1; i < lru_size; i += 1)
    {
      lru[i].blk = lru[0].blk + (blksize * i);
      lru[i].blkno = i;
      lru[i].size = blksize;
      main_blklru_list_push_back (& lru_list, & lru[i]);
    }
  }

  /* Call the appropriate set_source method, handle errors, print
   * verbose message, etc. */
  if (sfile->size_known)
  {
    ret = xd3_set_source_and_size (stream, source, source_size);
  }
  else
  {
    ret = xd3_set_source (stream, source);
  }

  if (ret)
  {
    return ret;
  }

  return 0;
}
Exemplo n.º 2
0
int  BinDiff(void *in, void *buffer, size_t size) {
	stream_p    modified = ((bindiff_p)(in))->in2;
	diffdata_p  data = (diffdata_p)(((bindiff_p)(in))->userdata);
	int         retcode;
	int         len_done = 0;
	
	// Alloc resources if needed
	if(data == NULL)
	{
		data = malloc(sizeof(diffdata_t));
		xd3_init_config(&data->config, 0);
		data->config.winsize = BIN_DIFF_WINDOW_SIZE;
		data->config.getblk = &GetblkCallback;
		retcode = xd3_config_stream(&data->stream, &data->config);
		if (retcode != 0) return STREAM_EOF;
		
		data->source.ioh = in;
		data->source.curblkno = (xoff_t) -1;
		data->source.curblk = NULL;
		data->source.blksize = BIN_DIFF_WINDOW_SIZE;
		retcode = xd3_set_source(&data->stream, &data->source);
		
		if (retcode != 0) return STREAM_EOF;
		
		data->haveData = 0;
		data->reachedEOF = 0;
		data->org_cur = data->org_last = 0;
		((bindiff_p)(in))->userdata = data;
	}
	
	if(data->haveData) {
		if((size_t)data->haveData >= size) {
			memcpy (buffer, &data->stream.next_out[data->stream.avail_out-data->haveData], size);
			data->haveData = data->haveData - size;
			return size;
		} else {
			memcpy (buffer, &data->stream.next_out[data->stream.avail_out-data->haveData], data->haveData);
			len_done = data->haveData;
			data->stream.avail_out = 0;
			data->haveData = 0;
		}
	}
	
	do {
		if(((bindiff_p)(in))->isPatch) retcode = xd3_decode_input(&data->stream);
		else retcode = xd3_encode_input(&data->stream);
		switch (retcode) {
		case XD3_INPUT:
			if(data->reachedEOF) return len_done ? len_done : STREAM_EOF;
			retcode = StreamRead(modified, data->inbuf, BIN_DIFF_WINDOW_SIZE);
			//fprintf(stderr,"\tXD3_INPUT (%i)\n", retcode);
			if (retcode == STREAM_EOF) {
				xd3_set_flags (&data->stream, XD3_FLUSH);
				data->reachedEOF = 1;
				retcode = 0;
			}
			xd3_avail_input(&data->stream, (uint8_t*)data->inbuf, retcode);
			continue;
		case XD3_OUTPUT:
			//fprintf(stderr,"\tXD3_OUTPUT (%i)\n", data->stream.avail_out);
			if(data->stream.avail_out >= (size-len_done)) {
				memcpy (((char *)buffer)+len_done, data->stream.next_out, size-len_done);
				data->haveData = data->stream.avail_out - size+len_done;
				return size;
			} else {
				memcpy (((char *)buffer)+len_done, data->stream.next_out, data->stream.avail_out);
				len_done += data->stream.avail_out;
				data->stream.avail_out = 0;
				data->haveData = 0;
				continue;
			}
		case XD3_GETSRCBLK:
		case XD3_GOTHEADER:
		case XD3_WINSTART:
		case XD3_WINFINISH:
		    continue;
		default:
			//fprintf(stderr,"\terror: %s\n", data->stream.msg);
		    return STREAM_EOF;
		}
	} while (1);
}