Esempio n. 1
0
static void test3() {
    struct Buffer *buffer;
    char input[] = "Test buffer resizing.";
    char output[sizeof(input)];
    int len, i;

    buffer = new_buffer(200, EV_DEFAULT);
    assert(buffer != NULL);

    len = buffer_push(buffer, input, sizeof(input));
    assert(len == sizeof(input));

    /* Test resizing to too small of a buffer size */
    len = buffer_resize(buffer, 5);
    assert(len == -1);


    buffer_resize(buffer, 40);
    assert(buffer_room(buffer) == 40 - sizeof(input));

    len = buffer_peek(buffer, output, sizeof(output));
    assert(len == sizeof(input));

    for (i = 0; i < len; i++)
        assert(input[i] == output[i]);

    free_buffer(buffer);
}
Esempio n. 2
0
void buffer_openspacehelper(BUFFER *buff, size_t amount)
{
    if (amount + buff->pos < 1024)
        buffer_resize(buff, 1024);
    else
        buffer_resize(buff, amount + buff->pos);
}
Esempio n. 3
0
/*
 * Read from a file descriptor until end of file is reached, doubling the
 * buffer size as necessary to hold all of the data.  Returns true on success,
 * false on failure (in which case errno will be set).
 */
bool
buffer_read_all(struct buffer *buffer, int fd)
{
    ssize_t count;

    if (buffer->size == 0)
        buffer_resize(buffer, 1024);
    do {
        size_t used = buffer->used + buffer->left;
        if (buffer->size <= used)
            buffer_resize(buffer, buffer->size * 2);
        count = buffer_read(buffer, fd);
    } while (count > 0);
    return (count == 0);
}
Esempio n. 4
0
bool buffer_insert (Buffer* buffer, int32_t index, unsigned char* data, int32_t length) {
    assert(NULL != buffer);
    assert(NULL != buffer->data);
    assert(0 < length);
    assert(0 <= index && index <= buffer->length);

    if (index == buffer->length) {
        return buffer_append(buffer, data, length);
    }

    if (buffer->size < buffer->length + length && !buffer_resize(buffer, buffer->length + length)) {
        return false;
    }

    unsigned char* tmp = malloc(__BUFFER_ALIGN_SIZE(buffer->length - index));

    if (NULL == tmp) {
        return false;
    }

    memcpy(tmp, buffer->data + index, buffer->length - index);
    memcpy(buffer->data + index + length, tmp, buffer->length - index);
    memcpy(buffer->data + index, data, length);
    free(tmp);

    buffer->length += length;

    return true;
}
buffer_t * ipv6_pseudo_header_create(const uint8_t * ipv6_segment)
{
    buffer_t             * psh;
    const struct ip6_hdr * iph = (const struct ip6_hdr *) ipv6_segment;
    ipv6_pseudo_header_t * data;

    if (!(psh = buffer_create())) {
        goto ERR_BUFFER_CREATE;
    }

    if (!(buffer_resize(psh, sizeof(ipv6_pseudo_header_t)))) {
        goto ERR_BUFFER_RESIZE;
    }

    data = (ipv6_pseudo_header_t *) buffer_get_data(psh);
    memcpy((uint8_t *) data + offsetof(ipv6_pseudo_header_t, ip_src), &iph->ip6_src, sizeof(ipv6_t));
    memcpy((uint8_t *) data + offsetof(ipv6_pseudo_header_t, ip_dst), &iph->ip6_dst, sizeof(ipv6_t));

    // IPv6 stores a uint16 but our pseudo header uses an uint32 ...
    // So to take care of endianness we cannot directly copy the value.
    data->size = htonl(ntohs(iph->ip6_ctlun.ip6_un1.ip6_un1_plen));
    data->zeros = 0;
    data->zero  = 0;
    data->protocol = iph->ip6_ctlun.ip6_un1.ip6_un1_nxt;

    return psh;

ERR_BUFFER_RESIZE:
    buffer_free(psh);
ERR_BUFFER_CREATE:
    return NULL;
}
Esempio n. 6
0
// Appends a block of data to a buffer; respects the current offset and will overwrite data.
ssize_t buffer_append(Buffer *buffer, const char* data, size_t length)
{
    size_t new_size = (buffer->offset + length);
    
    // Will this read put us past the specified growth limit?
    if(buffer->capacity < new_size) {
        errno = ENOBUFS;
        return -1;
    }
    
    // The new size is less than capacity. Do we need to grow to handle it?
    if( new_size > malloc_size(buffer->data) ) {
        size_t result = buffer_resize(buffer, new_size);
        if (result < new_size) {
            errno = ENOBUFS;
            return -1;
        }
    }
    
    // Append the data
    void* destination = buffer->data + buffer->offset;
    memcpy(destination, data, length);

    // Kick the can
    buffer->offset += length;
    
    return length;
}
Esempio n. 7
0
/*
 * Print data into a buffer from the supplied va_list, appending to the end.
 * The new data shows up as unused data at the end of the buffer.  The
 * trailing nul is not added to the buffer.
 */
