Esempio n. 1
0
static inline unsigned
ole_bytes_left_in_block (GsfOutfileMSOle *ole)
{
	/* blocks are multiples of bb.size (the header is padded out to bb.size) */
	unsigned r = gsf_output_tell (ole->sink) % ole->bb.size;
	return (r != 0) ? (ole->bb.size - r) : 0;
}
Esempio n. 2
0
/* write the metadata (dirents, small block, xbats) and close the sink */
static gboolean
gsf_outfile_msole_close_root (GsfOutfileMSOle *ole)
{
	GsfOutfile *tmp;
	guint8  buf [OLE_HEADER_SIZE];
	guint32	sbat_start, num_sbat, sb_data_start, sb_data_size, sb_data_blocks;
	guint32	bat_start, num_bat, dirent_start, num_dirent_blocks, next, child_index;
	unsigned i, j, blocks, num_xbat, xbat_pos;
	gsf_off_t data_size;
	unsigned metabat_size = ole->bb.size / BAT_INDEX_SIZE - 1;
	GPtrArray *elem = ole->root->content.dir.root_order;

	/* write small block data */
	blocks = 0;
	sb_data_start = ole_cur_block (ole);
	data_size = gsf_output_tell (ole->sink);
	for (i = 0 ; i < elem->len ; i++) {
		GsfOutfileMSOle *child = g_ptr_array_index (elem, i);
		if (child->type == MSOLE_SMALL_BLOCK) {
			gsf_off_t size = gsf_output_size (GSF_OUTPUT (child));
			if (size > 0) {
				child->blocks = ((size - 1) >> ole->sb.shift) + 1;
				gsf_output_write (ole->sink,
						  child->blocks << ole->sb.shift,
						  child->content.small_block.buf);
				child->first_block = blocks;
				blocks += child->blocks;
			} else {
Esempio n. 3
0
static void
gsf_output_get_property (GObject     *object,
			 guint        property_id,
			 GValue      *value,
			 GParamSpec  *pspec)
{
	GsfOutput *output = GSF_OUTPUT (object);

	/* gsf_off_t is typedef'd to gint64 */

	switch (property_id) {
	case PROP_NAME:
		g_value_set_string (value, gsf_output_name (output));
		break;
	case PROP_SIZE:
		g_value_set_int64 (value, gsf_output_size (output));
		break;
	case PROP_CLOSED:
		g_value_set_boolean (value, gsf_output_is_closed (output));
		break;
	case PROP_POS:
		g_value_set_int64 (value, gsf_output_tell (output));
		break;
	case PROP_MODTIME:
		g_value_set_boxed (value, gsf_output_get_modtime (output));
		break;
	case PROP_CONTAINER:
		g_value_set_object (value, output->container);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}
Esempio n. 4
0
static void
gsf_output_get_property (GObject     *object,
			 guint        property_id,
			 GValue      *value,
			 GParamSpec  *pspec)
{
	/* gsf_off_t is typedef'd to gint64 */
	switch (property_id) {
	case PROP_NAME:
		g_value_set_string (value, gsf_output_name (GSF_OUTPUT (object)));
		break;
	case PROP_SIZE:
		g_value_set_int64 (value, gsf_output_size (GSF_OUTPUT (object)));
		break;
	case PROP_POS:
		g_value_set_int64 (value, gsf_output_tell (GSF_OUTPUT (object)));
		break;
	case PROP_CLOSED:
		g_value_set_boolean (value, gsf_output_is_closed (GSF_OUTPUT (object)));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}
Esempio n. 5
0
static gboolean
zip_close_root (GsfOutput *output)
{
	GsfOutfileZip *zip = GSF_OUTFILE_ZIP (output);
	GsfOutfileZip *child;
	gsf_off_t dirpos = gsf_output_tell (zip->sink);
	GPtrArray *elem = zip->root_order;
	unsigned entries = elem->len;
	unsigned i;

	/* Check that children are closed */
	for (i = 0 ; i < elem->len ; i++) {
		child = g_ptr_array_index (elem, i);
		if (!gsf_output_is_closed (GSF_OUTPUT (child))) {
			g_warning ("Child still open");
			return FALSE;
		}
	}

	/* Write directory */
	for (i = 0 ; i < entries ; i++) {
		child = g_ptr_array_index (elem, i);
		if (!zip_dirent_write (zip->sink, child->vdir->dirent))
			return FALSE;
	}

	disconnect_children (zip);

	return zip_trailer_write (zip, entries, dirpos);
}
Esempio n. 6
0
static gboolean
zip_trailer_write (GsfOutfileZip *zip, unsigned entries, gsf_off_t dirpos)
{
	static guint8 const trailer_signature[] =
		{ 'P', 'K', 0x05, 0x06 };
	guint8 buf[ZIP_TRAILER_SIZE];
	gsf_off_t pos = gsf_output_tell (zip->sink);

	memset (buf, 0, sizeof buf);
	memcpy (buf, trailer_signature, sizeof trailer_signature);
	GSF_LE_SET_GUINT16 (buf + ZIP_TRAILER_ENTRIES, entries);
	GSF_LE_SET_GUINT16 (buf + ZIP_TRAILER_TOTAL_ENTRIES, entries);
	GSF_LE_SET_GUINT32 (buf + ZIP_TRAILER_DIR_SIZE, pos - dirpos);
	GSF_LE_SET_GUINT32 (buf + ZIP_TRAILER_DIR_POS, dirpos);

	return gsf_output_write (zip->sink, sizeof buf, buf);
}
Esempio n. 7
0
static gboolean
zip_init_write (GsfOutput *output)
{
	GsfOutfileZip *zip = GSF_OUTFILE_ZIP (output);
	GsfZipDirent *dirent;
	int      ret;

	if (zip->root->writing) {
		g_warning ("Already writing to another stream in archive");
		return FALSE;
	}

	if (!gsf_output_wrap (G_OBJECT (output), zip->sink))
		return FALSE;

	dirent = zip_dirent_new_out (zip);
	dirent->offset = gsf_output_tell (zip->sink);
	if (zip->vdir->dirent)
		g_warning ("Leak.");

	zip->vdir->dirent = dirent;
	zip_header_write (zip);
	zip->writing = TRUE;
	zip->root->writing = TRUE;
	dirent->crc32 = crc32 (0L, Z_NULL, 0);
	if (zip->compression_method == GSF_ZIP_DEFLATED) {
		if (!zip->stream) {
			zip->stream = g_new0 (z_stream, 1);
		}
		ret = deflateInit2 (zip->stream, Z_DEFAULT_COMPRESSION,
				    Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL,
				    Z_DEFAULT_STRATEGY);
		if (ret != Z_OK)
			return FALSE;
		if (!zip->buf) {
			zip->buf_size = ZIP_BUF_SIZE;
			zip->buf = g_new (guint8, zip->buf_size);
		}
		zip->stream->next_out  = zip->buf;
		zip->stream->avail_out = zip->buf_size;
	}

	return TRUE;
}
Esempio n. 8
0
static gboolean
zip_header_write_sizes (GsfOutfileZip *zip)
{
	guint8 hbuf[ZIP_HEADER_SIZE];
	GsfZipDirent *dirent = zip->vdir->dirent;
	gsf_off_t pos = gsf_output_tell (zip->sink);

	if (!gsf_output_seek (zip->sink, dirent->offset + ZIP_HEADER_CRC,
			      G_SEEK_SET))
		return FALSE;

	GSF_LE_SET_GUINT32 (hbuf + ZIP_HEADER_CRC, dirent->crc32);
	GSF_LE_SET_GUINT32 (hbuf + ZIP_HEADER_COMP_SIZE, dirent->csize);
	GSF_LE_SET_GUINT32 (hbuf + ZIP_HEADER_UNCOMP_SIZE, dirent->usize);
	if (!gsf_output_write (zip->sink, 12, hbuf + ZIP_HEADER_CRC))
		return FALSE;
	if (!gsf_output_seek (zip->sink, pos, G_SEEK_SET))
		return FALSE;

	return TRUE;
}
Esempio n. 9
0
/* Calculate the block of the current offset in the file.  A useful idiom is to
 * pad_zero to move to the start of the next block, then get the block number.
 * This avoids fence post type problems with partial blocks. */
static inline guint32
ole_cur_block (GsfOutfileMSOle const *ole)
{
	return (gsf_output_tell (ole->sink) - OLE_HEADER_SIZE) >> ole->bb.shift;
}