From cd7322fd8726b1cd45761e0436c021ffca1bf485 Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Tue, 8 Oct 2013 21:22:14 +0200 Subject: [PATCH] app: port XCF loading/saving to GIO but for now restrict it to local files (see bug #709432). Thanks to Jehan and Sven for testing. --- app/xcf/xcf-load.c | 233 +++++++++++++++++++++--------------------- app/xcf/xcf-private.h | 4 +- app/xcf/xcf-read.c | 56 +++++----- app/xcf/xcf-read.h | 24 ++--- app/xcf/xcf-save.c | 65 ++++++------ app/xcf/xcf-seek.c | 43 ++++---- app/xcf/xcf-write.c | 50 ++++----- app/xcf/xcf-write.h | 8 +- app/xcf/xcf.c | 127 +++++++++++------------ 9 files changed, 291 insertions(+), 319 deletions(-) diff --git a/app/xcf/xcf-load.c b/app/xcf/xcf-load.c index 6c7ebeef85..f3c89abc94 100644 --- a/app/xcf/xcf-load.c +++ b/app/xcf/xcf-load.c @@ -17,7 +17,6 @@ #include "config.h" -#include #include #include @@ -150,15 +149,15 @@ xcf_load_image (Gimp *gimp, gint num_successful_elements = 0; /* read in the image width, height and type */ - info->cp += xcf_read_int32 (info->fp, (guint32 *) &width, 1); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &height, 1); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &image_type, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &width, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &height, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &image_type, 1); if (info->file_version >= 4) { gint p; - info->cp += xcf_read_int32 (info->fp, (guint32 *) &p, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &p, 1); if (info->file_version == 4) { @@ -217,7 +216,7 @@ xcf_load_image (Gimp *gimp, GList *item_path = NULL; /* read in the offset of the next layer */ - info->cp += xcf_read_int32 (info->fp, &offset, 1); + info->cp += xcf_read_int32 (info->input, &offset, 1); /* if the offset is 0 then we are at the end * of the layer list. @@ -301,7 +300,7 @@ xcf_load_image (Gimp *gimp, GimpChannel *channel; /* read in the offset of the next channel */ - info->cp += xcf_read_int32 (info->fp, &offset, 1); + info->cp += xcf_read_int32 (info->input, &offset, 1); /* if the offset is 0 then we are at the end * of the channel list. @@ -452,7 +451,7 @@ xcf_load_image_props (XcfInfo *info, guint32 n_colors; guchar cmap[GIMP_IMAGE_COLORMAP_SIZE]; - info->cp += xcf_read_int32 (info->fp, &n_colors, 1); + info->cp += xcf_read_int32 (info->input, &n_colors, 1); if (n_colors > (GIMP_IMAGE_COLORMAP_SIZE / 3)) { @@ -485,7 +484,7 @@ xcf_load_image_props (XcfInfo *info, } else { - info->cp += xcf_read_int8 (info->fp, cmap, n_colors * 3); + info->cp += xcf_read_int8 (info->input, cmap, n_colors * 3); } /* only set color map if image is indexed, this is just @@ -501,7 +500,7 @@ xcf_load_image_props (XcfInfo *info, { guint8 compression; - info->cp += xcf_read_int8 (info->fp, (guint8 *) &compression, 1); + info->cp += xcf_read_int8 (info->input, (guint8 *) &compression, 1); if ((compression != COMPRESS_NONE) && (compression != COMPRESS_RLE) && @@ -529,9 +528,9 @@ xcf_load_image_props (XcfInfo *info, nguides = prop_size / (4 + 1); for (i = 0; i < nguides; i++) { - info->cp += xcf_read_int32 (info->fp, + info->cp += xcf_read_int32 (info->input, (guint32 *) &position, 1); - info->cp += xcf_read_int8 (info->fp, + info->cp += xcf_read_int8 (info->input, (guint8 *) &orientation, 1); /* skip -1 guides from old XCFs */ @@ -572,8 +571,8 @@ xcf_load_image_props (XcfInfo *info, n_sample_points = prop_size / (4 + 4); for (i = 0; i < n_sample_points; i++) { - info->cp += xcf_read_int32 (info->fp, (guint32 *) &x, 1); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &y, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &x, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &y, 1); gimp_image_add_sample_point_at_pos (image, x, y, FALSE); } @@ -584,8 +583,8 @@ xcf_load_image_props (XcfInfo *info, { gfloat xres, yres; - info->cp += xcf_read_float (info->fp, &xres, 1); - info->cp += xcf_read_float (info->fp, &yres, 1); + info->cp += xcf_read_float (info->input, &xres, 1); + info->cp += xcf_read_float (info->input, &yres, 1); if (xres < GIMP_MIN_RESOLUTION || xres > GIMP_MAX_RESOLUTION || yres < GIMP_MIN_RESOLUTION || yres > GIMP_MAX_RESOLUTION) @@ -605,7 +604,7 @@ xcf_load_image_props (XcfInfo *info, case PROP_TATTOO: { - info->cp += xcf_read_int32 (info->fp, &info->tattoo_state, 1); + info->cp += xcf_read_int32 (info->input, &info->tattoo_state, 1); } break; @@ -635,7 +634,7 @@ xcf_load_image_props (XcfInfo *info, { guint32 unit; - info->cp += xcf_read_int32 (info->fp, &unit, 1); + info->cp += xcf_read_int32 (info->input, &unit, 1); if ((unit <= GIMP_UNIT_PIXEL) || (unit >= gimp_unit_get_number_of_built_in_units ())) @@ -664,9 +663,9 @@ xcf_load_image_props (XcfInfo *info, gint num_units; gint i; - info->cp += xcf_read_float (info->fp, &factor, 1); - info->cp += xcf_read_int32 (info->fp, &digits, 1); - info->cp += xcf_read_string (info->fp, unit_strings, 5); + info->cp += xcf_read_float (info->input, &factor, 1); + info->cp += xcf_read_int32 (info->input, &digits, 1); + info->cp += xcf_read_string (info->input, unit_strings, 5); for (i = 0; i < 5; i++) if (unit_strings[i] == NULL) @@ -774,7 +773,7 @@ xcf_load_layer_props (XcfInfo *info, case PROP_FLOATING_SELECTION: info->floating_sel = *layer; info->cp += - xcf_read_int32 (info->fp, + xcf_read_int32 (info->input, (guint32 *) &info->floating_sel_offset, 1); break; @@ -782,7 +781,7 @@ xcf_load_layer_props (XcfInfo *info, { guint32 opacity; - info->cp += xcf_read_int32 (info->fp, &opacity, 1); + info->cp += xcf_read_int32 (info->input, &opacity, 1); gimp_layer_set_opacity (*layer, (gdouble) opacity / 255.0, FALSE); } break; @@ -791,7 +790,7 @@ xcf_load_layer_props (XcfInfo *info, { gboolean visible; - info->cp += xcf_read_int32 (info->fp, (guint32 *) &visible, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &visible, 1); gimp_item_set_visible (GIMP_ITEM (*layer), visible, FALSE); } break; @@ -800,7 +799,7 @@ xcf_load_layer_props (XcfInfo *info, { gboolean linked; - info->cp += xcf_read_int32 (info->fp, (guint32 *) &linked, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &linked, 1); gimp_item_set_linked (GIMP_ITEM (*layer), linked, FALSE); } break; @@ -809,7 +808,7 @@ xcf_load_layer_props (XcfInfo *info, { gboolean lock_content; - info->cp += xcf_read_int32 (info->fp, (guint32 *) &lock_content, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &lock_content, 1); if (gimp_item_can_lock_content (GIMP_ITEM (*layer))) gimp_item_set_lock_content (GIMP_ITEM (*layer), @@ -821,7 +820,7 @@ xcf_load_layer_props (XcfInfo *info, { gboolean lock_alpha; - info->cp += xcf_read_int32 (info->fp, (guint32 *) &lock_alpha, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &lock_alpha, 1); if (gimp_layer_can_lock_alpha (*layer)) gimp_layer_set_lock_alpha (*layer, lock_alpha, FALSE); @@ -832,7 +831,7 @@ xcf_load_layer_props (XcfInfo *info, { gboolean lock_position; - info->cp += xcf_read_int32 (info->fp, (guint32 *) &lock_position, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &lock_position, 1); if (gimp_item_can_lock_position (GIMP_ITEM (*layer))) gimp_item_set_lock_position (GIMP_ITEM (*layer), @@ -841,15 +840,15 @@ xcf_load_layer_props (XcfInfo *info, break; case PROP_APPLY_MASK: - info->cp += xcf_read_int32 (info->fp, (guint32 *) apply_mask, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) apply_mask, 1); break; case PROP_EDIT_MASK: - info->cp += xcf_read_int32 (info->fp, (guint32 *) edit_mask, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) edit_mask, 1); break; case PROP_SHOW_MASK: - info->cp += xcf_read_int32 (info->fp, (guint32 *) show_mask, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) show_mask, 1); break; case PROP_OFFSETS: @@ -857,8 +856,8 @@ xcf_load_layer_props (XcfInfo *info, guint32 offset_x; guint32 offset_y; - info->cp += xcf_read_int32 (info->fp, &offset_x, 1); - info->cp += xcf_read_int32 (info->fp, &offset_y, 1); + info->cp += xcf_read_int32 (info->input, &offset_x, 1); + info->cp += xcf_read_int32 (info->input, &offset_y, 1); gimp_item_set_offset (GIMP_ITEM (*layer), offset_x, offset_y); } @@ -868,7 +867,7 @@ xcf_load_layer_props (XcfInfo *info, { guint32 mode; - info->cp += xcf_read_int32 (info->fp, &mode, 1); + info->cp += xcf_read_int32 (info->input, &mode, 1); gimp_layer_set_mode (*layer, (GimpLayerModeEffects) mode, FALSE); } break; @@ -877,7 +876,7 @@ xcf_load_layer_props (XcfInfo *info, { GimpTattoo tattoo; - info->cp += xcf_read_int32 (info->fp, (guint32 *) &tattoo, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &tattoo, 1); gimp_item_set_tattoo (GIMP_ITEM (*layer), tattoo); } break; @@ -905,7 +904,7 @@ xcf_load_layer_props (XcfInfo *info, break; case PROP_TEXT_LAYER_FLAGS: - info->cp += xcf_read_int32 (info->fp, text_layer_flags, 1); + info->cp += xcf_read_int32 (info->input, text_layer_flags, 1); break; case PROP_GROUP_ITEM: @@ -932,7 +931,7 @@ xcf_load_layer_props (XcfInfo *info, { guint32 index; - info->cp += xcf_read_int32 (info->fp, &index, 1); + info->cp += xcf_read_int32 (info->input, &index, 1); path = g_list_append (path, GUINT_TO_POINTER (index)); } @@ -942,7 +941,7 @@ xcf_load_layer_props (XcfInfo *info, break; case PROP_GROUP_ITEM_FLAGS: - info->cp += xcf_read_int32 (info->fp, group_layer_flags, 1); + info->cp += xcf_read_int32 (info->input, group_layer_flags, 1); break; default: @@ -1006,7 +1005,7 @@ xcf_load_channel_props (XcfInfo *info, { guint32 opacity; - info->cp += xcf_read_int32 (info->fp, &opacity, 1); + info->cp += xcf_read_int32 (info->input, &opacity, 1); gimp_channel_set_opacity (*channel, opacity / 255.0, FALSE); } break; @@ -1015,7 +1014,7 @@ xcf_load_channel_props (XcfInfo *info, { gboolean visible; - info->cp += xcf_read_int32 (info->fp, (guint32 *) &visible, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &visible, 1); gimp_item_set_visible (GIMP_ITEM (*channel), visible ? TRUE : FALSE, FALSE); } @@ -1025,7 +1024,7 @@ xcf_load_channel_props (XcfInfo *info, { gboolean linked; - info->cp += xcf_read_int32 (info->fp, (guint32 *) &linked, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &linked, 1); gimp_item_set_linked (GIMP_ITEM (*channel), linked ? TRUE : FALSE, FALSE); } @@ -1035,7 +1034,7 @@ xcf_load_channel_props (XcfInfo *info, { gboolean lock_content; - info->cp += xcf_read_int32 (info->fp, (guint32 *) &lock_content, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &lock_content, 1); gimp_item_set_lock_content (GIMP_ITEM (*channel), lock_content ? TRUE : FALSE, FALSE); } @@ -1045,7 +1044,7 @@ xcf_load_channel_props (XcfInfo *info, { gboolean lock_position; - info->cp += xcf_read_int32 (info->fp, (guint32 *) &lock_position, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &lock_position, 1); gimp_item_set_lock_position (GIMP_ITEM (*channel), lock_position ? TRUE : FALSE, FALSE); } @@ -1055,7 +1054,7 @@ xcf_load_channel_props (XcfInfo *info, { gboolean show_masked; - info->cp += xcf_read_int32 (info->fp, (guint32 *) &show_masked, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &show_masked, 1); gimp_channel_set_show_masked (*channel, show_masked); } break; @@ -1064,7 +1063,7 @@ xcf_load_channel_props (XcfInfo *info, { guchar col[3]; - info->cp += xcf_read_int8 (info->fp, (guint8 *) col, 3); + info->cp += xcf_read_int8 (info->input, (guint8 *) col, 3); gimp_rgb_set_uchar (&(*channel)->color, col[0], col[1], col[2]); } break; @@ -1073,7 +1072,7 @@ xcf_load_channel_props (XcfInfo *info, { GimpTattoo tattoo; - info->cp += xcf_read_int32 (info->fp, (guint32 *) &tattoo, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &tattoo, 1); gimp_item_set_tattoo (GIMP_ITEM (*channel), tattoo); } break; @@ -1119,12 +1118,12 @@ xcf_load_prop (XcfInfo *info, PropType *prop_type, guint32 *prop_size) { - if (G_UNLIKELY (xcf_read_int32 (info->fp, (guint32 *) prop_type, 1) != 4)) + if (G_UNLIKELY (xcf_read_int32 (info->input, (guint32 *) prop_type, 1) != 4)) return FALSE; info->cp += 4; - if (G_UNLIKELY (xcf_read_int32 (info->fp, (guint32 *) prop_size, 1) != 4)) + if (G_UNLIKELY (xcf_read_int32 (info->input, (guint32 *) prop_size, 1) != 4)) return FALSE; info->cp += 4; @@ -1163,10 +1162,10 @@ xcf_load_layer (XcfInfo *info, is_fs_drawable = (info->cp == info->floating_sel_offset); /* read in the layer width, height, type and name */ - info->cp += xcf_read_int32 (info->fp, (guint32 *) &width, 1); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &height, 1); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &type, 1); - info->cp += xcf_read_string (info->fp, &name, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &width, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &height, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &type, 1); + info->cp += xcf_read_string (info->input, &name, 1); switch (type) { @@ -1242,8 +1241,8 @@ xcf_load_layer (XcfInfo *info, } /* read the hierarchy and layer mask offsets */ - info->cp += xcf_read_int32 (info->fp, &hierarchy_offset, 1); - info->cp += xcf_read_int32 (info->fp, &layer_mask_offset, 1); + info->cp += xcf_read_int32 (info->input, &hierarchy_offset, 1); + info->cp += xcf_read_int32 (info->input, &layer_mask_offset, 1); /* read in the hierarchy (ignore it for group layers, both as an * optimization and because the hierarchy's extents don't match @@ -1323,9 +1322,9 @@ xcf_load_channel (XcfInfo *info, is_fs_drawable = (info->cp == info->floating_sel_offset); /* read in the layer width, height and name */ - info->cp += xcf_read_int32 (info->fp, (guint32 *) &width, 1); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &height, 1); - info->cp += xcf_read_string (info->fp, &name, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &width, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &height, 1); + info->cp += xcf_read_string (info->input, &name, 1); /* create a new channel */ channel = gimp_channel_new (image, width, height, name, &color); @@ -1340,7 +1339,7 @@ xcf_load_channel (XcfInfo *info, xcf_progress_update (info); /* read the hierarchy and layer mask offsets */ - info->cp += xcf_read_int32 (info->fp, &hierarchy_offset, 1); + info->cp += xcf_read_int32 (info->input, &hierarchy_offset, 1); /* read in the hierarchy */ if (!xcf_seek_pos (info, hierarchy_offset, NULL)) @@ -1381,9 +1380,9 @@ xcf_load_layer_mask (XcfInfo *info, is_fs_drawable = (info->cp == info->floating_sel_offset); /* read in the layer width, height and name */ - info->cp += xcf_read_int32 (info->fp, (guint32 *) &width, 1); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &height, 1); - info->cp += xcf_read_string (info->fp, &name, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &width, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &height, 1); + info->cp += xcf_read_string (info->input, &name, 1); /* create a new layer mask */ layer_mask = gimp_layer_mask_new (image, width, height, name, &color); @@ -1399,7 +1398,7 @@ xcf_load_layer_mask (XcfInfo *info, xcf_progress_update (info); /* read the hierarchy and layer mask offsets */ - info->cp += xcf_read_int32 (info->fp, &hierarchy_offset, 1); + info->cp += xcf_read_int32 (info->input, &hierarchy_offset, 1); /* read in the hierarchy */ if (! xcf_seek_pos (info, hierarchy_offset, NULL)) @@ -1436,9 +1435,9 @@ xcf_load_buffer (XcfInfo *info, format = gegl_buffer_get_format (buffer); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &width, 1); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &height, 1); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &bpp, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &width, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &height, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &bpp, 1); /* make sure the values in the file correspond to the values * calculated when the TileManager was created. @@ -1453,13 +1452,13 @@ xcf_load_buffer (XcfInfo *info, * as the number of levels found in the file. */ - info->cp += xcf_read_int32 (info->fp, &offset, 1); /* top level */ + info->cp += xcf_read_int32 (info->input, &offset, 1); /* top level */ /* discard offsets for layers below first, if any. */ do { - info->cp += xcf_read_int32 (info->fp, &junk, 1); + info->cp += xcf_read_int32 (info->input, &junk, 1); } while (junk != 0); @@ -1505,8 +1504,8 @@ xcf_load_level (XcfInfo *info, format = gegl_buffer_get_format (buffer); bpp = babl_format_get_bytes_per_pixel (format); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &width, 1); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &height, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &width, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &height, 1); if (width != gegl_buffer_get_width (buffer) || height != gegl_buffer_get_height (buffer)) @@ -1516,7 +1515,7 @@ xcf_load_level (XcfInfo *info, * if it is '0', then this tile level is empty * and we can simply return. */ - info->cp += xcf_read_int32 (info->fp, &offset, 1); + info->cp += xcf_read_int32 (info->input, &offset, 1); if (offset == 0) return TRUE; @@ -1545,7 +1544,7 @@ xcf_load_level (XcfInfo *info, /* read in the offset of the next tile so we can calculate the amount of data needed for this tile*/ - info->cp += xcf_read_int32 (info->fp, &offset2, 1); + info->cp += xcf_read_int32 (info->input, &offset2, 1); /* if the offset is 0 then we need to read in the maximum possible allowing for negative compression */ @@ -1595,7 +1594,7 @@ xcf_load_level (XcfInfo *info, return FALSE; /* read in the offset of the next tile */ - info->cp += xcf_read_int32 (info->fp, &offset, 1); + info->cp += xcf_read_int32 (info->input, &offset, 1); } if (offset != 0) @@ -1618,7 +1617,7 @@ xcf_load_tile (XcfInfo *info, gint tile_size = bpp * tile_rect->width * tile_rect->height; guchar *tile_data = g_alloca (tile_size); - info->cp += xcf_read_int8 (info->fp, tile_data, tile_size); + info->cp += xcf_read_int8 (info->input, tile_data, tile_size); gegl_buffer_set (buffer, tile_rect, 0, format, tile_data, GEGL_AUTO_ROWSTRIDE); @@ -1637,7 +1636,7 @@ xcf_load_tile_rle (XcfInfo *info, gint tile_size = bpp * tile_rect->width * tile_rect->height; guchar *tile_data = g_alloca (tile_size); gint i; - gint nmemb_read_successfully; + gsize nmemb_read_successfully; guchar *xcfdata; guchar *xcfodata; guchar *xcfdatalimit; @@ -1653,11 +1652,15 @@ xcf_load_tile_rle (XcfInfo *info, xcfdata = xcfodata = g_alloca (data_length); - /* we have to use fread instead of xcf_read_* because we may be + /* we have to read directly instead of xcf_read_* because we may be * reading past the end of the file here */ - nmemb_read_successfully = fread ((gchar *) xcfdata, sizeof (gchar), - data_length, info->fp); + g_input_stream_read_all (info->input, xcfdata, data_length, + &nmemb_read_successfully, NULL, NULL); + + if (nmemb_read_successfully == 0) + return TRUE; + info->cp += nmemb_read_successfully; xcfdatalimit = &xcfodata[nmemb_read_successfully - 1]; @@ -1770,9 +1773,9 @@ xcf_load_parasite (XcfInfo *info) guint32 size; gpointer data; - info->cp += xcf_read_string (info->fp, &name, 1); - info->cp += xcf_read_int32 (info->fp, &flags, 1); - info->cp += xcf_read_int32 (info->fp, &size, 1); + info->cp += xcf_read_string (info->input, &name, 1); + info->cp += xcf_read_int32 (info->input, &flags, 1); + info->cp += xcf_read_int32 (info->input, &size, 1); if (size > MAX_XCF_PARASITE_DATA_LEN) { @@ -1783,7 +1786,7 @@ xcf_load_parasite (XcfInfo *info) } data = g_new (gchar, size); - info->cp += xcf_read_int8 (info->fp, data, size); + info->cp += xcf_read_int8 (info->input, data, size); parasite = gimp_parasite_new (name, flags, size, data); @@ -1801,8 +1804,8 @@ xcf_load_old_paths (XcfInfo *info, guint32 last_selected_row; GimpVectors *active_vectors; - info->cp += xcf_read_int32 (info->fp, &last_selected_row, 1); - info->cp += xcf_read_int32 (info->fp, &num_paths, 1); + info->cp += xcf_read_int32 (info->input, &last_selected_row, 1); + info->cp += xcf_read_int32 (info->input, &num_paths, 1); while (num_paths-- > 0) xcf_load_old_path (info, image); @@ -1832,27 +1835,27 @@ xcf_load_old_path (XcfInfo *info, GimpVectorsCompatPoint *points; gint i; - info->cp += xcf_read_string (info->fp, &name, 1); - info->cp += xcf_read_int32 (info->fp, &locked, 1); - info->cp += xcf_read_int8 (info->fp, &state, 1); - info->cp += xcf_read_int32 (info->fp, &closed, 1); - info->cp += xcf_read_int32 (info->fp, &num_points, 1); - info->cp += xcf_read_int32 (info->fp, &version, 1); + info->cp += xcf_read_string (info->input, &name, 1); + info->cp += xcf_read_int32 (info->input, &locked, 1); + info->cp += xcf_read_int8 (info->input, &state, 1); + info->cp += xcf_read_int32 (info->input, &closed, 1); + info->cp += xcf_read_int32 (info->input, &num_points, 1); + info->cp += xcf_read_int32 (info->input, &version, 1); if (version == 2) { guint32 dummy; /* Had extra type field and points are stored as doubles */ - info->cp += xcf_read_int32 (info->fp, (guint32 *) &dummy, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &dummy, 1); } else if (version == 3) { guint32 dummy; /* Has extra tatto field */ - info->cp += xcf_read_int32 (info->fp, (guint32 *) &dummy, 1); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &tattoo, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &dummy, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &tattoo, 1); } else if (version != 1) { @@ -1877,9 +1880,9 @@ xcf_load_old_path (XcfInfo *info, gint32 x; gint32 y; - info->cp += xcf_read_int32 (info->fp, &points[i].type, 1); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &x, 1); - info->cp += xcf_read_int32 (info->fp, (guint32 *) &y, 1); + info->cp += xcf_read_int32 (info->input, &points[i].type, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &x, 1); + info->cp += xcf_read_int32 (info->input, (guint32 *) &y, 1); points[i].x = x; points[i].y = y; @@ -1889,9 +1892,9 @@ xcf_load_old_path (XcfInfo *info, gfloat x; gfloat y; - info->cp += xcf_read_int32 (info->fp, &points[i].type, 1); - info->cp += xcf_read_float (info->fp, &x, 1); - info->cp += xcf_read_float (info->fp, &y, 1); + info->cp += xcf_read_int32 (info->input, &points[i].type, 1); + info->cp += xcf_read_float (info->input, &x, 1); + info->cp += xcf_read_float (info->input, &y, 1); points[i].x = x; points[i].y = y; @@ -1929,7 +1932,7 @@ xcf_load_vectors (XcfInfo *info, g_printerr ("xcf_load_vectors\n"); #endif - info->cp += xcf_read_int32 (info->fp, &version, 1); + info->cp += xcf_read_int32 (info->input, &version, 1); if (version != 1) { @@ -1939,8 +1942,8 @@ xcf_load_vectors (XcfInfo *info, return FALSE; } - info->cp += xcf_read_int32 (info->fp, &active_index, 1); - info->cp += xcf_read_int32 (info->fp, &num_paths, 1); + info->cp += xcf_read_int32 (info->input, &active_index, 1); + info->cp += xcf_read_int32 (info->input, &num_paths, 1); #ifdef GIMP_XCF_PATH_DEBUG g_printerr ("%d paths (active: %d)\n", num_paths, active_index); @@ -1981,12 +1984,12 @@ xcf_load_vector (XcfInfo *info, g_printerr ("xcf_load_vector\n"); #endif - info->cp += xcf_read_string (info->fp, &name, 1); - info->cp += xcf_read_int32 (info->fp, &tattoo, 1); - info->cp += xcf_read_int32 (info->fp, &visible, 1); - info->cp += xcf_read_int32 (info->fp, &linked, 1); - info->cp += xcf_read_int32 (info->fp, &num_parasites, 1); - info->cp += xcf_read_int32 (info->fp, &num_strokes, 1); + info->cp += xcf_read_string (info->input, &name, 1); + info->cp += xcf_read_int32 (info->input, &tattoo, 1); + info->cp += xcf_read_int32 (info->input, &visible, 1); + info->cp += xcf_read_int32 (info->input, &linked, 1); + info->cp += xcf_read_int32 (info->input, &num_parasites, 1); + info->cp += xcf_read_int32 (info->input, &num_strokes, 1); #ifdef GIMP_XCF_PATH_DEBUG g_printerr ("name: %s, tattoo: %d, visible: %d, linked: %d, " @@ -2032,10 +2035,10 @@ xcf_load_vector (XcfInfo *info, g_value_init (&value, GIMP_TYPE_ANCHOR); - info->cp += xcf_read_int32 (info->fp, &stroke_type_id, 1); - info->cp += xcf_read_int32 (info->fp, &closed, 1); - info->cp += xcf_read_int32 (info->fp, &num_axes, 1); - info->cp += xcf_read_int32 (info->fp, &num_control_points, 1); + info->cp += xcf_read_int32 (info->input, &stroke_type_id, 1); + info->cp += xcf_read_int32 (info->input, &closed, 1); + info->cp += xcf_read_int32 (info->input, &num_axes, 1); + info->cp += xcf_read_int32 (info->input, &num_control_points, 1); #ifdef GIMP_XCF_PATH_DEBUG g_printerr ("stroke_type: %d, closed: %d, num_axes %d, len %d\n", @@ -2068,8 +2071,8 @@ xcf_load_vector (XcfInfo *info, for (j = 0; j < num_control_points; j++) { - info->cp += xcf_read_int32 (info->fp, &type, 1); - info->cp += xcf_read_float (info->fp, coords, num_axes); + info->cp += xcf_read_int32 (info->input, &type, 1); + info->cp += xcf_read_float (info->input, coords, num_axes); anchor.type = type; anchor.position.x = coords[0]; @@ -2119,11 +2122,11 @@ xcf_skip_unknown_prop (XcfInfo *info, while (size > 0) { - if (feof (info->fp)) + if (g_input_stream_is_closed (info->input)) return FALSE; amount = MIN (16, size); - info->cp += xcf_read_int8 (info->fp, buf, amount); + info->cp += xcf_read_int8 (info->input, buf, amount); size -= MIN (16, amount); } diff --git a/app/xcf/xcf-private.h b/app/xcf/xcf-private.h index eb05224df0..89e4f09c01 100644 --- a/app/xcf/xcf-private.h +++ b/app/xcf/xcf-private.h @@ -90,7 +90,9 @@ struct _XcfInfo { Gimp *gimp; GimpProgress *progress; - FILE *fp; + GInputStream *input; + GOutputStream *output; + GSeekable *seekable; guint cp; const gchar *filename; GimpTattoo tattoo_state; diff --git a/app/xcf/xcf-read.c b/app/xcf/xcf-read.c index d087c86479..ad16144cdc 100644 --- a/app/xcf/xcf-read.c +++ b/app/xcf/xcf-read.c @@ -17,9 +17,7 @@ #include "config.h" -#include - -#include +#include #include "libgimpbase/gimpbase.h" @@ -27,18 +25,20 @@ #include "gimp-intl.h" + #define MAX_XCF_STRING_LEN (16L * 1024 * 1024) + guint -xcf_read_int32 (FILE *fp, - guint32 *data, - gint count) +xcf_read_int32 (GInputStream *input, + guint32 *data, + gint count) { guint total = 0; if (count > 0) { - total += xcf_read_int8 (fp, (guint8 *) data, count * 4); + total += xcf_read_int8 (input, (guint8 *) data, count * 4); while (count--) { @@ -51,40 +51,30 @@ xcf_read_int32 (FILE *fp, } guint -xcf_read_float (FILE *fp, - gfloat *data, - gint count) +xcf_read_float (GInputStream *input, + gfloat *data, + gint count) { - return xcf_read_int32 (fp, (guint32 *) ((void *) data), count); + return xcf_read_int32 (input, (guint32 *) ((void *) data), count); } guint -xcf_read_int8 (FILE *fp, - guint8 *data, - gint count) +xcf_read_int8 (GInputStream *input, + guint8 *data, + gint count) { - guint total = 0; + gsize bytes_read; - while (count > 0) - { - gint bytes = fread ((char *) data, sizeof (char), count, fp); + g_input_stream_read_all (input, data, count, + &bytes_read, NULL, NULL); - if (bytes <= 0) /* something bad happened */ - break; - - total += bytes; - - count -= bytes; - data += bytes; - } - - return total; + return bytes_read; } guint -xcf_read_string (FILE *fp, - gchar **data, - gint count) +xcf_read_string (GInputStream *input, + gchar **data, + gint count) { guint total = 0; gint i; @@ -93,7 +83,7 @@ xcf_read_string (FILE *fp, { guint32 tmp; - total += xcf_read_int32 (fp, &tmp, 1); + total += xcf_read_int32 (input, &tmp, 1); if (tmp > MAX_XCF_STRING_LEN) { @@ -106,7 +96,7 @@ xcf_read_string (FILE *fp, gchar *str; str = g_new (gchar, tmp); - total += xcf_read_int8 (fp, (guint8*) str, tmp); + total += xcf_read_int8 (input, (guint8*) str, tmp); if (str[tmp - 1] != '\0') str[tmp - 1] = '\0'; diff --git a/app/xcf/xcf-read.h b/app/xcf/xcf-read.h index 3f7b2c3357..5f107f7068 100644 --- a/app/xcf/xcf-read.h +++ b/app/xcf/xcf-read.h @@ -19,18 +19,18 @@ #define __XCF_READ_H__ -guint xcf_read_int32 (FILE *fp, - guint32 *data, - gint count); -guint xcf_read_float (FILE *fp, - gfloat *data, - gint count); -guint xcf_read_int8 (FILE *fp, - guint8 *data, - gint count); -guint xcf_read_string (FILE *fp, - gchar **data, - gint count); +guint xcf_read_int32 (GInputStream *input, + guint32 *data, + gint count); +guint xcf_read_float (GInputStream *input, + gfloat *data, + gint count); +guint xcf_read_int8 (GInputStream *input, + guint8 *data, + gint count); +guint xcf_read_string (GInputStream *input, + gchar **data, + gint count); #endif /* __XCF_READ_H__ */ diff --git a/app/xcf/xcf-save.c b/app/xcf/xcf-save.c index d577971c52..d931f8175d 100644 --- a/app/xcf/xcf-save.c +++ b/app/xcf/xcf-save.c @@ -17,7 +17,6 @@ #include "config.h" -#include #include #include @@ -124,40 +123,40 @@ static gboolean xcf_save_vectors (XcfInfo *info, /* private convenience macros */ -#define xcf_write_int32_check_error(info, data, count) G_STMT_START { \ - info->cp += xcf_write_int32 (info->fp, data, count, &tmp_error); \ - if (tmp_error) \ - { \ - g_propagate_error (error, tmp_error); \ - return FALSE; \ - } \ +#define xcf_write_int32_check_error(info, data, count) G_STMT_START { \ + info->cp += xcf_write_int32 (info->output, data, count, &tmp_error); \ + if (tmp_error) \ + { \ + g_propagate_error (error, tmp_error); \ + return FALSE; \ + } \ } G_STMT_END -#define xcf_write_int8_check_error(info, data, count) G_STMT_START { \ - info->cp += xcf_write_int8 (info->fp, data, count, &tmp_error); \ - if (tmp_error) \ - { \ - g_propagate_error (error, tmp_error); \ - return FALSE; \ - } \ +#define xcf_write_int8_check_error(info, data, count) G_STMT_START { \ + info->cp += xcf_write_int8 (info->output, data, count, &tmp_error); \ + if (tmp_error) \ + { \ + g_propagate_error (error, tmp_error); \ + return FALSE; \ + } \ } G_STMT_END -#define xcf_write_float_check_error(info, data, count) G_STMT_START { \ - info->cp += xcf_write_float (info->fp, data, count, &tmp_error); \ - if (tmp_error) \ - { \ - g_propagate_error (error, tmp_error); \ - return FALSE; \ - } \ +#define xcf_write_float_check_error(info, data, count) G_STMT_START { \ + info->cp += xcf_write_float (info->output, data, count, &tmp_error); \ + if (tmp_error) \ + { \ + g_propagate_error (error, tmp_error); \ + return FALSE; \ + } \ } G_STMT_END -#define xcf_write_string_check_error(info, data, count) G_STMT_START { \ - info->cp += xcf_write_string (info->fp, data, count, &tmp_error); \ - if (tmp_error) \ - { \ - g_propagate_error (error, tmp_error); \ - return FALSE; \ - } \ +#define xcf_write_string_check_error(info, data, count) G_STMT_START { \ + info->cp += xcf_write_string (info->output, data, count, &tmp_error); \ + if (tmp_error) \ + { \ + g_propagate_error (error, tmp_error); \ + return FALSE; \ + } \ } G_STMT_END #define xcf_write_prop_type_check_error(info, prop_type) G_STMT_START { \ @@ -383,7 +382,7 @@ xcf_save_image (XcfInfo *info, xcf_write_int32_check_error (info, &offset, 1); saved_pos = info->cp; - return !ferror (info->fp); + return ! g_output_stream_is_closed (info->output); } static gboolean @@ -997,7 +996,7 @@ xcf_save_prop (XcfInfo *info, length = info->cp - base; /* go back to the saved position and write the length */ xcf_check_error (xcf_seek_pos (info, pos, error)); - xcf_write_int32 (info->fp, &length, 1, &tmp_error); + xcf_write_int32 (info->output, &length, 1, &tmp_error); if (tmp_error) { g_propagate_error (error, tmp_error); @@ -1044,7 +1043,7 @@ xcf_save_prop (XcfInfo *info, /* go back to the saved position and write the length */ xcf_check_error (xcf_seek_pos (info, pos, error)); - xcf_write_int32 (info->fp, &length, 1, &tmp_error); + xcf_write_int32 (info->output, &length, 1, &tmp_error); if (tmp_error) { g_propagate_error (error, tmp_error); @@ -1110,7 +1109,7 @@ xcf_save_prop (XcfInfo *info, /* go back to the saved position and write the length */ xcf_check_error (xcf_seek_pos (info, pos, error)); - xcf_write_int32 (info->fp, &length, 1, &tmp_error); + xcf_write_int32 (info->output, &length, 1, &tmp_error); if (tmp_error) { g_propagate_error (error, tmp_error); diff --git a/app/xcf/xcf-seek.c b/app/xcf/xcf-seek.c index e75eb5786a..955da5d375 100644 --- a/app/xcf/xcf-seek.c +++ b/app/xcf/xcf-seek.c @@ -17,10 +17,7 @@ #include "config.h" -#include -#include - -#include +#include #include "core/core-types.h" @@ -36,15 +33,19 @@ xcf_seek_pos (XcfInfo *info, { if (info->cp != pos) { - info->cp = pos; - if (fseek (info->fp, info->cp, SEEK_SET) == -1) - { - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), - _("Could not seek in XCF file: %s"), - g_strerror (errno)); + GError *my_error = NULL; + info->cp = pos; + + if (! g_seekable_seek (info->seekable, info->cp, G_SEEK_SET, + NULL, &my_error)) + { + g_propagate_prefixed_error (error, my_error, + _("Could not seek in XCF file: ")); return FALSE; } + + g_assert (info->cp == g_seekable_tell (info->seekable)); } return TRUE; @@ -54,25 +55,17 @@ gboolean xcf_seek_end (XcfInfo *info, GError **error) { - if (fseek (info->fp, 0, SEEK_END) == -1) - { - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), - _("Could not seek in XCF file: %s"), - g_strerror (errno)); + GError *my_error = NULL; + if (! g_seekable_seek (info->seekable, 0, G_SEEK_END, + NULL, &my_error)) + { + g_propagate_prefixed_error (error, my_error, + _("Could not seek in XCF file: ")); return FALSE; } - info->cp = ftell (info->fp); - - if (fseek (info->fp, 0, SEEK_END) == -1) - { - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), - _("Could not seek in XCF file: %s"), - g_strerror (errno)); - - return FALSE; - } + info->cp = g_seekable_tell (info->seekable); return TRUE; } diff --git a/app/xcf/xcf-write.c b/app/xcf/xcf-write.c index 6280d35400..2574cde2e7 100644 --- a/app/xcf/xcf-write.c +++ b/app/xcf/xcf-write.c @@ -17,11 +17,9 @@ #include "config.h" -#include -#include /* strlen */ -#include +#include -#include +#include #include "xcf-write.h" @@ -29,7 +27,7 @@ #include "gimp-intl.h" guint -xcf_write_int32 (FILE *fp, +xcf_write_int32 (GOutputStream *output, const guint32 *data, gint count, GError **error) @@ -43,7 +41,7 @@ xcf_write_int32 (FILE *fp, { guint32 tmp = g_htonl (data[i]); - xcf_write_int8 (fp, (const guint8 *) &tmp, 4, &tmp_error); + xcf_write_int8 (output, (const guint8 *) &tmp, 4, &tmp_error); if (tmp_error) { @@ -58,48 +56,40 @@ xcf_write_int32 (FILE *fp, } guint -xcf_write_float (FILE *fp, +xcf_write_float (GOutputStream *output, const gfloat *data, gint count, GError **error) { - return xcf_write_int32 (fp, + return xcf_write_int32 (output, (const guint32 *)((gconstpointer) data), count, error); } guint -xcf_write_int8 (FILE *fp, +xcf_write_int8 (GOutputStream *output, const guint8 *data, gint count, GError **error) { - guint total = count; + GError *my_error = NULL; + gsize bytes_written; - while (count > 0) + if (! g_output_stream_write_all (output, data, count, + &bytes_written, NULL, &my_error)) { - gint bytes = fwrite ((const gchar*) data, sizeof (gchar), count, fp); - - if (bytes == 0) - { - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), - _("Error writing XCF: %s"), g_strerror (errno)); - - return total; - } - - count -= bytes; - data += bytes; + g_propagate_prefixed_error (error, my_error, + _("Error writing XCF: ")); } - return total; + return bytes_written; } guint -xcf_write_string (FILE *fp, - gchar **data, - gint count, - GError **error) +xcf_write_string (GOutputStream *output, + gchar **data, + gint count, + GError **error) { GError *tmp_error = NULL; guint total = 0; @@ -114,7 +104,7 @@ xcf_write_string (FILE *fp, else tmp = 0; - xcf_write_int32 (fp, &tmp, 1, &tmp_error); + xcf_write_int32 (output, &tmp, 1, &tmp_error); if (tmp_error) { @@ -123,7 +113,7 @@ xcf_write_string (FILE *fp, } if (tmp > 0) - xcf_write_int8 (fp, (const guint8 *) data[i], tmp, &tmp_error); + xcf_write_int8 (output, (const guint8 *) data[i], tmp, &tmp_error); if (tmp_error) { diff --git a/app/xcf/xcf-write.h b/app/xcf/xcf-write.h index 8177f15497..cf5c5f8234 100644 --- a/app/xcf/xcf-write.h +++ b/app/xcf/xcf-write.h @@ -19,19 +19,19 @@ #define __XCF_WRITE_H__ -guint xcf_write_int32 (FILE *fp, +guint xcf_write_int32 (GOutputStream *output, const guint32 *data, gint count, GError **error); -guint xcf_write_float (FILE *fp, +guint xcf_write_float (GOutputStream *output, const gfloat *data, gint count, GError **error); -guint xcf_write_int8 (FILE *fp, +guint xcf_write_int8 (GOutputStream *output, const guint8 *data, gint count, GError **error); -guint xcf_write_string (FILE *fp, +guint xcf_write_string (GOutputStream *output, gchar **data, gint count, GError **error); diff --git a/app/xcf/xcf.c b/app/xcf/xcf.c index 7b8f464b14..b758cac614 100644 --- a/app/xcf/xcf.c +++ b/app/xcf/xcf.c @@ -105,6 +105,9 @@ xcf_init (Gimp *gimp) gimp_plug_in_procedure_set_image_types (proc, "RGB*, GRAY*, INDEXED*"); gimp_plug_in_procedure_set_file_proc (proc, "xcf", "", NULL); gimp_plug_in_procedure_set_mime_type (proc, "image/xcf"); +#ifdef GIO_IS_FIXED + gimp_plug_in_procedure_set_handles_uri (proc); +#endif gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-xcf-save"); gimp_procedure_set_static_strings (procedure, @@ -174,6 +177,9 @@ xcf_init (Gimp *gimp) gimp_plug_in_procedure_set_file_proc (proc, "xcf", "", "0,string,gimp\\040xcf\\040"); gimp_plug_in_procedure_set_mime_type (proc, "image/xcf"); +#ifdef GIO_IS_FIXED + gimp_plug_in_procedure_set_handles_uri (proc); +#endif gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-xcf-load"); gimp_procedure_set_static_strings (procedure, @@ -238,34 +244,35 @@ xcf_load_invoker (GimpProcedure *procedure, const GimpValueArray *args, GError **error) { - XcfInfo info; + XcfInfo info = { 0, }; GimpValueArray *return_vals; GimpImage *image = NULL; - const gchar *filename; + const gchar *uri; + gchar *filename; + GFile *file; gboolean success = FALSE; gchar id[14]; + GError *my_error = NULL; gimp_set_busy (gimp); - filename = g_value_get_string (gimp_value_array_index (args, 1)); + uri = g_value_get_string (gimp_value_array_index (args, 1)); +#ifdef GIO_IS_FIXED + file = g_file_new_for_uri (uri); +#else + file = g_file_new_for_path (uri); +#endif + filename = g_file_get_parse_name (file); - info.fp = g_fopen (filename, "rb"); + info.input = G_INPUT_STREAM (g_file_read (file, NULL, &my_error)); - if (info.fp) + if (info.input) { - info.gimp = gimp; - info.progress = progress; - info.cp = 0; - info.filename = filename; - info.tattoo_state = 0; - info.active_layer = NULL; - info.active_channel = NULL; - info.floating_sel_drawable = NULL; - info.floating_sel = NULL; - info.floating_sel_offset = 0; - info.swap_num = 0; - info.ref_count = NULL; - info.compression = COMPRESS_NONE; + info.gimp = gimp; + info.seekable = G_SEEKABLE (info.input); + info.progress = progress; + info.filename = filename; + info.compression = COMPRESS_NONE; if (progress) { @@ -280,7 +287,7 @@ xcf_load_invoker (GimpProcedure *procedure, success = TRUE; - info.cp += xcf_read_int8 (info.fp, (guint8 *) id, 14); + info.cp += xcf_read_int8 (info.input, (guint8 *) id, 14); if (! g_str_has_prefix (id, "gimp xcf ")) { @@ -318,20 +325,21 @@ xcf_load_invoker (GimpProcedure *procedure, } } - fclose (info.fp); + g_object_unref (info.input); if (progress) gimp_progress_end (progress); } else { - int save_errno = errno; - - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (save_errno), - _("Could not open '%s' for reading: %s"), - gimp_filename_to_utf8 (filename), g_strerror (save_errno)); + g_propagate_prefixed_error (error, my_error, + _("Could not open '%s' for reading: "), + filename); } + g_free (filename); + g_object_unref (file); + return_vals = gimp_procedure_get_return_values (procedure, success, error ? *error : NULL); @@ -351,33 +359,36 @@ xcf_save_invoker (GimpProcedure *procedure, const GimpValueArray *args, GError **error) { - XcfInfo info; + XcfInfo info = { 0, }; GimpValueArray *return_vals; GimpImage *image; - const gchar *filename; - gboolean success = FALSE; + const gchar *uri; + gchar *filename; + GFile *file; + gboolean success = FALSE; + GError *my_error = NULL; gimp_set_busy (gimp); image = gimp_value_get_image (gimp_value_array_index (args, 1), gimp); - filename = g_value_get_string (gimp_value_array_index (args, 3)); + uri = g_value_get_string (gimp_value_array_index (args, 3)); +#ifdef GIO_IS_FIXED + file = g_file_new_for_uri (uri); +#else + file = g_file_new_for_path (uri); +#endif + filename = g_file_get_parse_name (file); - info.fp = g_fopen (filename, "wb"); + info.output = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, 0, NULL, + &my_error)); - if (info.fp) + if (info.output) { - info.gimp = gimp; - info.progress = progress; - info.cp = 0; - info.filename = filename; - info.active_layer = NULL; - info.active_channel = NULL; - info.floating_sel_drawable = NULL; - info.floating_sel = NULL; - info.floating_sel_offset = 0; - info.swap_num = 0; - info.ref_count = NULL; - info.compression = COMPRESS_RLE; + info.gimp = gimp; + info.seekable = G_SEEKABLE (info.output); + info.progress = progress; + info.filename = filename; + info.compression = COMPRESS_RLE; if (progress) { @@ -394,37 +405,21 @@ xcf_save_invoker (GimpProcedure *procedure, success = xcf_save_image (&info, image, error); - if (success) - { - if (fclose (info.fp) == EOF) - { - int save_errno = errno; - - g_set_error (error, G_FILE_ERROR, - g_file_error_from_errno (save_errno), - _("Error saving XCF file: %s"), - g_strerror (save_errno)); - - success = FALSE; - } - } - else - { - fclose (info.fp); - } + g_object_unref (info.output); if (progress) gimp_progress_end (progress); } else { - int save_errno = errno; - - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (save_errno), - _("Could not open '%s' for writing: %s"), - gimp_filename_to_utf8 (filename), g_strerror (save_errno)); + g_propagate_prefixed_error (error, my_error, + _("Could not open '%s' for writing: "), + filename); } + g_free (filename); + g_object_unref (file); + return_vals = gimp_procedure_get_return_values (procedure, success, error ? *error : NULL);