void
buffer_append_vsprintf(struct buffer *buffer, const char *format, va_list args)
{
    size_t total, avail;
    ssize_t status;
    va_list args_copy;

    total = buffer->used + buffer->left;
    avail = buffer->size - total;
    va_copy(args_copy, args);
    status = vsnprintf(buffer->data + total, avail, format, args_copy);
    va_end(args_copy);
    if (status < 0)
        return;
    if ((size_t) status < avail) {
        buffer->left += status;
    } else {
        buffer_resize(buffer, total + status + 1);
        avail = buffer->size - total;
        status = vsnprintf(buffer->data + total, avail, format, args);
        if (status < 0 || (size_t) status >= avail)
            return;
        buffer->left += status;
    }
}
Esempio n. 8
0
File: buffer.c Progetto: erik/arroyo
void buffer_putsn(buffer* b, const char* s, unsigned sz)
{
  if(b->pos + sz >= b->size) buffer_resize(b, sz + b->size);

  for(unsigned i = 0; i < sz; ++i)
    b->buf[b->pos++] = s[i];
}
Esempio n. 9
0
static int nas_add_buffer(WINE_WAVEOUT* wwo) {
    int len = wwo->lpPlayPtr->dwBufferLength;

    buffer_resize(wwo, len);
    memcpy(wwo->SoundBuffer + wwo->BufferUsed, wwo->lpPlayPtr->lpData, len);
    wwo->BufferUsed += len;
    wwo->WrittenTotal += len;
    return len;
}
Esempio n. 10
0
/* Appends @size bytes of @data to the buffer */
int buffer_append(t_buffer* buff, const void* data, size_t size)
{
  if (buff->len + size + 1 > buff->allocd &&
      buffer_resize(buff, buff->len + size))
    return (1);
  memcpy(&(buff->buff[buff->len]), data, size);
  buff->len += size;
  buff->buff[buff->len] = 0;
  return (0);
}
Esempio n. 11
0
/*
 * Replace whatever data is currently in the buffer with the provided data.
 * Resize the buffer if needed.
 */
void
buffer_set(struct buffer *buffer, const char *data, size_t length)
{
    if (length > 0) {
        buffer_resize(buffer, length);
        memmove(buffer->data, data, length);
    }
    buffer->left = length;
    buffer->used = 0;
}
Esempio n. 12
0
/*
 * Read the entire contents of a file into a buffer.  This is a slight
 * optimization over buffer_read_all because it can stat the file descriptor
 * first and size the buffer appropriately.  buffer_read_all will still handle
 * the case where the file size changes while it's being read.  Returns true
 * on success, false on failure (in which case errno will be set).
 */
bool
buffer_read_file(struct buffer *buffer, int fd)
{
    struct stat st;
    size_t used = buffer->used + buffer->left;

    if (fstat(fd, &st) < 0)
        return false;
    buffer_resize(buffer, st.st_size + used);
    return buffer_read_all(buffer, fd);
}
Esempio n. 13
0
bool buffer_resize_ts (Buffer* buffer, int32_t size) {
    assert(NULL != buffer);
    assert(NULL != buffer->mutex);

    pthread_mutex_lock(buffer->mutex);

    bool ret = buffer_resize(buffer, size);

    pthread_mutex_unlock(buffer->mutex);

    return ret;
}
Esempio n. 14
0
/**
 * VMNative: string_prealloc( workshop , newsize )
 * Accepts a workshop argument and a number. The newsize is the size to
 * reallocate the workshop buffer to. Preallocate buffer for best performance.
 */
static bool vmn_str_prealloc(VM * vm, VMArg * arg, int argc) {
  VMLibData * data;
  Buffer * buffer;
  int newSize;

  /* check for proper number of arguments */
  if(argc != 2) {
    vm_set_err(vm, VMERR_INCORRECT_NUMARGS);
    return false;
  }

  /* check argument 1 major type */
  if(vmarg_type(arg[0]) != TYPE_LIBDATA) {
    vm_set_err(vm, VMERR_INVALID_TYPE_ARGUMENT);
    return false;
  }

  /* extract the libdata from the argument */
  data = vmarg_libdata(arg[0]);

  /* check libdata type */
  if(!vmlibdata_is_type(data, LIBSTR_STRING_TYPE, LIBSTR_STRING_TYPE_LEN)) {
    vm_set_err(vm, VMERR_INVALID_TYPE_ARGUMENT);
    return false;
  }

  /* check argument 2 type */
  if(vmarg_type(arg[1]) != TYPE_NUMBER) {
    vm_set_err(vm, VMERR_INVALID_TYPE_ARGUMENT);
    return false;
  }

  newSize = (int)vmarg_number(arg[1], NULL);

  /* check buffer size range */
  if(newSize < 1) {
    vm_set_err(vm, VMERR_ARGUMENT_OUT_OF_RANGE);
    return false;
  }

  /* extract the workshop */
  buffer = vmlibdata_data(data);

  /* can't make it smaller, only bigger */
  buffer_resize(buffer, newSize >= buffer_size(buffer)
		? newSize : buffer_size(buffer));

  /* push null result */
  vmarg_push_null(vm);

  /* this function does return a value */
  return true;
}
Esempio n. 15
0
/*
 * Append data to a buffer.  The new data shows up as additional unused data
 * at the end of the buffer.  Resize the buffer if needed.
 */
void
buffer_append(struct buffer *buffer, const char *data, size_t length)
{
    size_t total;

    if (length == 0)
        return;
    total = buffer->used + buffer->left;
    buffer_resize(buffer, total + length);
    buffer->left += length;
    memcpy(buffer->data + total, data, length);
}
Esempio n. 16
0
/* Removes the first @shift bytes of @buff by shifing the buffer contents
 * left from @shift bytes
 * It may realloc datas to release memory */
int buffer_rotate(t_buffer* buff, size_t shift)
{
  if (shift < buff->len)
  {
    memmove(buff->buff, &(buff->buff[shift]), buff->len - shift);
    buff->len -= shift;
  }
  else
    buff->len = 0;
  if (buff->allocd - buff->len > 2 * BUFFER_STEP)
    return (buffer_resize(buff, buff->len + BUFFER_STEP));
  return (0);
}
Esempio n. 17
0
static int
reset (vga_op_list_t* vol)
{
  if (vol->count == 0) {
    buffer_file_truncate (&vol->bf);
    if (buffer_file_write (&vol->bf, &vol->count, sizeof (size_t)) != 0) {
      return -1;
    }

    if (buffer_resize (vol->bdb, 0) != 0) {
      return -1;
    }
  }
  return 0;
}
Esempio n. 18
0
File: under.c Progetto: vvv/under.c
/*
 * Adjust buffer to the blocksize of a file.
 *
 * Do nothing if size of buffer is equal to blocksize of file;
 * otherwise (re)allocate memory.
 */
static int
adjust_buffer(struct Buffer *buf, FILE *f)
{
#ifdef DEBUG
    (void) f;
#  warning "Using buffer of size 5 for tests"
    return buffer_resize(buf, 5);
#else
    struct stat st;
    size_t insize;

    if (fstat(fileno(f), &st) != 0) {
        error(0, errno, "fstat failed");
        return -1;
    } else if ((insize = st.st_blksize) == buf->_max_size) {
        return 0;
    } else if (fstat(fileno(stdout), &st) != 0) {
        error(0, errno, "fstat(stdout) failed");
        return -1;
    } else {
        return buffer_resize(buf, MAX(insize, (size_t) st.st_blksize));
    }
#endif
}
Esempio n. 19
0
int main(int argc, char *argv[]) {
    client_udp_t *client;
    io_service_t *iosvc;
    buffer_t *buffer;
    context_t context;
    endpoint_t ep;

    if (argc < 3) {
        fprintf(stdout, "usage: %s <src-port> <dst-port>\n", argv[0]);
        exit(0);
    }

    buffer = buffer_init(10, buffer_policy_no_shrink);
    assert(buffer != NULL);

    iosvc = io_service_init();
    assert(iosvc != NULL);

    ep.ep_type = EPT_TCP;
    ep.ep_class = EPC_IP4;
    ep.ep.ip4.addr[0] = ep.ep.ip4.addr[1] =
    ep.ep.ip4.addr[2] = ep.ep.ip4.addr[3] = 0;
    ep.ep.ip4.port = 12345;

    client = client_udp_init(iosvc, NULL /*"127.0.0.1"*/, argv[1] /*"54321"*/, 1);
    assert(client != NULL);

    context.buffer = buffer;
    context.client = client;
    context.service = iosvc;

    buffer_resize(&buffer, 10);
    memcpy(buffer_data(buffer), "1234567890", 10);

    //client_udp_connect_sync(client, "127.0.0.1", "12345", connected, &context);

    //oto_server_tcp_listen_async(server, connection_accepted, &context);

    client_udp_send_async(context.client, context.buffer, "127.0.0.1", argv[2], data_sent, &context);
    io_service_run(iosvc);
    /*io_service_stop(iosvc, true);*/

    client_udp_deinit(client);
    io_service_deinit(iosvc);
    buffer_deinit(buffer);

    return 0;
}
Esempio n. 20
0
bool buffer_append (Buffer* buffer, unsigned char* data, int32_t length) {
    assert(NULL != buffer);
    assert(NULL != buffer->data);
    assert(0 < length);

    if (buffer->size < buffer->length + length &&
        !buffer_resize(buffer, buffer->length + length)) {
        return false;
    }

    memcpy(buffer->data + buffer->length, data, length);

    buffer->length += length;

    return true;
}
Esempio n. 21
0
int
buffer_append(buffer_t *self, char *str) {
  size_t len = strlen(str);
  size_t prev = strlen(self->data);
  size_t needed = len + prev;

  // enough space
  if (self->len > needed) {
    strcat(self->data, str);
    return 0;
  }

  // resize
  int ret = buffer_resize(self, needed);
  if (-1 == ret) return -1;
  strcat(self->data, str);

  return 0;
}
Esempio n. 22
0
buffer_t *buffer_init(buffer_t *buffer, size_t size, allocator_t *alloc)
{
  if (buffer) {
    if (alloc == NULL)
      alloc = g_default_allocator;

    buffer->alloc = alloc;
    buffer->ptr = NULL;
    buffer->size = 0;
    buffer->capacity = 0;
    buffer->outside = false;

    buffer_resize(buffer, size);
  } else if (! buffer) {
    s_log_error("Attempt to initialize a NULL buffer.");
  }

  return buffer;
}
Esempio n. 23
0
int
buffer_prepend(buffer_t *self, char *str) {
  size_t len = strlen(str);
  size_t prev = strlen(self->data);
  size_t needed = len + prev;

  // enough space
  if (self->len > needed) goto move;

  // resize
  int ret = buffer_resize(self, needed);
  if (-1 == ret) return -1;

  // move
  move:
  memmove(self->data + len, self->data, len + 1);
  memcpy(self->data, str, len);

  return 0;
}
Esempio n. 24
0
int
buffer_file_write (buffer_file_t* bf,
		   const void* ptr,
		   size_t size)
{
  if (!bf->can_update) {
    return -1;
  }

  size_t new_position = bf->position + size;
  if (new_position < bf->position) {
    /* Overflow. */
    return -1;
  }

  /* Resize if necessary. */
  if (bf->capacity < new_position) {
    buffer_unmap (bf->bd);
    bf->capacity = ALIGN_UP (new_position, pagesize ());
    bf->bd_size = bf->capacity / pagesize ();
    if (buffer_resize (bf->bd, bf->bd_size) != 0) {
      return -1;
    }
    bf->ptr = buffer_map (bf->bd);
    if (bf->ptr == 0) {
      return -1;
    }
  }

  memcpy (bf->ptr + bf->position, ptr, size);
  bf->position = new_position;
  if (bf->position > bf->size) {
    bf->size = bf->position;
    *((size_t*)bf->ptr) = bf->size;
  }

  return 0;
}
Esempio n. 25
0
int
buffer_file_put (buffer_file_t* bf,
		 char c)
{
  if (!bf->can_update) {
    return -1;
  }
  
  size_t new_position = bf->position + 1;
  if (new_position < bf->position) {
    /* Overflow. */
    return -1;
  }
  
  /* Resize if necessary. */
  if (bf->capacity < new_position) {
    buffer_unmap (bf->bd);
    bf->capacity = ALIGN_UP (new_position, pagesize ());
    bf->bd_size = bf->capacity / pagesize ();
    if (buffer_resize (bf->bd, bf->bd_size) != 0) {
      return -1;
    }
    bf->ptr = buffer_map (bf->bd);
    if (bf->ptr == 0) {
      return -1;
    }
  }
  
  *((char*)(bf->ptr + bf->position)) = c;
  bf->position = new_position;
  if (bf->position > bf->size) {
    bf->size = bf->position;
    *((size_t*)bf->ptr) = bf->size;
  }

  return 0;
}
Esempio n. 26
0
/*
 * @brief handle token request
 * mode=0:add token request
 * mode=1:remove token request
 */
static int novacom_handle_tokenrequest(device_handle_t dev, uint32_t chan, buffer_t *b, buffer_t *r, unsigned char cmd)
{
	int rc=-1;
	char *hash = NULL;
	char *token = NULL;
	char *blob = NULL;

	/* skip version */
	if ( 0 != buffer_getbyte(b, NULL) ) {
		LTRACEF("missing version\n");
		goto out;
	}

	/* get hash */
	if ( 0 != buffer_getstring(b, (unsigned char **)&hash) ) {
		LTRACEF("missing password hash\n");
		goto out;
	}

	/* get hashed token for "remove" */
	if ( (SSH_MSG_USERAUTH_TOKENREQUEST_RM == cmd)
			&& ( 0 != buffer_getstring(b, (unsigned char **)&token) ) ) {
		LTRACEF("missing token hash\n");
		goto out;
	}

	/* verify that password hash is good */
	if ( true != auth_process_passw(hash, strlen(hash), 1) ) {
		LTRACEF("invalid password hash\n");
		goto out;
	}

	/* process tokens */
	if (SSH_MSG_USERAUTH_TOKENREQUEST_RM == cmd) {
		rc = auth_tokenfile_delete(token, strlen(token));
		/* pickup res */
		if (!rc) {
			buffer_putbyte(r, SSH_MSG_USERAUTH_SUCCESS);
			buffer_putbyte(r, 0);   /* version */
			buffer_putbyte(r, cmd); /* command */
		}
	} else {
		blob = platform_calloc(NOVACOM_AUTHTOKEN_LEN);
		if (!blob) {
			LTRACEF("unable to allocate token\n");
			goto out;
		}
		/* fill with random data */
		LTRACEF("generate token\n");
		rc = auth_tokenfile_buffergenerate(blob, NOVACOM_AUTHTOKEN_LEN);
		if (rc) {
			LTRACEF("unable to generate token\n");
			goto out;
		}
		/* save token: creating file with name:<rnduid> */
		LTRACEF("save token\n");
		char *file = novacom_rnduid(dev);
		if (!file) {
			LTRACEF("unable to retrieve rnduid\n");
			goto out;
		}
		rc = auth_tokenfile_create(file, blob, NOVACOM_AUTHTOKEN_LEN);
		platform_free(file);
		if (rc) {
			LTRACEF("unable to store token\n");
			goto out;
		}
		LTRACEF("token generated && saved\n");
		/* pickup res */
		buffer_putbyte(r, SSH_MSG_USERAUTH_TOKEN_REPLY);
		buffer_putbyte(r, 0);   /* version */
		buffer_putbyte(r, cmd); /* command */
		/* resize output buffer to fit token data */
		rc = buffer_resize(r, 16 + NOVACOM_AUTHTOKEN_LEN);
		if (rc)
			goto out;

		rc = buffer_putblob(r, (unsigned char *)blob, NOVACOM_AUTHTOKEN_LEN);
		LTRACEF("token placed\n");
	}

out:
	/* error result */
	if (rc) {
		buffer_setpos(r, 0);
		buffer_putbyte(r, SSH_MSG_USERAUTH_FAILURE);
		buffer_putbyte(r, 0);   /* version */
		buffer_putbyte(r, cmd); /* command */
	}
	LTRACEF("result(%d), r->pos %d, r->size %d\n", rc, r->pos, r->len);
	/* free resources */
	platform_free(hash);
	platform_free(token);
	platform_free(blob);
	return rc;
}
Esempio n. 27
0
static void buffer_assure_space(bson_buffer* buffer, int size) {
    if (buffer->position + size <= buffer->size) {
        return;
    }
    buffer_resize(buffer, buffer->position + size);
}
Esempio n. 28
0
void
hcache_readfile(HCACHEFILE *file)
{
	HCACHEDATA	cachedata, *c, *last = 0;
	FILE	*f;
	int		bad_cache = 1, ch;
	const char	*version;
	BUFFER	buff;
	long	buffsize;

/*    if( ! (hcachename = hcache_filename()) )
	return;*/

	if( ! (f = fopen( file->cachefilename, "rb" )) )
		return;

	fseek( f, 0, SEEK_END );
	buffsize = ftell( f );
	fseek( f, 0, SEEK_SET );
	buffer_init( &buff );
	buffer_resize( &buff, buffsize + 1 );
	if ( fread( buffer_ptr( &buff ), buffsize, 1, f ) != 1 )
	{
		fclose( f );
		goto bail;
	}
	buffer_ptr( &buff )[buffsize] = 0;
	fclose( f );

	version = read_string( &buff );
	ch = buffer_getchar( &buff );
	if (!version || strcmp( version, CACHE_FILE_VERSION ) || ch != '\n' ) {
		goto bail;
	}

	for(;;) {
		int i, count, ch;
		LIST *l;

		c = &cachedata;

		c->boundname = read_string( &buff );
		if( !c->boundname ) /* Test for eof */
			break;

		c->time = read_int( &buff );
		c->age = read_int( &buff ) + 1; /* we're getting older... */

#ifdef OPT_BUILTIN_MD5CACHE_EXT
		c->mtime = read_int( &buff );
		read_md5sum( &buff, c->rulemd5sum );
		memcpy( &c->currentrulemd5sum, &c->rulemd5sum, MD5_SUMSIZE );
		read_md5sum( &buff, c->contentmd5sum );
		memcpy( &c->currentcontentmd5sum, &c->contentmd5sum, MD5_SUMSIZE );
#endif

		if( !c->boundname )
			goto bail;

		/* headers */
		count = read_int( &buff );
		for( l = 0, i = 0; i < count; ++i ) {
			const char *s = read_string( &buff );
			if( !s )
				goto bail;
			l = list_new( l, s, 0 );
		}
		c->includes = l;

		/* hdrscan */
		count = read_int( &buff );
		for( l = 0, i = 0; i < count; ++i ) {
			const char *s = read_string( &buff );
			if( !s )
				goto bail;
			l = list_new( l, s, 0 );
		}
		c->hdrscan = l;

		/* Read the newline */
		ch = skip_spaces( &buff );
		if( ch != '!' )
			goto bail;
		ch = skip_spaces( &buff );
		if( ch != '\n' )
			goto bail;

		if( !hashenter( file->hcachehash, (HASHDATA **)&c ) ) {
			printf( "jam: can't insert header cache item, bailing on %s\n",
				file->cachefilename );
			goto bail;
		}

		c->next = 0;
		if( last )
			last->next = c;
		else
			file->hcachelist = c;
		last = c;
	}

	bad_cache = 0;

	if( DEBUG_HEADER )
		printf( "hcache read from file %s\n", file->cachefilename );

bail:
	/* If its bad, no worries, it'll be overwritten in hcache_done() */
	if( bad_cache )
		printf( "jam: warning: the cache was invalid: %s\n", file->cachefilename );
	buffer_free( &buff );
}
Esempio n. 29
0
/* returns zero on failure */
static int buffer_assure_space(bson_buffer* buffer, int size) {
    if (buffer->position + size <= buffer->size) {
        return 1;
    }
    return buffer_resize(buffer, buffer->position + size);
}
Esempio n. 30
0
GSAPI bool gunderscript_import_bytecode(Gunderscript * instance, char * fileName) {
  DSValue value;
  FILE * inFile = fopen(fileName, "r");
  GSByteCodeHeader header;
  int i = 0;

  if(inFile == NULL) {
    instance->err = GUNDERSCRIPTERR_BAD_FILE_OPEN_READ;
    return false;
  }

  /* read header */
  if(fread(&header, sizeof(GSByteCodeHeader), 1, inFile) != 1) {
    instance->err = GUNDERSCRIPTERR_BAD_FILE_READ;
    fclose(inFile);
    return false;
  }

  /* check for header */
  if(strcmp(header.header, GS_BYTECODE_HEADER) != 0) {
    instance->err = GUNDERSCRIPTERR_NOT_BYTECODE_FILE;
    fclose(inFile);
    return false;
  }

  /* check that this build is the same as the one that created the file */
  if(strcmp(header.buildDate, GUNDERSCRIPT_BUILD_DATE) != 0) {
    instance->err = GUNDERSCRIPTERR_INCORRECT_RUNTIME_VERSION;
    fclose(inFile);
    return false;
  }

  /* check that the number of functions isn't negative or zero */
  if(header.numFunctions < 1) {
    instance->err = GUNDERSCRIPTERR_CORRUPTED_BYTECODE;
    return false;
  }

  /* import the exported functions definitions (script entry points) */
  for(i = 0; i < header.numFunctions; i++) {
    VMFunc * currentFunc = calloc(1, sizeof(VMFunc));
    char functionName[GS_MAX_FUNCTION_NAME_LEN];
    char functionNameLen;
    bool prevValue = false;

    /* check if VMFunc alloc failed */
    if(currentFunc == NULL) {
      instance->err = GUNDERSCRIPTERR_ALLOC_FAILED;
      fclose(inFile);
      return false;
    }

    /* read function name length */
    if(fread(&functionNameLen, sizeof(char), 1, inFile) != 1) {
      instance->err = GUNDERSCRIPTERR_BAD_FILE_READ;
      return false;
    }

    /* check function name length */
    if(functionNameLen > GS_MAX_FUNCTION_NAME_LEN) {
      instance->err = GUNDERSCRIPTERR_CORRUPTED_BYTECODE;
      fclose(inFile);
      return false;
    }

    /* read function name */
    if(fread(&functionName, sizeof(char), functionNameLen, inFile) 
       != functionNameLen) {
      instance->err = GUNDERSCRIPTERR_BAD_FILE_READ;
      fclose(inFile);
      return false;
    }
    
    /* read from file into new VMFunc */
    value.pointerVal = currentFunc;
    if(fread(currentFunc, sizeof(VMFunc), 1, inFile) != 1) {
      instance->err = GUNDERSCRIPTERR_BAD_FILE_READ;
      fclose(inFile);
      return false;
    }

    /* put functions into VM functions hashtable */
    if(!ht_put_raw_key(vm_functions(instance->vm), functionName, 
		       functionNameLen, &value, NULL, &prevValue)) {
      instance->err = GUNDERSCRIPTERR_ALLOC_FAILED;
      fclose(inFile);
      return false;
    }

    /* check for duplicate function names */
    if(prevValue) {
      instance->err = GUNDERSCRIPTERR_CORRUPTED_BYTECODE;
      fclose(inFile);
      return false;
    }
  }

  /* make space in buffer for the bytecode */
  if(!buffer_resize(vm_buffer(instance->vm), header.byteCodeLen)) {
    instance->err = GUNDERSCRIPTERR_ALLOC_FAILED;
    fclose(inFile);
    return false;
  }

  /* read raw bytecode from end of bytecode file */
  {
    int c, i;
    for(i = 0; (c = fgetc(inFile)) != -1; i++) {
      buffer_append_char(vm_buffer(instance->vm), (char)c);
    }

    if(i != (header.byteCodeLen)) {
      instance->err = GUNDERSCRIPTERR_BAD_FILE_READ;
      fclose(inFile);
      return false;
    }
  }

  fclose(inFile);
  return true;
}