[gimp] plug-ins: fix #5944 Unable to open XCF converted PSD files in Gimp and Photoshop- "Too many channels



commit 38c0344fa88c023b9e69d3c237a35f2e8fcac158
Author: Jacob Boerema <jgboerema gmail com>
Date:   Sun May 9 23:21:02 2021 -0400

    plug-ins: fix #5944 Unable to open XCF converted PSD files
    in Gimp and Photoshop- "Too many channels in layer: 4907"
    
    To be better able to handle 64 bit offsets we switch to
    using GInputStream/GOutputStream and its related
    functions instead of using FILE functions like fseek.
    
    In addition we changed several offsets and sizes to
    64 bit instead of 32 bit to correctly handle large
    image sizes and offsets.
    
    I should probably have split this out in two parts
    (the move to GInput/OutputStream, and the
    changing to 64 bit variables) but don't feel like
    it's worth the trouble at this point.

 plug-ins/file-psd/psd-image-res-load.c | 372 +++++++++--------
 plug-ins/file-psd/psd-image-res-load.h |  29 +-
 plug-ins/file-psd/psd-layer-res-load.c | 436 ++++++++++----------
 plug-ins/file-psd/psd-layer-res-load.h |  14 +-
 plug-ins/file-psd/psd-load.c           | 579 ++++++++++++++-------------
 plug-ins/file-psd/psd-save.c           | 702 ++++++++++++++++++---------------
 plug-ins/file-psd/psd-thumb-load.c     | 166 ++++----
 plug-ins/file-psd/psd-util.c           | 171 ++++----
 plug-ins/file-psd/psd-util.h           |  22 +-
 plug-ins/file-psd/psd.h                |  28 +-
 10 files changed, 1334 insertions(+), 1185 deletions(-)
---
diff --git a/plug-ins/file-psd/psd-image-res-load.c b/plug-ins/file-psd/psd-image-res-load.c
index b721c7930a..fd96af0eeb 100644
--- a/plug-ins/file-psd/psd-image-res-load.c
+++ b/plug-ins/file-psd/psd-image-res-load.c
@@ -138,126 +138,129 @@
 /*  Local function prototypes  */
 static gint     load_resource_unknown  (const PSDimageres     *res_a,
                                         GimpImage             *image,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_ps_only  (const PSDimageres     *res_a,
                                         GimpImage             *image,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1005     (const PSDimageres     *res_a,
                                         GimpImage             *image,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1006     (const PSDimageres     *res_a,
                                         GimpImage             *image,
                                         PSDimage              *img_a,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1007     (const PSDimageres     *res_a,
                                         GimpImage             *image,
                                         PSDimage              *img_a,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1008     (const PSDimageres     *res_a,
                                         GimpImage             *image,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1022     (const PSDimageres     *res_a,
                                         GimpImage             *image,
                                         PSDimage              *img_a,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1024     (const PSDimageres     *res_a,
                                         GimpImage             *image,
                                         PSDimage              *img_a,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1028     (const PSDimageres     *res_a,
                                         GimpImage             *image,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1032     (const PSDimageres     *res_a,
                                         GimpImage             *image,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
+/* 1033 - Thumbnail needs special handling since it calls the jpeg library
+ *        which needs a classic FILE. */
 static gint     load_resource_1033     (const PSDimageres     *res_a,
                                         GimpImage             *image,
-                                        FILE                  *f,
+                                        GFile                 *file,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1039     (const PSDimageres     *res_a,
                                         PSDimage              *img_a,
                                         GimpImage             *image,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1045     (const PSDimageres     *res_a,
                                         GimpImage             *image,
                                         PSDimage              *img_a,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1046     (const PSDimageres     *res_a,
                                         GimpImage             *image,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1053     (const PSDimageres     *res_a,
                                         GimpImage             *image,
                                         PSDimage              *img_a,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1058     (const PSDimageres     *res_a,
                                         GimpImage             *image,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1069     (const PSDimageres     *res_a,
                                         GimpImage             *image,
                                         PSDimage              *img_a,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_1077     (const PSDimageres     *res_a,
                                         GimpImage             *image,
                                         PSDimage              *img_a,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 static gint     load_resource_2000     (const PSDimageres     *res_a,
                                         GimpImage             *image,
-                                        FILE                  *f,
+                                        GInputStream          *input,
                                         GError               **error);
 
 /* Public Functions */
 gint
-get_image_resource_header (PSDimageres  *res_a,
-                           FILE         *f,
-                           GError      **error)
+get_image_resource_header (PSDimageres   *res_a,
+                           GInputStream  *input,
+                           GError       **error)
 {
   gint32        read_len;
   gint32        write_len;
   gchar        *name;
 
-  if (fread (&res_a->type, 4, 1, f) < 1
-      || fread (&res_a->id, 2, 1, f) < 1)
+  if (psd_read (input, &res_a->type, 4, error) < 4 ||
+      psd_read (input, &res_a->id,   2, error) < 2)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   res_a->id = GUINT16_FROM_BE (res_a->id);
-  name = fread_pascal_string (&read_len, &write_len, 2, f, error);
+  name = fread_pascal_string (&read_len, &write_len, 2, input, error);
   if (*error)
     return -1;
   if (name != NULL)
@@ -265,15 +268,15 @@ get_image_resource_header (PSDimageres  *res_a,
   else
     res_a->name[0] = 0x0;
   g_free (name);
-  if (fread (&res_a->data_len, 4, 1, f) < 1)
+  if (psd_read (input, &res_a->data_len, 4, error) < 4)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   res_a->data_len = GUINT32_FROM_BE (res_a->data_len);
-  res_a->data_start = ftell (f);
+  res_a->data_start = g_seekable_tell (G_SEEKABLE (input));
 
-  IFDBG(2) g_debug ("Type: %.4s, id: %d, start: %d, len: %d",
+  IFDBG(2) g_debug ("Type: %.4s, id: %d, start: %" G_GOFFSET_FORMAT ", len: %" G_GSIZE_FORMAT,
                     res_a->type, res_a->id, res_a->data_start, res_a->data_len);
 
   return 0;
@@ -283,7 +286,7 @@ gint
 load_image_resource (PSDimageres  *res_a,
                      GimpImage    *image,
                      PSDimage     *img_a,
-                     FILE         *f,
+                     GInputStream  *input,
                      gboolean     *resolution_loaded,
                      gboolean     *profile_loaded,
                      GError      **error)
@@ -291,9 +294,9 @@ load_image_resource (PSDimageres  *res_a,
   gint  pad;
 
   /* Set file position to start of image resource data block */
-  if (fseek (f, res_a->data_start, SEEK_SET) < 0)
+  if (! psd_seek (input, res_a->data_start, G_SEEK_SET, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
@@ -329,92 +332,92 @@ load_image_resource (PSDimageres  *res_a,
           case PSD_JPEG_QUAL:
             /* Save photoshop resources with no meaning for GIMP
               as image parasites */
-            load_resource_ps_only (res_a, image, f, error);
+            load_resource_ps_only (res_a, image, input, error);
             break;
 
           case PSD_RESN_INFO:
-            if (! load_resource_1005 (res_a, image, f, error))
+            if (! load_resource_1005 (res_a, image, input, error))
               *resolution_loaded = TRUE;
             break;
 
           case PSD_ALPHA_NAMES:
             if (! img_a->merged_image_only)
-              load_resource_1006 (res_a, image, img_a, f, error);
+              load_resource_1006 (res_a, image, img_a, input, error);
             break;
 
           case PSD_DISPLAY_INFO:
-            load_resource_1007 (res_a, image, img_a, f, error);
+            load_resource_1007 (res_a, image, img_a, input, error);
             break;
 
           case PSD_CAPTION:
-            load_resource_1008 (res_a, image, f, error);
+            load_resource_1008 (res_a, image, input, error);
             break;
 
           case PSD_QUICK_MASK:
             if (! img_a->merged_image_only)
-              load_resource_1022 (res_a, image, img_a, f, error);
+              load_resource_1022 (res_a, image, img_a, input, error);
             break;
 
           case PSD_LAYER_STATE:
             if (! img_a->merged_image_only)
-              load_resource_1024 (res_a, image, img_a, f, error);
+              load_resource_1024 (res_a, image, img_a, input, error);
             break;
 
           case PSD_WORKING_PATH:
             if (! img_a->merged_image_only)
-              load_resource_2000 (res_a, image, f, error);
+              load_resource_2000 (res_a, image, input, error);
             break;
 
           case PSD_IPTC_NAA_DATA:
-            load_resource_1028 (res_a, image, f, error);
+            load_resource_1028 (res_a, image, input, error);
             break;
 
           case PSD_GRID_GUIDE:
             if (! img_a->merged_image_only)
-              load_resource_1032 (res_a, image, f, error);
+              load_resource_1032 (res_a, image, input, error);
             break;
 
           case PSD_ICC_PROFILE:
-            if (! load_resource_1039 (res_a, img_a, image, f, error))
+            if (! load_resource_1039 (res_a, img_a, image, input, error))
               *profile_loaded = TRUE;
             break;
 
           case PSD_ALPHA_NAMES_UNI:
             if (! img_a->merged_image_only)
-              load_resource_1045 (res_a, image, img_a, f, error);
+              load_resource_1045 (res_a, image, img_a, input, error);
             break;
 
           case PSD_IDX_COL_TAB_CNT:
-            load_resource_1046 (res_a, image, f, error);
+            load_resource_1046 (res_a, image, input, error);
             break;
 
           case PSD_ALPHA_ID:
             if (! img_a->merged_image_only)
-              load_resource_1053 (res_a, image, img_a, f, error);
+              load_resource_1053 (res_a, image, img_a, input, error);
             break;
 
           case PSD_EXIF_DATA:
-            load_resource_1058 (res_a, image, f, error);
+            load_resource_1058 (res_a, image, input, error);
             break;
 
           case PSD_LAYER_SELECT_ID:
             if (! img_a->merged_image_only)
-              load_resource_1069 (res_a, image, img_a, f, error);
+              load_resource_1069 (res_a, image, img_a, input, error);
             break;
 
           case PSD_XMP_DATA:
             break;
 
           case PSD_DISPLAY_INFO_NEW:
-            load_resource_1077 (res_a, image, img_a, f, error);
+            load_resource_1077 (res_a, image, img_a, input, error);
             break;
 
           default:
             if (res_a->id >= 2000 &&
                 res_a->id <  2999)
-              load_resource_2000 (res_a, image, f, error);
+              load_resource_2000 (res_a, image, input, error);
             else
-              load_resource_unknown (res_a, image, f, error);
+              load_resource_unknown (res_a, image, input, error);
         }
     }
 
@@ -425,9 +428,9 @@ load_image_resource (PSDimageres  *res_a,
     pad = 1;
 
   /* Set file position to end of image resource block */
-  if (fseek (f, res_a->data_start + res_a->data_len + pad, SEEK_SET) < 0)
+  if (! psd_seek (input, res_a->data_start + res_a->data_len + pad, G_SEEK_SET, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
@@ -435,18 +438,19 @@ load_image_resource (PSDimageres  *res_a,
 }
 
 gint
-load_thumbnail_resource (PSDimageres  *res_a,
-                         GimpImage    *image,
-                         FILE         *f,
-                         GError      **error)
+load_thumbnail_resource (PSDimageres   *res_a,
+                         GimpImage     *image,
+                         GFile         *file,
+                         GInputStream  *input,
+                         GError       **error)
 {
   gint  rtn = 0;
   gint  pad;
 
   /* Set file position to start of image resource data block */
-  if (fseek (f, res_a->data_start, SEEK_SET) < 0)
+  if (! psd_seek (input, res_a->data_start, G_SEEK_SET, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
@@ -455,7 +459,7 @@ load_thumbnail_resource (PSDimageres  *res_a,
       || res_a->id == PSD_THUMB_RES2)
     {
       /* Load thumbnails from standard file load */
-      load_resource_1033 (res_a, image, f, error);
+      load_resource_1033 (res_a, image, file, input, error);
       rtn = 1;
     }
 
@@ -466,9 +470,9 @@ load_thumbnail_resource (PSDimageres  *res_a,
     pad = 1;
 
   /* Set file position to end of image resource block */
-  if (fseek (f, res_a->data_start + res_a->data_len + pad, SEEK_SET) < 0)
+  if (psd_seek (input, res_a->data_start + res_a->data_len + pad, G_SEEK_SET, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
@@ -480,7 +484,7 @@ load_thumbnail_resource (PSDimageres  *res_a,
 static gint
 load_resource_unknown (const PSDimageres  *res_a,
                        GimpImage          *image,
-                       FILE               *f,
+                       GInputStream       *input,
                        GError            **error)
 {
   /* Unknown image resources attached as parasites to re-save later */
@@ -491,9 +495,9 @@ load_resource_unknown (const PSDimageres  *res_a,
   IFDBG(2) g_debug ("Process unknown image resource block: %d", res_a->id);
 
   data = g_malloc (res_a->data_len);
-  if (res_a->data_len > 0 && fread (data, res_a->data_len, 1, f) < 1)
+  if (res_a->data_len > 0 && psd_read (input, data, res_a->data_len, error) < res_a->data_len)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       g_free (data);
       return -1;
     }
@@ -514,7 +518,7 @@ load_resource_unknown (const PSDimageres  *res_a,
 static gint
 load_resource_ps_only (const PSDimageres  *res_a,
                        GimpImage          *image,
-                       FILE               *f,
+                       GInputStream       *input,
                        GError            **error)
 {
   /* Save photoshop resources with no meaning for GIMP as image parasites
@@ -526,9 +530,9 @@ load_resource_ps_only (const PSDimageres  *res_a,
   IFDBG(3) g_debug ("Process image resource block: %d", res_a->id);
 
   data = g_malloc (res_a->data_len);
-  if (fread (data, res_a->data_len, 1, f) < 1)
+  if (psd_read (input, data, res_a->data_len, error) < res_a->data_len)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       g_free (data);
       return -1;
     }
@@ -549,7 +553,7 @@ load_resource_ps_only (const PSDimageres  *res_a,
 static gint
 load_resource_1005 (const PSDimageres  *res_a,
                     GimpImage          *image,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load image resolution and unit of measure */
@@ -561,14 +565,14 @@ load_resource_1005 (const PSDimageres  *res_a,
 
   IFDBG(2) g_debug ("Process image resource block 1005: Resolution Info");
 
-  if (fread (&res_info.hRes, 4, 1, f) < 1
-      || fread (&res_info.hResUnit, 2, 1, f) < 1
-      || fread (&res_info.widthUnit, 2, 1, f) < 1
-      || fread (&res_info.vRes, 4, 1, f) < 1
-      || fread (&res_info.vResUnit, 2, 1, f) < 1
-      || fread (&res_info.heightUnit, 2, 1, f) < 1)
+  if (psd_read (input, &res_info.hRes,       4, error) < 4 ||
+      psd_read (input, &res_info.hResUnit,   2, error) < 2 ||
+      psd_read (input, &res_info.widthUnit,  2, error) < 2 ||
+      psd_read (input, &res_info.vRes,       4, error) < 4 ||
+      psd_read (input, &res_info.vResUnit,   2, error) < 2 ||
+      psd_read (input, &res_info.heightUnit, 2, error) < 2)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   res_info.hRes = GINT32_FROM_BE (res_info.hRes);
@@ -614,7 +618,7 @@ static gint
 load_resource_1006 (const PSDimageres  *res_a,
                     GimpImage          *image,
                     PSDimage           *img_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load alpha channel names stored as a series of pascal strings
@@ -638,7 +642,7 @@ load_resource_1006 (const PSDimageres  *res_a,
   block_rem = res_a->data_len;
   while (block_rem > 1)
     {
-      str = fread_pascal_string (&read_len, &write_len, 1, f, error);
+      str = fread_pascal_string (&read_len, &write_len, 1, input, error);
       if (*error)
         return -1;
       IFDBG(3) g_debug ("String: %s, %d, %d", str, read_len, write_len);
@@ -656,7 +660,7 @@ static gint
 load_resource_1007 (const PSDimageres  *res_a,
                     GimpImage          *image,
                     PSDimage           *img_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load alpha channel display info */
@@ -678,13 +682,13 @@ load_resource_1007 (const PSDimageres  *res_a,
   img_a->alpha_display_count = tot_rec;
   for (cidx = 0; cidx < tot_rec; ++cidx)
     {
-      if (fread (&dsp_info.colorSpace, 2, 1, f) < 1
-          || fread (&dsp_info.color, 8, 1, f) < 1
-          || fread (&dsp_info.opacity, 2, 1, f) < 1
-          || fread (&dsp_info.kind, 1, 1, f) < 1
-          || fread (&dsp_info.padding, 1, 1, f) < 1)
+      if (psd_read (input, &dsp_info.colorSpace, 2, error) < 2 ||
+          psd_read (input, &dsp_info.color,      8, error) < 8 ||
+          psd_read (input, &dsp_info.opacity,    2, error) < 2 ||
+          psd_read (input, &dsp_info.kind,       1, error) < 1 ||
+          psd_read (input, &dsp_info.padding,    1, error) < 1)
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return -1;
         }
       dsp_info.colorSpace = GINT16_FROM_BE (dsp_info.colorSpace);
@@ -763,7 +767,7 @@ load_resource_1007 (const PSDimageres  *res_a,
 static gint
 load_resource_1008 (const PSDimageres  *res_a,
                     GimpImage          *image,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load image caption */
@@ -773,7 +777,7 @@ load_resource_1008 (const PSDimageres  *res_a,
   gint32         write_len;
 
   IFDBG(2) g_debug ("Process image resource block: 1008: Caption");
-  caption = fread_pascal_string (&read_len, &write_len, 1, f, error);
+  caption = fread_pascal_string (&read_len, &write_len, 1, input, error);
   if (*error)
     return -1;
 
@@ -791,7 +795,7 @@ static gint
 load_resource_1022 (const PSDimageres  *res_a,
                     GimpImage          *image,
                     PSDimage           *img_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load quick mask info */
@@ -799,10 +803,10 @@ load_resource_1022 (const PSDimageres  *res_a,
 
   IFDBG(2) g_debug ("Process image resource block: 1022: Quick Mask");
 
-  if (fread (&img_a->quick_mask_id, 2, 1, f) < 1
-      || fread (&quick_mask_empty, 1, 1, f) < 1)
+  if (psd_read (input, &img_a->quick_mask_id, 2, error) < 2 ||
+      psd_read (input, &quick_mask_empty,     1, error) < 1)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   img_a->quick_mask_id = GUINT16_FROM_BE (img_a->quick_mask_id);
@@ -818,15 +822,15 @@ static gint
 load_resource_1024 (const PSDimageres  *res_a,
                     GimpImage          *image,
                     PSDimage           *img_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load image layer state - current active layer counting from bottom up */
   IFDBG(2) g_debug ("Process image resource block: 1024: Layer State");
 
-  if (fread (&img_a->layer_state, 2, 1, f) < 1)
+  if (psd_read (input, &img_a->layer_state, 2, error) < 2)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   img_a->layer_state = GUINT16_FROM_BE (img_a->layer_state);
@@ -837,7 +841,7 @@ load_resource_1024 (const PSDimageres  *res_a,
 static gint
 load_resource_1028 (const PSDimageres  *res_a,
                     GimpImage          *image,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load IPTC data block */
@@ -856,9 +860,9 @@ load_resource_1028 (const PSDimageres  *res_a,
   IFDBG(2) g_debug ("Process image resource block: 1028: IPTC data");
 
   res_data = g_malloc (res_a->data_len);
-  if (fread (res_data, res_a->data_len, 1, f) < 1)
+  if (psd_read (input, res_data, res_a->data_len, error) < res_a->data_len)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       g_free (res_data);
       return -1;
     }
@@ -905,7 +909,7 @@ load_resource_1028 (const PSDimageres  *res_a,
 static gint
 load_resource_1032 (const PSDimageres  *res_a,
                     GimpImage          *image,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load grid and guides */
@@ -918,12 +922,12 @@ load_resource_1032 (const PSDimageres  *res_a,
 
   IFDBG(2) g_debug ("Process image resource block 1032: Grid and Guide Info");
 
-  if (fread (&hdr.fVersion, 4, 1, f) < 1
-      || fread (&hdr.fGridCycleV, 4, 1, f) < 1
-      || fread (&hdr.fGridCycleH, 4, 1, f) < 1
-      || fread (&hdr.fGuideCount, 4, 1, f) < 1)
+  if (psd_read (input, &hdr.fVersion,    4, error) < 4 ||
+      psd_read (input, &hdr.fGridCycleV, 4, error) < 4 ||
+      psd_read (input, &hdr.fGridCycleH, 4, error) < 4 ||
+      psd_read (input, &hdr.fGuideCount, 4, error) < 4)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   hdr.fVersion = GUINT32_FROM_BE (hdr.fVersion);
@@ -939,10 +943,10 @@ load_resource_1032 (const PSDimageres  *res_a,
 
   for (i = 0; i < hdr.fGuideCount; ++i)
     {
-      if (fread (&guide.fLocation, 4, 1, f) < 1
-          || fread (&guide.fDirection, 1, 1, f) < 1)
+      if (psd_read (input, &guide.fLocation,  4, error) < 4 ||
+          psd_read (input, &guide.fDirection, 1, error) < 1)
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return -1;
         }
       guide.fLocation = GUINT32_FROM_BE (guide.fLocation);
@@ -964,7 +968,8 @@ load_resource_1032 (const PSDimageres  *res_a,
 static gint
 load_resource_1033 (const PSDimageres  *res_a,
                     GimpImage          *image,
-                    FILE               *f,
+                    GFile              *file,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load thumbnail image */
@@ -972,6 +977,8 @@ load_resource_1033 (const PSDimageres  *res_a,
   struct jpeg_decompress_struct cinfo;
   struct jpeg_error_mgr         jerr;
 
+  gchar                *filename;
+  FILE                 *f;
   ThumbnailInfo         thumb_info;
   GeglBuffer           *buffer;
   const Babl           *format;
@@ -984,16 +991,16 @@ load_resource_1033 (const PSDimageres  *res_a,
   IFDBG(2) g_debug ("Process image resource block %d: Thumbnail Image", res_a->id);
 
   /* Read thumbnail resource header info */
-  if (fread (&thumb_info.format, 4, 1, f) < 1
-      || fread (&thumb_info.width, 4, 1, f) < 1
-      || fread (&thumb_info.height, 4, 1, f) < 1
-      || fread (&thumb_info.widthbytes, 4, 1, f) < 1
-      || fread (&thumb_info.size, 4, 1, f) < 1
-      || fread (&thumb_info.compressedsize, 4, 1, f) < 1
-      || fread (&thumb_info.bitspixel, 2, 1, f) < 1
-      || fread (&thumb_info.planes, 2, 1, f) < 1)
+  if (psd_read (input, &thumb_info.format,         4, error) < 4 ||
+      psd_read (input, &thumb_info.width,          4, error) < 4 ||
+      psd_read (input, &thumb_info.height,         4, error) < 4 ||
+      psd_read (input, &thumb_info.widthbytes,     4, error) < 4 ||
+      psd_read (input, &thumb_info.size,           4, error) < 4 ||
+      psd_read (input, &thumb_info.compressedsize, 4, error) < 4 ||
+      psd_read (input, &thumb_info.bitspixel,      2, error) < 2 ||
+      psd_read (input, &thumb_info.planes,         2, error) < 2)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   thumb_info.format = GINT32_FROM_BE (thumb_info.format);
@@ -1020,6 +1027,17 @@ load_resource_1033 (const PSDimageres  *res_a,
 
   /* Load Jpeg RGB thumbnail info */
 
+  /* Open input also as a FILE. */
+  filename = g_file_get_path (file);
+  f = g_fopen (filename, "rb");
+  g_free (filename);
+
+  if (! f)
+    return -1;
+
+  /* Now seek to the same position as we have in input. */
+  fseek(f, g_seekable_tell (G_SEEKABLE (input)), SEEK_SET);
+
   /* Step 1: Allocate and initialize JPEG decompression object */
   cinfo.err = jpeg_std_error (&jerr);
   jpeg_create_decompress (&cinfo);
@@ -1105,6 +1123,9 @@ load_resource_1033 (const PSDimageres  *res_a,
   g_free (buf);
   g_free (rgb_buf);
 
+  /* Close FILE */
+  fclose (f);
+
   /* At this point you may want to check to see whether any
    * corrupt-data warnings occurred (test whether
    * jerr.num_warnings is nonzero).
@@ -1119,7 +1140,7 @@ static gint
 load_resource_1039 (const PSDimageres  *res_a,
                     PSDimage           *img_a,
                     GimpImage          *image,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load ICC profile */
@@ -1129,9 +1150,9 @@ load_resource_1039 (const PSDimageres  *res_a,
   IFDBG(2) g_debug ("Process image resource block: 1039: ICC Profile");
 
   icc_profile = g_malloc (res_a->data_len);
-  if (fread (icc_profile, res_a->data_len, 1, f) < 1)
+  if (psd_read (input, icc_profile, res_a->data_len, error) < res_a->data_len)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       g_free (icc_profile);
       return -1;
     }
@@ -1162,7 +1183,7 @@ static gint
 load_resource_1045 (const PSDimageres  *res_a,
                     GimpImage          *image,
                     PSDimage           *img_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load alpha channel names stored as a series of unicode strings
@@ -1192,7 +1213,7 @@ load_resource_1045 (const PSDimageres  *res_a,
   block_rem = res_a->data_len;
   while (block_rem > 1)
     {
-      str = fread_unicode_string (&read_len, &write_len, 1, f, error);
+      str = fread_unicode_string (&read_len, &write_len, 1, input, error);
       if (*error)
         return -1;
 
@@ -1210,7 +1231,7 @@ load_resource_1045 (const PSDimageres  *res_a,
 static gint
 load_resource_1046 (const PSDimageres  *res_a,
                     GimpImage          *image,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load indexed color table count */
@@ -1220,9 +1241,9 @@ load_resource_1046 (const PSDimageres  *res_a,
 
   IFDBG(2) g_debug ("Process image resource block: 1046: Indexed Color Table Count");
 
-  if (fread (&index_count, 2, 1, f) < 1)
+  if (psd_read (input, &index_count, 2, error) < 2)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   index_count = GINT16_FROM_BE (index_count);
@@ -1243,7 +1264,7 @@ static gint
 load_resource_1053 (const PSDimageres  *res_a,
                     GimpImage          *image,
                     PSDimage           *img_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load image alpha channel ids (tattoos) */
@@ -1260,9 +1281,9 @@ load_resource_1053 (const PSDimageres  *res_a,
   img_a->alpha_id_count = tot_rec;
   for (cidx = 0; cidx < tot_rec; ++cidx)
     {
-      if (fread (&img_a->alpha_id[cidx], 4, 1, f) < 1)
+      if (psd_read (input, &img_a->alpha_id[cidx], 4, error) < 4)
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return -1;
         }
       img_a->alpha_id[cidx] = GUINT32_FROM_BE (img_a->alpha_id[cidx]);
@@ -1276,7 +1297,7 @@ load_resource_1053 (const PSDimageres  *res_a,
 static gint
 load_resource_1058 (const PSDimageres  *res_a,
                     GimpImage          *image,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   gchar        *name;
@@ -1287,9 +1308,9 @@ load_resource_1058 (const PSDimageres  *res_a,
   IFDBG(2) g_debug ("Process image resource block: 1058: Exif data");
 
   res_data = g_malloc (res_a->data_len);
-  if (fread (res_data, res_a->data_len, 1, f) < 1)
+  if (psd_read (input, res_data, res_a->data_len, error) < res_a->data_len)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       g_free (res_data);
       return -1;
     }
@@ -1313,7 +1334,7 @@ static gint
 load_resource_1069 (const PSDimageres  *res_a,
                     GimpImage          *image,
                     PSDimage           *img_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   guint16 layer_count;
@@ -1321,9 +1342,9 @@ load_resource_1069 (const PSDimageres  *res_a,
 
   IFDBG(2) g_debug ("Process image resource block: 1069: Layer Selection ID(s)");
 
-  if (fread (&layer_count, 2, 1, f) < 1)
+  if (psd_read (input, &layer_count, 2, error) < 2)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   layer_count = GUINT16_FROM_BE (layer_count);
@@ -1338,9 +1359,9 @@ load_resource_1069 (const PSDimageres  *res_a,
     {
       guint32 layer_id;
 
-      if (fread (&layer_id, 4, 1, f) < 1)
+      if (psd_read (input, &layer_id, 4, error) < 4)
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return -1;
         }
       layer_id = GUINT32_FROM_BE (layer_id);
@@ -1354,7 +1375,7 @@ static gint
 load_resource_1077 (const PSDimageres  *res_a,
                     GimpImage          *image,
                     PSDimage           *img_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load alpha channel display info */
@@ -1371,7 +1392,8 @@ load_resource_1077 (const PSDimageres  *res_a,
 
   /* For now, skip first 4 bytes since intention is unclear. Seems to be
      a version number that is always one, but who knows. */
-  fseek (f, 4, SEEK_CUR);
+  if (! psd_seek (input, 4, G_SEEK_CUR, error))
+    return -1;
 
   tot_rec = res_a->data_len / 13;
   if (tot_rec == 0)
@@ -1381,12 +1403,12 @@ load_resource_1077 (const PSDimageres  *res_a,
   img_a->alpha_display_count = tot_rec;
   for (cidx = 0; cidx < tot_rec; ++cidx)
     {
-      if (fread (&dsp_info.colorSpace, 2, 1, f) < 1
-          || fread (&dsp_info.color, 8, 1, f) < 1
-          || fread (&dsp_info.opacity, 2, 1, f) < 1
-          || fread (&dsp_info.mode, 1, 1, f) < 1)
+      if (psd_read (input, &dsp_info.colorSpace, 2, error) < 2 ||
+          psd_read (input, &dsp_info.color,      8, error) < 8 ||
+          psd_read (input, &dsp_info.opacity,    2, error) < 2 ||
+          psd_read (input, &dsp_info.mode,       1, error) < 1)
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return -1;
         }
       dsp_info.colorSpace = GINT16_FROM_BE (dsp_info.colorSpace);
@@ -1465,7 +1487,7 @@ load_resource_1077 (const PSDimageres  *res_a,
 static gint
 load_resource_2000 (const PSDimageres  *res_a,
                     GimpImage          *image,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   gdouble      *controlpoints;
@@ -1489,9 +1511,9 @@ load_resource_2000 (const PSDimageres  *res_a,
   if (path_rec ==0)
     return 0;
 
-  if (fread (&type, 2, 1, f) < 1)
+  if (psd_read (input, &type, 2, error) < 2)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   type = GINT16_FROM_BE (type);
@@ -1501,9 +1523,9 @@ load_resource_2000 (const PSDimageres  *res_a,
       return -1;
     }
 
-  if (fseek (f, 24, SEEK_CUR) < 0)
+  if (! psd_seek (input, 24, G_SEEK_CUR, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
@@ -1530,9 +1552,9 @@ load_resource_2000 (const PSDimageres  *res_a,
 
   while (path_rec > 0)
     {
-      if (fread (&type, 2, 1, f) < 1)
+      if (psd_read (input, &type, 2, error) < 2)
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return -1;
         }
       type = GINT16_FROM_BE (type);
@@ -1540,24 +1562,24 @@ load_resource_2000 (const PSDimageres  *res_a,
 
       if (type == PSD_PATH_FILL_RULE)
         {
-          if (fseek (f, 24, SEEK_CUR) < 0)
+          if (! psd_seek (input, 24, G_SEEK_CUR, error))
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               return -1;
             }
         }
 
       else if (type == PSD_PATH_FILL_INIT)
         {
-          if (fread (&init_fill, 2, 1, f) < 1)
+          if (psd_read (input, &init_fill, 2, error) < 2)
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               return -1;
             }
 
-          if (fseek (f, 22, SEEK_CUR) < 0)
+          if (! psd_seek (input, 22, G_SEEK_CUR, error))
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               return -1;
             }
         }
@@ -1565,18 +1587,18 @@ load_resource_2000 (const PSDimageres  *res_a,
       else if (type == PSD_PATH_CL_LEN
                || type == PSD_PATH_OP_LEN)
         {
-          if (fread (&num_rec, 2, 1, f) < 1)
+          if (psd_read (input, &num_rec, 2, error) < 2)
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               return -1;
             }
           num_rec = GINT16_FROM_BE (num_rec);
+          IFDBG(3) g_debug ("Num path records %d", num_rec);
           if (num_rec > path_rec)
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               return - 1;
             }
-          IFDBG(3) g_debug ("Num path records %d", num_rec);
 
           if (type == PSD_PATH_CL_LEN)
             closed = TRUE;
@@ -1584,18 +1606,18 @@ load_resource_2000 (const PSDimageres  *res_a,
             closed = FALSE;
           cntr = 0;
           controlpoints = g_malloc (sizeof (gdouble) * num_rec * 6);
-          if (fseek (f, 22, SEEK_CUR) < 0)
+          if (! psd_seek (input, 22, G_SEEK_CUR, error))
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               g_free (controlpoints);
               return -1;
             }
 
           while (num_rec > 0)
             {
-              if (fread (&type, 2, 1, f) < 1)
+              if (psd_read (input, &type, 2, error) < 2)
                 {
-                  psd_set_error (feof (f), errno, error);
+                  psd_set_error (error);
                   return -1;
                 }
               type = GINT16_FROM_BE (type);
@@ -1606,14 +1628,14 @@ load_resource_2000 (const PSDimageres  *res_a,
                   || type == PSD_PATH_OP_LNK
                   || type == PSD_PATH_OP_UNLNK)
                 {
-                  if (fread (&y[0], 4, 1, f) < 1
-                      || fread (&x[0], 4, 1, f) < 1
-                      || fread (&y[1], 4, 1, f) < 1
-                      || fread (&x[1], 4, 1, f) < 1
-                      || fread (&y[2], 4, 1, f) < 1
-                      || fread (&x[2], 4, 1, f) < 1)
+                  if (psd_read (input, &y[0], 4, error) < 4 ||
+                      psd_read (input, &x[0], 4, error) < 4 ||
+                      psd_read (input, &y[1], 4, error) < 4 ||
+                      psd_read (input, &x[1], 4, error) < 4 ||
+                      psd_read (input, &y[2], 4, error) < 4 ||
+                      psd_read (input, &x[2], 4, error) < 4)
                     {
-                      psd_set_error (feof (f), errno, error);
+                      psd_set_error (error);
                       return -1;
                     }
                   for (i = 0; i < 3; ++i)
@@ -1631,9 +1653,9 @@ load_resource_2000 (const PSDimageres  *res_a,
               else
                 {
                   IFDBG(1) g_debug ("Unexpected path type record %d", type);
-                  if (fseek (f, 24, SEEK_CUR) < 0)
+                  if (! psd_seek (input, 24, G_SEEK_CUR, error))
                     {
-                      psd_set_error (feof (f), errno, error);
+                      psd_set_error (error);
                       return -1;
                     }
                 }
@@ -1649,9 +1671,9 @@ load_resource_2000 (const PSDimageres  *res_a,
 
       else
         {
-          if (fseek (f, 24, SEEK_CUR) < 0)
+          if (! psd_seek (input, 24, G_SEEK_CUR, error))
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               return -1;
             }
         }
diff --git a/plug-ins/file-psd/psd-image-res-load.h b/plug-ins/file-psd/psd-image-res-load.h
index c21a995929..33a8bf9fa6 100644
--- a/plug-ins/file-psd/psd-image-res-load.h
+++ b/plug-ins/file-psd/psd-image-res-load.h
@@ -22,22 +22,23 @@
 #define __PSD_IMAGE_RES_LOAD_H__
 
 
-gint  get_image_resource_header (PSDimageres  *res_a,
-                                 FILE         *f,
-                                 GError      **error);
+gint  get_image_resource_header (PSDimageres   *res_a,
+                                 GInputStream  *input,
+                                 GError       **error);
 
-gint  load_image_resource       (PSDimageres  *res_a,
-                                 GimpImage    *image,
-                                 PSDimage     *img_a,
-                                 FILE         *f,
-                                 gboolean     *resolution_loaded,
-                                 gboolean     *profile_loaded,
-                                 GError      **error);
+gint  load_image_resource       (PSDimageres   *res_a,
+                                 GimpImage     *image,
+                                 PSDimage      *img_a,
+                                 GInputStream  *input,
+                                 gboolean      *resolution_loaded,
+                                 gboolean      *profile_loaded,
+                                 GError       **error);
 
-gint  load_thumbnail_resource   (PSDimageres  *res_a,
-                                 GimpImage    *image,
-                                 FILE         *f,
-                                 GError      **error);
+gint  load_thumbnail_resource   (PSDimageres   *res_a,
+                                 GimpImage     *image,
+                                 GFile         *file,
+                                 GInputStream  *input,
+                                 GError       **error);
 
 
 #endif /* __PSD_IMAGE_RES_LOAD_H__ */
diff --git a/plug-ins/file-psd/psd-layer-res-load.c b/plug-ins/file-psd/psd-layer-res-load.c
index d2207b30a8..460825809f 100644
--- a/plug-ins/file-psd/psd-layer-res-load.c
+++ b/plug-ins/file-psd/psd-layer-res-load.c
@@ -137,96 +137,97 @@
 /*  Local function prototypes  */
 static gint     load_resource_unknown (const PSDlayerres     *res_a,
                                        PSDlayer              *lyr_a,
-                                       FILE                  *f,
+                                       GInputStream          *input,
                                        GError               **error);
 
 static gint     load_resource_ladj    (const PSDlayerres     *res_a,
                                        PSDlayer              *lyr_a,
-                                       FILE                  *f,
+                                       GInputStream          *input,
                                        GError               **error);
 
 static gint     load_resource_lfil    (const PSDlayerres     *res_a,
                                        PSDlayer              *lyr_a,
-                                       FILE                  *f,
+                                       GInputStream          *input,
                                        GError               **error);
 
 static gint     load_resource_lfx     (const PSDlayerres     *res_a,
                                        PSDlayer              *lyr_a,
-                                       FILE                  *f,
+                                       GInputStream          *input,
                                        GError               **error);
 
 static gint     load_resource_ltyp    (const PSDlayerres     *res_a,
                                        PSDlayer              *lyr_a,
-                                       FILE                  *f,
+                                       GInputStream          *input,
                                        GError               **error);
 
 static gint     load_resource_luni    (const PSDlayerres     *res_a,
                                        PSDlayer              *lyr_a,
-                                       FILE                  *f,
+                                       GInputStream          *input,
                                        GError               **error);
 
 static gint     load_resource_lyid    (const PSDlayerres     *res_a,
                                        PSDlayer              *lyr_a,
-                                       FILE                  *f,
+                                       GInputStream          *input,
                                        GError               **error);
 
 static gint     load_resource_lclr    (const PSDlayerres     *res_a,
                                        PSDlayer              *lyr_a,
-                                       FILE                  *f,
+                                       GInputStream          *input,
                                        GError               **error);
 
 static gint     load_resource_lsct    (const PSDlayerres     *res_a,
                                        PSDlayer              *lyr_a,
-                                       FILE                  *f,
+                                       GInputStream          *input,
                                        GError               **error);
 
 static gint     load_resource_lrfx    (const PSDlayerres     *res_a,
                                        PSDlayer              *lyr_a,
-                                       FILE                  *f,
+                                       GInputStream          *input,
                                        GError               **error);
 
 static gint     load_resource_lyvr    (const PSDlayerres     *res_a,
                                        PSDlayer              *lyr_a,
-                                       FILE                  *f,
+                                       GInputStream          *input,
                                        GError               **error);
 
 static gint     load_resource_lnsr    (const PSDlayerres     *res_a,
                                        PSDlayer              *lyr_a,
-                                       FILE                  *f,
+                                       GInputStream          *input,
                                        GError               **error);
 
 /* Public Functions */
 gint
-get_layer_resource_header (PSDlayerres  *res_a,
-                           FILE         *f,
-                           GError      **error)
+get_layer_resource_header (PSDlayerres   *res_a,
+                           GInputStream  *input,
+                           GError       **error)
 {
-  if (fread (res_a->sig, 4, 1, f) < 1
-      || fread (res_a->key, 4, 1, f) < 1
-      || fread (&res_a->data_len, 4, 1, f) < 1)
+  g_debug ("get_layer_resource_header");
+  if (psd_read (input, res_a->sig,       4, error) < 4 ||
+      psd_read (input, res_a->key,       4, error) < 4 ||
+      psd_read (input, &res_a->data_len, 4, error) < 4)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   res_a->data_len = GUINT32_FROM_BE (res_a->data_len);
-  res_a->data_start = ftell (f);
+  res_a->data_start = g_seekable_tell (G_SEEKABLE (input));
 
-  IFDBG(2) g_debug ("Sig: %.4s, key: %.4s, start: %d, len: %d",
+  IFDBG(2) g_debug ("Sig: %.4s, key: %.4s, start: %" G_GOFFSET_FORMAT ", len: %" G_GOFFSET_FORMAT,
                      res_a->sig, res_a->key, res_a->data_start, res_a->data_len);
 
   return 0;
 }
 
 gint
-load_layer_resource (PSDlayerres  *res_a,
-                     PSDlayer     *lyr_a,
-                     FILE         *f,
-                     GError      **error)
+load_layer_resource (PSDlayerres   *res_a,
+                     PSDlayer      *lyr_a,
+                     GInputStream  *input,
+                     GError       **error)
 {
   /* Set file position to start of layer resource data block */
-  if (fseek (f, res_a->data_start, SEEK_SET) < 0)
+  if (! psd_seek (input, res_a->data_start, G_SEEK_SET, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
@@ -252,51 +253,54 @@ load_layer_resource (PSDlayerres  *res_a,
           || memcmp (res_a->key, PSD_LADJ_THRESHOLD, 4) == 0
           || memcmp (res_a->key, PSD_LADJ_INVERT, 4) == 0
           || memcmp (res_a->key, PSD_LADJ_POSTERIZE, 4) == 0)
-        load_resource_ladj (res_a, lyr_a, f, error);
+        load_resource_ladj (res_a, lyr_a, input, error);
 
       else if (memcmp (res_a->key, PSD_LFIL_SOLID, 4) == 0
                || memcmp (res_a->key, PSD_LFIL_PATTERN, 4) == 0
                || memcmp (res_a->key, PSD_LFIL_GRADIENT, 4) == 0)
-        load_resource_lfil (res_a, lyr_a, f, error);
+        load_resource_lfil (res_a, lyr_a, input, error);
 
       else if (memcmp (res_a->key, PSD_LFX_FX, 4) == 0
                || memcmp (res_a->key, PSD_LFX_FX2, 4) == 0)
-        load_resource_lfx (res_a, lyr_a, f, error);
+        load_resource_lfx (res_a, lyr_a, input, error);
 
       else if (memcmp (res_a->key, PSD_LTYP_TYPE, 4) == 0
                || memcmp (res_a->key, PSD_LTYP_TYPE2, 4) == 0)
-        load_resource_ltyp (res_a, lyr_a, f, error);
+        load_resource_ltyp (res_a, lyr_a, input, error);
 
       else if (memcmp (res_a->key, PSD_LPRP_UNICODE, 4) == 0)
-        load_resource_luni (res_a, lyr_a, f, error);
+        load_resource_luni (res_a, lyr_a, input, error);
 
       else if (memcmp (res_a->key, PSD_LPRP_ID, 4) == 0)
-        load_resource_lyid (res_a, lyr_a, f, error);
+        load_resource_lyid (res_a, lyr_a, input, error);
 
       else if (memcmp (res_a->key, PSD_LPRP_COLOR, 4) == 0)
-        load_resource_lclr (res_a, lyr_a, f, error);
+        load_resource_lclr (res_a, lyr_a, input, error);
 
       else if (memcmp (res_a->key, PSD_LOTH_SECTION, 4) == 0
                || memcmp (res_a->key, PSD_LOTH_SECTION2, 4) == 0) /* bug #789981 */
-        load_resource_lsct (res_a, lyr_a, f, error);
+        load_resource_lsct (res_a, lyr_a, input, error);
 
       else if (memcmp (res_a->key, PSD_LFX_FX, 4) == 0)
-        load_resource_lrfx (res_a, lyr_a, f, error);
+        load_resource_lrfx (res_a, lyr_a, input, error);
 
       else if (memcmp (res_a->key, PSD_LPRP_VERSION, 4) == 0)
-        load_resource_lyvr (res_a, lyr_a, f, error);
+        load_resource_lyvr (res_a, lyr_a, input, error);
 
       else if (memcmp (res_a->key, PSD_LPRP_SOURCE, 4) == 0)
-        load_resource_lnsr (res_a, lyr_a, f, error);
+        load_resource_lnsr (res_a, lyr_a, input, error);
 
       else
-        load_resource_unknown (res_a, lyr_a, f, error);
+        load_resource_unknown (res_a, lyr_a, input, error);
     }
 
+  if (error && *error)
+    return -1;
+
   /* Set file position to end of layer resource block */
-  if (fseek (f, res_a->data_start + res_a->data_len, SEEK_SET) < 0)
+  if (! psd_seek (input, res_a->data_start + res_a->data_len, G_SEEK_SET, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
@@ -308,7 +312,7 @@ load_layer_resource (PSDlayerres  *res_a,
 static gint
 load_resource_unknown (const PSDlayerres  *res_a,
                        PSDlayer           *lyr_a,
-                       FILE               *f,
+                       GInputStream       *input,
                        GError            **error)
 {
   IFDBG(2) g_debug ("Process unknown layer resource block: %.4s", res_a->key);
@@ -319,7 +323,7 @@ load_resource_unknown (const PSDlayerres  *res_a,
 static gint
 load_resource_ladj (const PSDlayerres  *res_a,
                     PSDlayer           *lyr_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load adjustment layer */
@@ -342,7 +346,7 @@ load_resource_ladj (const PSDlayerres  *res_a,
 static gint
 load_resource_lfil (const PSDlayerres  *res_a,
                     PSDlayer           *lyr_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load fill layer */
@@ -364,7 +368,7 @@ load_resource_lfil (const PSDlayerres  *res_a,
 static gint
 load_resource_lfx (const PSDlayerres  *res_a,
                    PSDlayer           *lyr_a,
-                   FILE               *f,
+                   GInputStream       *input,
                    GError            **error)
 {
   /* Load layer effects */
@@ -386,7 +390,7 @@ load_resource_lfx (const PSDlayerres  *res_a,
 static gint
 load_resource_ltyp (const PSDlayerres  *res_a,
                     PSDlayer           *lyr_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load type tool layer */
@@ -418,17 +422,17 @@ load_resource_ltyp (const PSDlayerres  *res_a,
   /* New style type tool layers (ps6) */
   if (memcmp (res_a->key, PSD_LTYP_TYPE2, 4) == 0)
     {
-      if (fread (&version, 2, 1, f) < 1
-          || fread (&t_xx, 8, 1, f) < 1
-          || fread (&t_xy, 8, 1, f) < 1
-          || fread (&t_yx, 8, 1, f) < 1
-          || fread (&t_yy, 8, 1, f) < 1
-          || fread (&t_tx, 8, 1, f) < 1
-          || fread (&t_ty, 8, 1, f) < 1
-          || fread (&text_desc_vers, 2, 1, f) < 1
-          || fread (&desc_version, 4, 1, f) < 1)
+      if (psd_read (input, &version, 2, error) < 2 ||
+          psd_read (input, &t_xx,    8, error) < 8 ||
+          psd_read (input, &t_xy,    8, error) < 8 ||
+          psd_read (input, &t_yx,    8, error) < 8 ||
+          psd_read (input, &t_yy,    8, error) < 8 ||
+          psd_read (input, &t_tx,    8, error) < 8 ||
+          psd_read (input, &t_ty,    8, error) < 8 ||
+          psd_read (input, &text_desc_vers, 2, error) < 2 ||
+          psd_read (input, &desc_version,   4, error) < 4)
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return -1;
         }
 
@@ -457,7 +461,7 @@ load_resource_ltyp (const PSDlayerres  *res_a,
                         lyr_a->text.xx, lyr_a->text.xy, lyr_a->text.yx,
                         lyr_a->text.yy, lyr_a->text.tx, lyr_a->text.ty);
 
-      classID = fread_unicode_string (&read_len, &write_len, 4, f, error);
+      classID = fread_unicode_string (&read_len, &write_len, 4, input, error);
       IFDBG(2) g_debug ("Unicode name: %s", classID);
     }
 
@@ -467,7 +471,7 @@ load_resource_ltyp (const PSDlayerres  *res_a,
 static gint
 load_resource_luni (const PSDlayerres  *res_a,
                     PSDlayer           *lyr_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load layer name in unicode (length padded to multiple of 4 bytes) */
@@ -478,7 +482,7 @@ load_resource_luni (const PSDlayerres  *res_a,
   if (lyr_a->name)
     g_free (lyr_a->name);
 
-  lyr_a->name = fread_unicode_string (&read_len, &write_len, 4, f, error);
+  lyr_a->name = fread_unicode_string (&read_len, &write_len, 4, input, error);
   if (*error)
     return -1;
   IFDBG(3) g_debug ("Unicode name: %s", lyr_a->name);
@@ -489,15 +493,15 @@ load_resource_luni (const PSDlayerres  *res_a,
 static gint
 load_resource_lyid (const PSDlayerres  *res_a,
                     PSDlayer           *lyr_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load layer id (tattoo) */
 
   IFDBG(2) g_debug ("Process layer resource block lyid: Layer ID");
-  if (fread (&lyr_a->id, 4, 1, f) < 1)
+  if (psd_read (input, &lyr_a->id, 4, error) < 4)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   lyr_a->id = GUINT32_FROM_BE (lyr_a->id);
@@ -509,16 +513,16 @@ load_resource_lyid (const PSDlayerres  *res_a,
 static gint
 load_resource_lclr (const PSDlayerres  *res_a,
                     PSDlayer           *lyr_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load layer sheet color code */
   IFDBG(2) g_debug ("Process layer resource block %.4s: Sheet color",
                     res_a->key);
 
-  if (fread (lyr_a->color_tag, 8, 1, f) < 1)
+  if (psd_read (input, lyr_a->color_tag, 8, error) < 8)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
@@ -533,7 +537,7 @@ load_resource_lclr (const PSDlayerres  *res_a,
 static gint
 load_resource_lsct (const PSDlayerres  *res_a,
                     PSDlayer           *lyr_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   /* Load layer group & type information
@@ -544,9 +548,9 @@ load_resource_lsct (const PSDlayerres  *res_a,
   guint32           type;
 
   IFDBG(2) g_debug ("Process layer resource block %.4s: Section divider", res_a->key);
-  if (fread (&type, 4, 1, f) < 1)
+  if (psd_read (input, &type, 4, error) < 4)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   type = GUINT32_FROM_BE (type);
@@ -559,10 +563,10 @@ load_resource_lsct (const PSDlayerres  *res_a,
       gchar signature[4];
       gchar blend_mode[4];
 
-      if (fread (signature,  4, 1, f) < 1 ||
-          fread (blend_mode, 4, 1, f) < 1)
+      if (psd_read (input, signature,  4, error) < 4 ||
+          psd_read (input, blend_mode, 4, error) < 4)
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return -1;
         }
       if (memcmp (signature, "8BIM", 4) == 0)
@@ -583,7 +587,7 @@ load_resource_lsct (const PSDlayerres  *res_a,
 static gint
 load_resource_lrfx (const PSDlayerres  *res_a,
                     PSDlayer           *lyr_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   gint16    version;
@@ -594,19 +598,19 @@ load_resource_lrfx (const PSDlayerres  *res_a,
 
   IFDBG(2) g_debug ("Process layer resource block %.4s: Layer effects", res_a->key);
 
-  if (fread (&version, 2, 1, f) < 1
-      || fread (&count, 2, 1, f) < 1)
+  if (psd_read (input, &version, 2, error) < 2 ||
+      psd_read (input, &count,   2, error) < 2)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
   for (i = 0; i < count; i++)
     {
-      if (fread (&signature, 4, 1, f) < 1
-          || fread(&effectname, 4, 1, f) < 1)
+      if (psd_read (input, &signature,  4, error) < 4 ||
+          psd_read (input, &effectname, 4, error) < 4)
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return -1;
         }
 
@@ -623,12 +627,12 @@ load_resource_lrfx (const PSDlayerres  *res_a,
               gchar     visible;
               gint16    unused;
 
-              if (fread (&size, 4, 1, f) < 1
-                  || fread(&ver, 4, 1, f) < 1
-                  || fread(&visible, 1, 1, f) < 1
-                  || fread(&unused, 2, 1, f) < 1)
+              if (psd_read (input, &size,    4, error) < 4 ||
+                  psd_read (input, &ver,     4, error) < 4 ||
+                  psd_read (input, &visible, 1, error) < 1 ||
+                  psd_read (input, &unused,  2, error) < 2)
                 {
-                  psd_set_error (feof (f), errno, error);
+                  psd_set_error (error);
                   return -1;
                 }
             }
@@ -649,29 +653,29 @@ load_resource_lrfx (const PSDlayerres  *res_a,
               gchar     opacity;
               gint16    natcolor[5];
 
-              if (fread (&size, 4, 1, f) < 1
-                  || fread(&ver, 4, 1, f) < 1
-                  || fread(&blur, 4, 1, f) < 1
-                  || fread(&intensity, 4, 1, f) < 1
-                  || fread(&angle, 4, 1, f) < 1
-                  || fread(&distance, 4, 1, f) < 1
-                  || fread(&color[0], 2, 1, f) < 1
-                  || fread(&color[1], 2, 1, f) < 1
-                  || fread(&color[2], 2, 1, f) < 1
-                  || fread(&color[3], 2, 1, f) < 1
-                  || fread(&color[4], 2, 1, f) < 1
-                  || fread(&blendsig, 4, 1, f) < 1
-                  || fread(&effect, 4, 1, f) < 1
-                  || fread(&effecton, 1, 1, f) < 1
-                  || fread(&anglefx, 1, 1, f) < 1
-                  || fread(&opacity, 1, 1, f) < 1
-                  || fread(&natcolor[0], 2, 1, f) < 1
-                  || fread(&natcolor[1], 2, 1, f) < 1
-                  || fread(&natcolor[2], 2, 1, f) < 1
-                  || fread(&natcolor[3], 2, 1, f) < 1
-                  || fread(&natcolor[4], 2, 1, f) < 1)
+              if (psd_read (input, &size,        4, error) < 4 ||
+                  psd_read (input, &ver,         4, error) < 4 ||
+                  psd_read (input, &blur,        4, error) < 4 ||
+                  psd_read (input, &intensity,   4, error) < 4 ||
+                  psd_read (input, &angle,       4, error) < 4 ||
+                  psd_read (input, &distance,    4, error) < 4 ||
+                  psd_read (input, &color[0],    2, error) < 2 ||
+                  psd_read (input, &color[1],    2, error) < 2 ||
+                  psd_read (input, &color[2],    2, error) < 2 ||
+                  psd_read (input, &color[3],    2, error) < 2 ||
+                  psd_read (input, &color[4],    2, error) < 2 ||
+                  psd_read (input, &blendsig,    4, error) < 4 ||
+                  psd_read (input, &effect,      4, error) < 4 ||
+                  psd_read (input, &effecton,    1, error) < 1 ||
+                  psd_read (input, &anglefx,     1, error) < 1 ||
+                  psd_read (input, &opacity,     1, error) < 1 ||
+                  psd_read (input, &natcolor[0], 2, error) < 2 ||
+                  psd_read (input, &natcolor[1], 2, error) < 2 ||
+                  psd_read (input, &natcolor[2], 2, error) < 2 ||
+                  psd_read (input, &natcolor[3], 2, error) < 2 ||
+                  psd_read (input, &natcolor[4], 2, error) < 2)
                 {
-                  psd_set_error (feof (f), errno, error);
+                  psd_set_error (error);
                   return -1;
                 }
             }
@@ -688,33 +692,33 @@ load_resource_lrfx (const PSDlayerres  *res_a,
               gchar     opacity;
               gint16    natcolor[5];
 
-              if (fread (&size, 4, 1, f) < 1
-                  || fread(&ver, 4, 1, f) < 1
-                  || fread(&blur, 4, 1, f) < 1
-                  || fread(&intensity, 4, 1, f) < 1
-                  || fread(&color[0], 2, 1, f) < 1
-                  || fread(&color[1], 2, 1, f) < 1
-                  || fread(&color[2], 2, 1, f) < 1
-                  || fread(&color[3], 2, 1, f) < 1
-                  || fread(&color[4], 2, 1, f) < 1
-                  || fread(&blendsig, 4, 1, f) < 1
-                  || fread(&effect, 4, 1, f) < 1
-                  || fread(&effecton, 1, 1, f) < 1
-                  || fread(&opacity, 1, 1, f) < 1)
+              if (psd_read (input, &size,      4, error) < 4 ||
+                  psd_read (input, &ver,       4, error) < 4 ||
+                  psd_read (input, &blur,      4, error) < 4 ||
+                  psd_read (input, &intensity, 4, error) < 4 ||
+                  psd_read (input, &color[0],  2, error) < 2 ||
+                  psd_read (input, &color[1],  2, error) < 2 ||
+                  psd_read (input, &color[2],  2, error) < 2 ||
+                  psd_read (input, &color[3],  2, error) < 2 ||
+                  psd_read (input, &color[4],  2, error) < 2 ||
+                  psd_read (input, &blendsig,  4, error) < 4 ||
+                  psd_read (input, &effect,    4, error) < 4 ||
+                  psd_read (input, &effecton,  1, error) < 1 ||
+                  psd_read (input, &opacity,   1, error) < 1)
                 {
-                  psd_set_error (feof (f), errno, error);
+                  psd_set_error (error);
                   return -1;
                 }
 
               if (size == 42)
                 {
-                  if (fread(&natcolor[0], 2, 1, f) < 1
-                      || fread(&natcolor[1], 2, 1, f) < 1
-                      || fread(&natcolor[2], 2, 1, f) < 1
-                      || fread(&natcolor[3], 2, 1, f) < 1
-                      || fread(&natcolor[4], 2, 1, f) < 1)
+                  if (psd_read (input, &natcolor[0], 2, error) < 2 ||
+                      psd_read (input, &natcolor[1], 2, error) < 2 ||
+                      psd_read (input, &natcolor[2], 2, error) < 2 ||
+                      psd_read (input, &natcolor[3], 2, error) < 2 ||
+                      psd_read (input, &natcolor[4], 2, error) < 2)
                     {
-                      psd_set_error (feof (f), errno, error);
+                      psd_set_error (error);
                       return -1;
                     }
                 }
@@ -736,43 +740,43 @@ load_resource_lrfx (const PSDlayerres  *res_a,
               gchar     invert;
               gint16    natcolor[5];
 
-              if (fread (&size, 4, 1, f) < 1
-                  || fread(&ver, 4, 1, f) < 1
-                  || fread(&blur, 4, 1, f) < 1
-                  || fread(&intensity, 4, 1, f) < 1
-                  || fread(&angle, 4, 1, f) < 1
-                  || fread(&distance, 4, 1, f) < 1
-                  || fread(&color[0], 2, 1, f) < 1
-                  || fread(&color[1], 2, 1, f) < 1
-                  || fread(&color[2], 2, 1, f) < 1
-                  || fread(&color[3], 2, 1, f) < 1
-                  || fread(&color[4], 2, 1, f) < 1
-                  || fread(&blendsig, 4, 1, f) < 1
-                  || fread(&effect, 4, 1, f) < 1
-                  || fread(&effecton, 1, 1, f) < 1
-                  || fread(&anglefx, 1, 1, f) < 1
-                  || fread(&opacity, 1, 1, f) < 1
-                  || fread(&natcolor[0], 2, 1, f) < 1
-                  || fread(&natcolor[1], 2, 1, f) < 1
-                  || fread(&natcolor[2], 2, 1, f) < 1
-                  || fread(&natcolor[3], 2, 1, f) < 1
-                  || fread(&natcolor[4], 2, 1, f) < 1)
+              if (psd_read (input, &size,        4, error) < 4 ||
+                  psd_read (input, &ver,         4, error) < 4 ||
+                  psd_read (input, &blur,        4, error) < 4 ||
+                  psd_read (input, &intensity,   4, error) < 4 ||
+                  psd_read (input, &angle,       4, error) < 4 ||
+                  psd_read (input, &distance,    4, error) < 4 ||
+                  psd_read (input, &color[0],    2, error) < 2 ||
+                  psd_read (input, &color[1],    2, error) < 2 ||
+                  psd_read (input, &color[2],    2, error) < 2 ||
+                  psd_read (input, &color[3],    2, error) < 2 ||
+                  psd_read (input, &color[4],    2, error) < 2 ||
+                  psd_read (input, &blendsig,    4, error) < 4 ||
+                  psd_read (input, &effect,      4, error) < 4 ||
+                  psd_read (input, &effecton,    1, error) < 1 ||
+                  psd_read (input, &anglefx,     1, error) < 1 ||
+                  psd_read (input, &opacity,     1, error) < 1 ||
+                  psd_read (input, &natcolor[0], 2, error) < 2 ||
+                  psd_read (input, &natcolor[1], 2, error) < 2 ||
+                  psd_read (input, &natcolor[2], 2, error) < 2 ||
+                  psd_read (input, &natcolor[3], 2, error) < 2 ||
+                  psd_read (input, &natcolor[4], 2, error) < 2)
                 {
-                  psd_set_error (feof (f), errno, error);
+                  psd_set_error (error);
                   return -1;
                 }
 
               if (size == 43)
                 {
-                  if (fread (&invert, 1, 1, f) < 1
-                      || fread(&natcolor[0], 2, 1, f) < 1
-                      || fread(&natcolor[0], 2, 1, f) < 1
-                      || fread(&natcolor[1], 2, 1, f) < 1
-                      || fread(&natcolor[2], 2, 1, f) < 1
-                      || fread(&natcolor[3], 2, 1, f) < 1
-                      || fread(&natcolor[4], 2, 1, f) < 1)
+                  if (psd_read (input, &invert,      1, error) < 1 ||
+                      psd_read (input, &natcolor[0], 2, error) < 2 ||
+                      psd_read (input, &natcolor[0], 2, error) < 2 ||
+                      psd_read (input, &natcolor[1], 2, error) < 2 ||
+                      psd_read (input, &natcolor[2], 2, error) < 2 ||
+                      psd_read (input, &natcolor[3], 2, error) < 2 ||
+                      psd_read (input, &natcolor[4], 2, error) < 2)
                     {
-                      psd_set_error (feof (f), errno, error);
+                      psd_set_error (error);
                       return -1;
                     }
                 }
@@ -799,52 +803,52 @@ load_resource_lrfx (const PSDlayerres  *res_a,
               gint16    highlightnatcolor[5];
               gint16    shadownatcolor[5];
 
-              if (fread (&size, 4, 1, f) < 1
-                  || fread(&ver, 4, 1, f) < 1
-                  || fread(&angle, 4, 1, f) < 1
-                  || fread(&strength, 4, 1, f) < 1
-                  || fread(&blur, 4, 1, f) < 1
-                  || fread(&highlightsig, 4, 1, f) < 1
-                  || fread(&highlighteffect, 4, 1, f) < 1
-                  || fread(&shadowsig, 4, 1, f) < 1
-                  || fread(&highlightcolor[0], 2, 1, f) < 1
-                  || fread(&shadoweffect, 4, 1, f) < 1
-                  || fread(&highlightcolor[1], 2, 1, f) < 1
-                  || fread(&highlightcolor[2], 2, 1, f) < 1
-                  || fread(&highlightcolor[3], 2, 1, f) < 1
-                  || fread(&highlightcolor[4], 2, 1, f) < 1
-                  || fread(&shadowcolor[0], 2, 1, f) < 1
-                  || fread(&shadowcolor[1], 2, 1, f) < 1
-                  || fread(&shadowcolor[2], 2, 1, f) < 1
-                  || fread(&shadowcolor[3], 2, 1, f) < 1
-                  || fread(&shadowcolor[4], 2, 1, f) < 1
-                  || fread(&style, 1, 1, f) < 1
-                  || fread(&highlightopacity, 1, 1, f) < 1
-                  || fread(&shadowopacity, 1, 1, f) < 1
-                  || fread(&enabled, 1, 1, f) < 1
-                  || fread(&global, 1, 1, f) < 1
-                  || fread(&direction, 1, 1, f) < 1)
+              if (psd_read (input, &size,              4, error) < 4 ||
+                  psd_read (input, &ver,               4, error) < 4 ||
+                  psd_read (input, &angle,             4, error) < 4 ||
+                  psd_read (input, &strength,          4, error) < 4 ||
+                  psd_read (input, &blur,              4, error) < 4 ||
+                  psd_read (input, &highlightsig,      4, error) < 4 ||
+                  psd_read (input, &highlighteffect,   4, error) < 4 ||
+                  psd_read (input, &shadowsig,         4, error) < 4 ||
+                  psd_read (input, &highlightcolor[0], 2, error) < 2 ||
+                  psd_read (input, &shadoweffect,      4, error) < 4 ||
+                  psd_read (input, &highlightcolor[1], 2, error) < 2 ||
+                  psd_read (input, &highlightcolor[2], 2, error) < 2 ||
+                  psd_read (input, &highlightcolor[3], 2, error) < 2 ||
+                  psd_read (input, &highlightcolor[4], 2, error) < 2 ||
+                  psd_read (input, &shadowcolor[0],    2, error) < 2 ||
+                  psd_read (input, &shadowcolor[1],    2, error) < 2 ||
+                  psd_read (input, &shadowcolor[2],    2, error) < 2 ||
+                  psd_read (input, &shadowcolor[3],    2, error) < 2 ||
+                  psd_read (input, &shadowcolor[4],    2, error) < 2 ||
+                  psd_read (input, &style,             1, error) < 1 ||
+                  psd_read (input, &highlightopacity,  1, error) < 1 ||
+                  psd_read (input, &shadowopacity,     1, error) < 1 ||
+                  psd_read (input, &enabled,           1, error) < 1 ||
+                  psd_read (input, &global,            1, error) < 1 ||
+                  psd_read (input, &direction,         1, error) < 1)
                 {
-                  psd_set_error (feof (f), errno, error);
+                  psd_set_error (error);
                   return -1;
                 }
 
               if (size == 78)
                 {
-                  if (fread(&highlightnatcolor[0], 2, 1, f) < 1
-                      || fread(&highlightnatcolor[0], 2, 1, f) < 1
-                      || fread(&highlightnatcolor[1], 2, 1, f) < 1
-                      || fread(&highlightnatcolor[2], 2, 1, f) < 1
-                      || fread(&highlightnatcolor[3], 2, 1, f) < 1
-                      || fread(&highlightnatcolor[4], 2, 1, f) < 1
-                      || fread(&shadownatcolor[0], 2, 1, f) < 1
-                      || fread(&shadownatcolor[0], 2, 1, f) < 1
-                      || fread(&shadownatcolor[1], 2, 1, f) < 1
-                      || fread(&shadownatcolor[2], 2, 1, f) < 1
-                      || fread(&shadownatcolor[3], 2, 1, f) < 1
-                      || fread(&shadownatcolor[4], 2, 1, f) < 1)
+                  if (psd_read (input, &highlightnatcolor[0], 2, error) < 2 ||
+                      psd_read (input, &highlightnatcolor[0], 2, error) < 2 ||
+                      psd_read (input, &highlightnatcolor[1], 2, error) < 2 ||
+                      psd_read (input, &highlightnatcolor[2], 2, error) < 2 ||
+                      psd_read (input, &highlightnatcolor[3], 2, error) < 2 ||
+                      psd_read (input, &highlightnatcolor[4], 2, error) < 2 ||
+                      psd_read (input, &shadownatcolor[0],    2, error) < 2 ||
+                      psd_read (input, &shadownatcolor[0],    2, error) < 2 ||
+                      psd_read (input, &shadownatcolor[1],    2, error) < 2 ||
+                      psd_read (input, &shadownatcolor[2],    2, error) < 2 ||
+                      psd_read (input, &shadownatcolor[3],    2, error) < 2 ||
+                      psd_read (input, &shadownatcolor[4],    2, error) < 2)
                     {
-                      psd_set_error (feof (f), errno, error);
+                      psd_set_error (error);
                       return -1;
                     }
                 }
@@ -859,23 +863,23 @@ load_resource_lrfx (const PSDlayerres  *res_a,
               gchar     enabled;
               gint16    natcolor[5];
 
-              if (fread (&size, 4, 1, f) < 1
-                  || fread(&ver, 4, 1, f) < 1
-                  || fread(&key, 4, 1, f) < 1
-                  || fread(&color[0], 2, 1, f) < 1
-                  || fread(&color[1], 2, 1, f) < 1
-                  || fread(&color[2], 2, 1, f) < 1
-                  || fread(&color[3], 2, 1, f) < 1
-                  || fread(&color[4], 2, 1, f) < 1
-                  || fread(&opacity, 1, 1, f) < 1
-                  || fread(&enabled, 1, 1, f) < 1
-                  || fread(&natcolor[0], 2, 1, f) < 1
-                  || fread(&natcolor[1], 2, 1, f) < 1
-                  || fread(&natcolor[2], 2, 1, f) < 1
-                  || fread(&natcolor[3], 2, 1, f) < 1
-                  || fread(&natcolor[4], 2, 1, f) < 1)
+              if (psd_read (input, &size,        4, error) < 4 ||
+                  psd_read (input, &ver,         4, error) < 4 ||
+                  psd_read (input, &key,         4, error) < 4 ||
+                  psd_read (input, &color[0],    2, error) < 2 ||
+                  psd_read (input, &color[1],    2, error) < 2 ||
+                  psd_read (input, &color[2],    2, error) < 2 ||
+                  psd_read (input, &color[3],    2, error) < 2 ||
+                  psd_read (input, &color[4],    2, error) < 2 ||
+                  psd_read (input, &opacity,     1, error) < 1 ||
+                  psd_read (input, &enabled,     1, error) < 1 ||
+                  psd_read (input, &natcolor[0], 2, error) < 2 ||
+                  psd_read (input, &natcolor[1], 2, error) < 2 ||
+                  psd_read (input, &natcolor[2], 2, error) < 2 ||
+                  psd_read (input, &natcolor[3], 2, error) < 2 ||
+                  psd_read (input, &natcolor[4], 2, error) < 2)
                 {
-                  psd_set_error (feof (f), errno, error);
+                  psd_set_error (error);
                   return -1;
                 }
             }
@@ -892,7 +896,7 @@ load_resource_lrfx (const PSDlayerres  *res_a,
 static gint
 load_resource_lyvr (const PSDlayerres  *res_a,
                     PSDlayer           *lyr_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   gint32 version;
@@ -900,9 +904,9 @@ load_resource_lyvr (const PSDlayerres  *res_a,
   IFDBG(2) g_debug ("Process layer resource block %.4s: layer version",
                     res_a->key);
 
-  if (fread (&version, 4, 1, f) < 1)
+  if (psd_read (input, &version, 4, error) < 4)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   version = GINT32_FROM_BE(version);
@@ -921,7 +925,7 @@ load_resource_lyvr (const PSDlayerres  *res_a,
 static gint
 load_resource_lnsr (const PSDlayerres  *res_a,
                     PSDlayer           *lyr_a,
-                    FILE               *f,
+                    GInputStream       *input,
                     GError            **error)
 {
   gchar layername[4];
@@ -929,9 +933,9 @@ load_resource_lnsr (const PSDlayerres  *res_a,
   IFDBG(2) g_debug ("Process layer resource block %.4s: layer source name",
                     res_a->key);
 
-  if (fread (&layername, 4, 1, f) < 1)
+  if (psd_read (input, &layername, 4, error) < 4)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
diff --git a/plug-ins/file-psd/psd-layer-res-load.h b/plug-ins/file-psd/psd-layer-res-load.h
index 516ed9583e..930d160c88 100644
--- a/plug-ins/file-psd/psd-layer-res-load.h
+++ b/plug-ins/file-psd/psd-layer-res-load.h
@@ -22,14 +22,14 @@
 #define __PSD_LAYER_RES_LOAD_H__
 
 
-gint  get_layer_resource_header (PSDlayerres  *res_a,
-                                 FILE         *f,
-                                 GError      **error);
+gint  get_layer_resource_header (PSDlayerres   *res_a,
+                                 GInputStream  *input,
+                                 GError       **error);
 
-gint  load_layer_resource       (PSDlayerres  *res_a,
-                                 PSDlayer     *lyr_a,
-                                 FILE         *f,
-                                 GError      **error);
+gint  load_layer_resource       (PSDlayerres   *res_a,
+                                 PSDlayer      *lyr_a,
+                                 GInputStream  *input,
+                                 GError       **error);
 
 
 #endif /* __PSD_LAYER_RES_LOAD_H__ */
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index a06d694f28..e4e4dc7cb9 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -40,54 +40,54 @@
 
 
 /*  Local function prototypes  */
-static gint             read_header_block          (PSDimage     *img_a,
-                                                    FILE         *f,
-                                                    GError      **error);
-
-static gint             read_color_mode_block      (PSDimage     *img_a,
-                                                    FILE         *f,
-                                                    GError      **error);
-
-static gint             read_image_resource_block  (PSDimage     *img_a,
-                                                    FILE         *f,
-                                                    GError      **error);
-
-static PSDlayer **      read_layer_block           (PSDimage     *img_a,
-                                                    FILE         *f,
-                                                    GError      **error);
-
-static gint             read_merged_image_block    (PSDimage     *img_a,
-                                                    FILE         *f,
-                                                    GError      **error);
-
-static GimpImage *      create_gimp_image          (PSDimage     *img_a,
-                                                    GFile        *file);
-
-static gint             add_color_map              (GimpImage    *image,
-                                                    PSDimage     *img_a);
-
-static gint             add_image_resources        (GimpImage    *image,
-                                                    PSDimage     *img_a,
-                                                    FILE         *f,
-                                                    gboolean     *resolution_loaded,
-                                                    gboolean     *profile_loaded,
-                                                    GError      **error);
-
-static gint             add_layers                 (GimpImage    *image,
-                                                    PSDimage     *img_a,
-                                                    PSDlayer    **lyr_a,
-                                                    FILE         *f,
-                                                    GError      **error);
-
-static gint             add_merged_image           (GimpImage    *image,
-                                                    PSDimage     *img_a,
-                                                    FILE         *f,
-                                                    GError      **error);
+static gint             read_header_block          (PSDimage       *img_a,
+                                                    GInputStream   *input,
+                                                    GError        **error);
+
+static gint             read_color_mode_block      (PSDimage       *img_a,
+                                                    GInputStream   *input,
+                                                    GError        **error);
+
+static gint             read_image_resource_block  (PSDimage       *img_a,
+                                                    GInputStream   *input,
+                                                    GError        **error);
+
+static PSDlayer **      read_layer_block           (PSDimage       *img_a,
+                                                    GInputStream   *input,
+                                                    GError        **error);
+
+static gint             read_merged_image_block    (PSDimage       *img_a,
+                                                    GInputStream   *input,
+                                                    GError        **error);
+
+static GimpImage *      create_gimp_image          (PSDimage       *img_a,
+                                                    GFile          *file);
+
+static gint             add_color_map              (GimpImage      *image,
+                                                    PSDimage       *img_a);
+
+static gint             add_image_resources        (GimpImage      *image,
+                                                    PSDimage       *img_a,
+                                                    GInputStream   *input,
+                                                    gboolean       *resolution_loaded,
+                                                    gboolean       *profile_loaded,
+                                                    GError        **error);
+
+static gint             add_layers                 (GimpImage      *image,
+                                                    PSDimage       *img_a,
+                                                    PSDlayer      **lyr_a,
+                                                    GInputStream   *input,
+                                                    GError        **error);
+
+static gint             add_merged_image           (GimpImage      *image,
+                                                    PSDimage       *img_a,
+                                                    GInputStream   *input,
+                                                    GError        **error);
 
 /*  Local utility function prototypes  */
-static gchar          * get_psd_color_mode_name    (PSDColorMode  mode);
+static gchar          * get_psd_color_mode_name    (PSDColorMode    mode);
 
-static void             psd_to_gimp_color_map      (guchar       *map256);
+static void             psd_to_gimp_color_map      (guchar         *map256);
 
 static GimpImageType    get_gimp_image_type        (GimpImageBaseType image_base_type,
                                                     gboolean          alpha);
@@ -96,19 +96,19 @@ static gint             read_channel_data          (PSDchannel     *channel,
                                                     guint16         bps,
                                                     guint16         compression,
                                                     const guint16  *rle_pack_len,
-                                                    FILE           *f,
+                                                    GInputStream   *input,
                                                     guint32         comp_len,
                                                     GError        **error);
 
-static void             convert_1_bit              (const gchar *src,
-                                                    gchar       *dst,
-                                                    guint32      rows,
-                                                    guint32      columns);
+static void             convert_1_bit              (const gchar    *src,
+                                                    gchar          *dst,
+                                                    guint32         rows,
+                                                    guint32         columns);
 
-static const Babl*      get_layer_format           (PSDimage    *img_a,
-                                                    gboolean     alpha);
-static const Babl*      get_channel_format         (PSDimage    *img_a);
-static const Babl*      get_mask_format            (PSDimage    *img_a);
+static const Babl*      get_layer_format           (PSDimage       *img_a,
+                                                    gboolean        alpha);
+static const Babl*      get_channel_format         (PSDimage       *img_a);
+static const Babl*      get_mask_format            (PSDimage       *img_a);
 
 
 /* Main file load function */
@@ -119,22 +119,32 @@ load_image (GFile        *file,
             gboolean     *profile_loaded,
             GError      **load_error)
 {
-  gchar      *filename;
-  FILE       *f;
-  GStatBuf    st;
-  PSDimage    img_a;
-  PSDlayer  **lyr_a;
-  GimpImage  *image = NULL;
-  GError     *error = NULL;
-
-  filename = g_file_get_path (file);
+  GInputStream  *input;
+  PSDimage       img_a;
+  PSDlayer     **lyr_a;
+  GimpImage     *image = NULL;
+  GError        *error = NULL;
 
   img_a.cmyk_transform = img_a.cmyk_transform_alpha = NULL;
   img_a.cmyk_profile = NULL;
+
   /* ----- Open PSD file ----- */
-  if (g_stat (filename, &st) == -1)
+
+  input = G_INPUT_STREAM (g_file_read (file, NULL, &error));
+  if (! input)
     {
-      g_free (filename);
+      if (! error)
+        g_set_error (load_error, G_FILE_ERROR, g_file_error_from_errno (errno),
+                     _("Could not open '%s' for reading: %s"),
+                     gimp_file_get_utf8_name (file), g_strerror (errno));
+      else
+        {
+          g_set_error (load_error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                       _("Could not open '%s' for reading: %s"),
+                       gimp_file_get_utf8_name (file), error->message);
+          g_error_free (error);
+        }
+
       return NULL;
     }
 
@@ -143,47 +153,41 @@ load_image (GFile        *file,
 
   IFDBG(1) g_debug ("Open file %s", gimp_file_get_utf8_name (file));
 
-  f = g_fopen (filename, "rb");
-  g_free (filename);
-
-  if (! f)
-    {
-      g_set_error (load_error, G_FILE_ERROR, g_file_error_from_errno (errno),
-                   _("Could not open '%s' for reading: %s"),
-                   gimp_file_get_utf8_name (file), g_strerror (errno));
-      return NULL;
-    }
-
   img_a.merged_image_only = merged_image_only;
 
   /* ----- Read the PSD file Header block ----- */
-  IFDBG(2) g_debug ("Read header block");
-  if (read_header_block (&img_a, f, &error) < 0)
+  IFDBG(2) g_debug ("Read header block at offset %" G_GOFFSET_FORMAT,
+                    PSD_TELL(input));
+  if (read_header_block (&img_a, input, &error) < 0)
     goto load_error;
   gimp_progress_update (0.1);
 
   /* ----- Read the PSD file Color Mode block ----- */
-  IFDBG(2) g_debug ("Read color mode block");
-  if (read_color_mode_block (&img_a, f, &error) < 0)
+  IFDBG(2) g_debug ("Read color mode block at offset %" G_GOFFSET_FORMAT,
+                    PSD_TELL(input));
+  if (read_color_mode_block (&img_a, input, &error) < 0)
     goto load_error;
   gimp_progress_update (0.2);
 
   /* ----- Read the PSD file Image Resource block ----- */
-  IFDBG(2) g_debug ("Read image resource block");
-  if (read_image_resource_block (&img_a, f, &error) < 0)
+  IFDBG(2) g_debug ("Read image resource block at offset %" G_GOFFSET_FORMAT,
+                    PSD_TELL(input));
+  if (read_image_resource_block (&img_a, input, &error) < 0)
     goto load_error;
   gimp_progress_update (0.3);
 
   /* ----- Read the PSD file Layer & Mask block ----- */
-  IFDBG(2) g_debug ("Read layer & mask block");
-  lyr_a = read_layer_block (&img_a, f, &error);
+  IFDBG(2) g_debug ("Read layer & mask block at offset %" G_GOFFSET_FORMAT,
+                    PSD_TELL(input));
+  lyr_a = read_layer_block (&img_a, input, &error);
   if (! img_a.merged_image_only && img_a.num_layers != 0 && lyr_a == NULL)
     goto load_error;
   gimp_progress_update (0.4);
 
   /* ----- Read the PSD file Merged Image Data block ----- */
-  IFDBG(2) g_debug ("Read merged image and extra alpha channel block");
-  if (read_merged_image_block (&img_a, f, &error) < 0)
+  IFDBG(2) g_debug ("Read merged image and extra alpha channel block at offset %" G_GOFFSET_FORMAT,
+                    PSD_TELL(input));
+  if (read_merged_image_block (&img_a, input, &error) < 0)
     goto load_error;
   gimp_progress_update (0.5);
 
@@ -202,7 +206,7 @@ load_image (GFile        *file,
 
   /* ----- Add image resources ----- */
   IFDBG(2) g_debug ("Add image resources");
-  if (add_image_resources (image, &img_a, f,
+  if (add_image_resources (image, &img_a, input,
                            resolution_loaded, profile_loaded,
                            &error) < 0)
     goto load_error;
@@ -210,13 +214,13 @@ load_image (GFile        *file,
 
   /* ----- Add layers -----*/
   IFDBG(2) g_debug ("Add layers");
-  if (add_layers (image, &img_a, lyr_a, f, &error) < 0)
+  if (add_layers (image, &img_a, lyr_a, input, &error) < 0)
     goto load_error;
   gimp_progress_update (0.9);
 
   /* ----- Add merged image data and extra alpha channels ----- */
   IFDBG(2) g_debug ("Add merged image data and extra alpha channels");
-  if (add_merged_image (image, &img_a, f, &error) < 0)
+  if (add_merged_image (image, &img_a, input, &error) < 0)
     goto load_error;
   gimp_progress_update (1.0);
 
@@ -226,7 +230,7 @@ load_image (GFile        *file,
 
   gimp_image_clean_all (image);
   gimp_image_undo_enable (image);
-  fclose (f);
+  g_object_unref (input);
   return image;
 
   /* ----- Process load errors ----- */
@@ -243,8 +247,7 @@ load_image (GFile        *file,
     gimp_image_delete (image);
 
   /* Close file if Open */
-  if (! (f == NULL))
-    fclose (f);
+  g_object_unref (input);
 
   return NULL;
 }
@@ -253,24 +256,24 @@ load_image (GFile        *file,
 /* Local functions */
 
 static gint
-read_header_block (PSDimage  *img_a,
-                   FILE      *f,
-                   GError   **error)
+read_header_block (PSDimage      *img_a,
+                   GInputStream  *input,
+                   GError       **error)
 {
   guint16  version;
   gchar    sig[4];
   gchar    buf[6];
 
-  if (fread (sig, 4, 1, f) < 1
-      || fread (&version, 2, 1, f) < 1
-      || fread (buf, 6, 1, f) < 1
-      || fread (&img_a->channels, 2, 1, f) < 1
-      || fread (&img_a->rows, 4, 1, f) < 1
-      || fread (&img_a->columns, 4, 1, f) < 1
-      || fread (&img_a->bps, 2, 1, f) < 1
-      || fread (&img_a->color_mode, 2, 1, f) < 1)
+  if (psd_read (input, sig,                4, error) < 4 ||
+      psd_read (input, &version,           2, error) < 2 ||
+      psd_read (input, buf,                6, error) < 6 ||
+      psd_read (input, &img_a->channels,   2, error) < 2 ||
+      psd_read (input, &img_a->rows,       4, error) < 4 ||
+      psd_read (input, &img_a->columns,    4, error) < 4 ||
+      psd_read (input, &img_a->bps,        2, error) < 2 ||
+      psd_read (input, &img_a->color_mode, 2, error) < 2)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   version = GUINT16_FROM_BE (version);
@@ -390,18 +393,18 @@ read_header_block (PSDimage  *img_a,
 }
 
 static gint
-read_color_mode_block (PSDimage  *img_a,
-                       FILE      *f,
-                       GError   **error)
+read_color_mode_block (PSDimage      *img_a,
+                       GInputStream  *input,
+                       GError       **error)
 {
   static guchar cmap[] = { 0, 0, 0, 255, 255, 255 };
   guint32       block_len;
 
   img_a->color_map_entries = 0;
   img_a->color_map_len = 0;
-  if (fread (&block_len, 4, 1, f) < 1)
+  if (psd_read (input, &block_len, 4, error) < 4)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   block_len = GUINT32_FROM_BE (block_len);
@@ -432,9 +435,9 @@ read_color_mode_block (PSDimage  *img_a,
         {
           img_a->color_map_len = block_len;
           img_a->color_map = g_malloc (img_a->color_map_len);
-          if (fread (img_a->color_map, block_len, 1, f) < 1)
+          if (psd_read (input, img_a->color_map, block_len, error) < block_len)
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               return -1;
             }
           else
@@ -448,9 +451,9 @@ read_color_mode_block (PSDimage  *img_a,
     {
       img_a->color_map_len = block_len;
       img_a->color_map = g_malloc (img_a->color_map_len);
-      if (fread (img_a->color_map, block_len, 1, f) < 1)
+      if (psd_read (input, img_a->color_map, block_len, error) < block_len)
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return -1;
         }
     }
@@ -469,28 +472,28 @@ read_color_mode_block (PSDimage  *img_a,
 }
 
 static gint
-read_image_resource_block (PSDimage  *img_a,
-                           FILE      *f,
-                           GError   **error)
+read_image_resource_block (PSDimage      *img_a,
+                           GInputStream  *input,
+                           GError       **error)
 {
-  guint32 block_len;
-  guint32 block_end;
+  guint64 block_len;
+  guint64 block_end;
 
-  if (fread (&block_len, 4, 1, f) < 1)
+  if (psd_read (input, &block_len, 4, error) < 4)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   img_a->image_res_len = GUINT32_FROM_BE (block_len);
 
   IFDBG(1) g_debug ("Image resource block size = %d", (int)img_a->image_res_len);
 
-  img_a->image_res_start = ftell (f);
+  img_a->image_res_start = PSD_TELL(input);
   block_end = img_a->image_res_start + img_a->image_res_len;
 
-  if (fseek (f, block_end, SEEK_SET) < 0)
+  if (! psd_seek (input, block_end, G_SEEK_SET, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
@@ -498,28 +501,30 @@ read_image_resource_block (PSDimage  *img_a,
 }
 
 static PSDlayer **
-read_layer_info (PSDimage  *img_a,
-                 FILE      *f,
-                 GError   **error)
+read_layer_info (PSDimage      *img_a,
+                 GInputStream  *input,
+                 GError       **error)
 {
   PSDlayer **lyr_a = NULL;
-  guint32    block_len;
-  guint32    block_rem;
+  guint64    block_len;
+  guint64    block_rem;
   gint32     read_len;
   gint32     write_len;
   gint       lidx;                  /* Layer index */
   gint       cidx;                  /* Channel index */
 
+  g_debug ("Reading layer info at offset %" G_GOFFSET_FORMAT,
+           PSD_TELL(input));
   /* Get number of layers */
-  if (fread (&img_a->num_layers, 2, 1, f) < 1)
+  if (psd_read (input, &img_a->num_layers, 2, error) < 2)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       img_a->num_layers = -1;
       return NULL;
     }
 
   img_a->num_layers = GINT16_FROM_BE (img_a->num_layers);
-  IFDBG(2) g_debug ("Number of layers: %d", img_a->num_layers);
+  IFDBG(2) g_debug ("Number of layers: %d (negative means transparency present)", img_a->num_layers);
 
   if (img_a->num_layers < 0)
     {
@@ -530,7 +535,7 @@ read_layer_info (PSDimage  *img_a,
   if (! img_a->merged_image_only && img_a->num_layers)
     {
       /* Read layer records */
-      PSDlayerres           res_a;
+      PSDlayerres  res_a;
 
       /* Create pointer array for the layer records */
       lyr_a = g_new (PSDlayer *, img_a->num_layers);
@@ -545,13 +550,13 @@ read_layer_info (PSDimage  *img_a,
           lyr_a[lidx]->id = 0;
           lyr_a[lidx]->group_type = 0;
 
-          if (fread (&lyr_a[lidx]->top, 4, 1, f) < 1
-              || fread (&lyr_a[lidx]->left, 4, 1, f) < 1
-              || fread (&lyr_a[lidx]->bottom, 4, 1, f) < 1
-              || fread (&lyr_a[lidx]->right, 4, 1, f) < 1
-              || fread (&lyr_a[lidx]->num_channels, 2, 1, f) < 1)
+          if (psd_read (input, &lyr_a[lidx]->top,          4, error) < 4 ||
+              psd_read (input, &lyr_a[lidx]->left,         4, error) < 4 ||
+              psd_read (input, &lyr_a[lidx]->bottom,       4, error) < 4 ||
+              psd_read (input, &lyr_a[lidx]->right,        4, error) < 4 ||
+              psd_read (input, &lyr_a[lidx]->num_channels, 2, error) < 2)
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               return NULL;
             }
 
@@ -604,10 +609,10 @@ read_layer_info (PSDimage  *img_a,
 
           for (cidx = 0; cidx < lyr_a[lidx]->num_channels; ++cidx)
             {
-              if (fread (&lyr_a[lidx]->chn_info[cidx].channel_id, 2, 1, f) < 1
-                  || fread (&lyr_a[lidx]->chn_info[cidx].data_len, 4, 1, f) < 1)
+              if (psd_read (input, &lyr_a[lidx]->chn_info[cidx].channel_id, 2, error) < 2 ||
+                  psd_read (input, &lyr_a[lidx]->chn_info[cidx].data_len,   4, error) < 4)
                 {
-                  psd_set_error (feof (f), errno, error);
+                  psd_set_error (error);
                   return NULL;
                 }
               lyr_a[lidx]->chn_info[cidx].channel_id =
@@ -620,15 +625,15 @@ read_layer_info (PSDimage  *img_a,
                                 lyr_a[lidx]->chn_info[cidx].data_len);
             }
 
-          if (fread (lyr_a[lidx]->mode_key, 4, 1, f) < 1
-              || fread (lyr_a[lidx]->blend_mode, 4, 1, f) < 1
-              || fread (&lyr_a[lidx]->opacity, 1, 1, f) < 1
-              || fread (&lyr_a[lidx]->clipping, 1, 1, f) < 1
-              || fread (&lyr_a[lidx]->flags, 1, 1, f) < 1
-              || fread (&lyr_a[lidx]->filler, 1, 1, f) < 1
-              || fread (&lyr_a[lidx]->extra_len, 4, 1, f) < 1)
+          if (psd_read (input, lyr_a[lidx]->mode_key,   4, error) < 4 ||
+              psd_read (input, lyr_a[lidx]->blend_mode, 4, error) < 4 ||
+              psd_read (input, &lyr_a[lidx]->opacity,   1, error) < 1 ||
+              psd_read (input, &lyr_a[lidx]->clipping,  1, error) < 1 ||
+              psd_read (input, &lyr_a[lidx]->flags,     1, error) < 1 ||
+              psd_read (input, &lyr_a[lidx]->filler,    1, error) < 1 ||
+              psd_read (input, &lyr_a[lidx]->extra_len, 4, error) < 4)
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               return NULL;
             }
           if (memcmp (lyr_a[lidx]->mode_key, "8BIM", 4) != 0)
@@ -651,7 +656,7 @@ read_layer_info (PSDimage  *img_a,
           lyr_a[lidx]->extra_len = GUINT32_FROM_BE (lyr_a[lidx]->extra_len);
           block_rem = lyr_a[lidx]->extra_len;
           IFDBG(2) g_debug ("\n\tLayer mode sig: %.4s\n\tBlend mode: %.4s\n\t"
-                            "Opacity: %d\n\tClipping: %d\n\tExtra data len: %d\n\t"
+                            "Opacity: %d\n\tClipping: %d\n\tExtra data len: %" G_GSIZE_FORMAT "\n\t"
                             "Alpha lock: %d\n\tVisible: %d\n\tIrrelevant: %d",
                             lyr_a[lidx]->mode_key,
                             lyr_a[lidx]->blend_mode,
@@ -661,26 +666,26 @@ read_layer_info (PSDimage  *img_a,
                             lyr_a[lidx]->layer_flags.trans_prot,
                             lyr_a[lidx]->layer_flags.visible,
                             lyr_a[lidx]->layer_flags.irrelevant);
-          IFDBG(3) g_debug ("Remaining length %d", block_rem);
+          IFDBG(3) g_debug ("Remaining length %" G_GOFFSET_FORMAT, block_rem);
 
           /* Layer mask data */
-          if (fread (&block_len, 4, 1, f) < 1)
+          if (psd_read (input, &block_len, 4, error) < 4)
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               return NULL;
             }
           block_len = GUINT32_FROM_BE (block_len);
-          IFDBG(3) g_debug ("Layer mask record size %u", block_len);
+          IFDBG(3) g_debug ("Layer mask record size %" G_GOFFSET_FORMAT, block_len);
           if (block_len + 4 > block_rem)
             {
               g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
-                           _("Unsupported or invalid mask info size: %d"),
+                           _("Unsupported or invalid mask info size: %" G_GOFFSET_FORMAT),
                            block_len);
               return NULL;
             }
 
           block_rem -= (block_len + 4);
-          IFDBG(3) g_debug ("Remaining length %d", block_rem);
+          IFDBG(3) g_debug ("Remaining length %" G_GOFFSET_FORMAT, block_rem);
 
           lyr_a[lidx]->layer_mask_extra.top = 0;
           lyr_a[lidx]->layer_mask_extra.left = 0;
@@ -703,14 +708,14 @@ read_layer_info (PSDimage  *img_a,
 
           if (block_len > 0)
             {
-              if (fread (&lyr_a[lidx]->layer_mask.top, 4, 1, f) < 1
-                  || fread (&lyr_a[lidx]->layer_mask.left, 4, 1, f) < 1
-                  || fread (&lyr_a[lidx]->layer_mask.bottom, 4, 1, f) < 1
-                  || fread (&lyr_a[lidx]->layer_mask.right, 4, 1, f) < 1
-                  || fread (&lyr_a[lidx]->layer_mask.def_color, 1, 1, f) < 1
-                  || fread (&lyr_a[lidx]->layer_mask.flags, 1, 1, f) < 1)
+              if (psd_read (input, &lyr_a[lidx]->layer_mask.top,       4, error) < 4 ||
+                  psd_read (input, &lyr_a[lidx]->layer_mask.left,      4, error) < 4 ||
+                  psd_read (input, &lyr_a[lidx]->layer_mask.bottom,    4, error) < 4 ||
+                  psd_read (input, &lyr_a[lidx]->layer_mask.right,     4, error) < 4 ||
+                  psd_read (input, &lyr_a[lidx]->layer_mask.def_color, 1, error) < 1 ||
+                  psd_read (input, &lyr_a[lidx]->layer_mask.flags,     1, error) < 1)
                 {
-                  psd_set_error (feof (f), errno, error);
+                  psd_set_error (error);
                   return NULL;
                 }
 
@@ -748,14 +753,14 @@ read_layer_info (PSDimage  *img_a,
                * how to distinguish them. */
               if (block_len >= 18)
                 {
-                  if (fread (&lyr_a[lidx]->layer_mask.extra_flags, 1, 1, f) < 1
-                      || fread (&lyr_a[lidx]->layer_mask.extra_def_color, 1, 1, f) < 1
-                      || fread (&lyr_a[lidx]->layer_mask_extra.top, 4, 1, f) < 1
-                      || fread (&lyr_a[lidx]->layer_mask_extra.left, 4, 1, f) < 1
-                      || fread (&lyr_a[lidx]->layer_mask_extra.bottom, 4, 1, f) < 1
-                      || fread (&lyr_a[lidx]->layer_mask_extra.right, 4, 1, f) < 1)
+                  if (psd_read (input, &lyr_a[lidx]->layer_mask.extra_flags,     1, error) < 1 ||
+                      psd_read (input, &lyr_a[lidx]->layer_mask.extra_def_color, 1, error) < 1 ||
+                      psd_read (input, &lyr_a[lidx]->layer_mask_extra.top,       4, error) < 4 ||
+                      psd_read (input, &lyr_a[lidx]->layer_mask_extra.left,      4, error) < 4 ||
+                      psd_read (input, &lyr_a[lidx]->layer_mask_extra.bottom,    4, error) < 4 ||
+                      psd_read (input, &lyr_a[lidx]->layer_mask_extra.right,     4, error) < 4)
                     {
-                      psd_set_error (feof (f), errno, error);
+                      psd_set_error (error);
                       return NULL;
                     }
                   block_len -= 18;
@@ -780,9 +785,9 @@ read_layer_info (PSDimage  *img_a,
                 {
                   gint extra_bytes = 0;
 
-                  if (fread (&lyr_a[lidx]->layer_mask.mask_params, 1, 1, f) < 1)
+                  if (psd_read (input, &lyr_a[lidx]->layer_mask.mask_params, 1, error) < 1)
                     {
-                      psd_set_error (feof (f), errno, error);
+                      psd_set_error (error);
                       return NULL;
                     }
                   block_len--;
@@ -795,9 +800,9 @@ read_layer_info (PSDimage  *img_a,
                   extra_bytes += (lyr_a[lidx]->layer_mask.mask_params & 4 ? 1 : 0);
                   extra_bytes += (lyr_a[lidx]->layer_mask.mask_params & 8 ? 8 : 0);
                   IFDBG(3) g_debug ("Extra bytes according to mask parameters %d", extra_bytes);
-                  if (fseek (f, extra_bytes, SEEK_CUR) < 0)
+                  if (! psd_seek (input, extra_bytes, G_SEEK_CUR, error))
                     {
-                      psd_set_error (feof (f), errno, error);
+                      psd_set_error (error);
                       return NULL;
                     }
                   block_len -= extra_bytes;
@@ -810,12 +815,12 @@ read_layer_info (PSDimage  *img_a,
                   IFDBG(1)
                     {
                       if (block_len > 3)
-                        g_debug ("Skipping %u bytes of unknown layer mask data", block_len);
+                        g_debug ("Skipping %" G_GOFFSET_FORMAT " bytes of unknown layer mask data", 
block_len);
                     }
 
-                  if (fseek (f, block_len, SEEK_CUR) < 0)
+                  if (! psd_seek (input, block_len, G_SEEK_CUR, error))
                     {
-                      psd_set_error (feof (f), errno, error);
+                      psd_set_error (error);
                       return NULL;
                     }
                 }
@@ -865,38 +870,38 @@ read_layer_info (PSDimage  *img_a,
             }
 
           /* Layer blending ranges */           /* FIXME  */
-          if (fread (&block_len, 4, 1, f) < 1)
+          if (psd_read (input, &block_len, 4, error) < 4)
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               return NULL;
             }
 
           block_len = GUINT32_FROM_BE (block_len);
           block_rem -= (block_len + 4);
-          IFDBG(3) g_debug ("Remaining length %d", block_rem);
+          IFDBG(3) g_debug ("Remaining length %" G_GOFFSET_FORMAT, block_rem);
 
           if (block_len > 0)
             {
-              if (fseek (f, block_len, SEEK_CUR) < 0)
+              if (! psd_seek (input, block_len, G_SEEK_CUR, error))
                 {
-                  psd_set_error (feof (f), errno, error);
+                  psd_set_error (error);
                   return NULL;
                 }
             }
 
           lyr_a[lidx]->name = fread_pascal_string (&read_len, &write_len,
-                                                   4, f, error);
+                                                   4, input, error);
           if (*error)
             return NULL;
 
           block_rem -= read_len;
-          IFDBG(3) g_debug ("Remaining length %d", block_rem);
+          IFDBG(3) g_debug ("Remaining length %" G_GOFFSET_FORMAT, block_rem);
 
           /* Adjustment layer info */           /* FIXME */
 
           while (block_rem > 7)
             {
-              if (get_layer_resource_header (&res_a, f, error) < 0)
+              if (get_layer_resource_header (&res_a, input, error) < 0)
                 return NULL;
 
               block_rem -= 12;
@@ -907,7 +912,7 @@ read_layer_info (PSDimage  *img_a,
                    *  try to recover graciously. See bug #771558.
                    */
                   g_printerr ("psd-load: Layer extra data length should "
-                              "be even, but it is %d.", res_a.data_len);
+                              "be even, but it is %"G_GOFFSET_FORMAT".", res_a.data_len);
                 }
 
               if (res_a.data_len > block_rem)
@@ -918,28 +923,28 @@ read_layer_info (PSDimage  *img_a,
                   return NULL;
                 }
 
-              if (load_layer_resource (&res_a, lyr_a[lidx], f, error) < 0)
+              if (load_layer_resource (&res_a, lyr_a[lidx], input, error) < 0)
                 return NULL;
               block_rem -= res_a.data_len;
             }
           if (block_rem > 0)
             {
-              if (fseek (f, block_rem, SEEK_CUR) < 0)
+              if (! psd_seek (input, block_rem, G_SEEK_CUR, error))
                 {
-                  psd_set_error (feof (f), errno, error);
+                  psd_set_error (error);
                   return NULL;
                 }
             }
         }
 
-      img_a->layer_data_start = ftell(f);
-      if (fseek (f, img_a->layer_data_len, SEEK_CUR) < 0)
+      img_a->layer_data_start = PSD_TELL(input);
+      if (! psd_seek (input, img_a->layer_data_len, G_SEEK_CUR, error))
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return NULL;
         }
 
-      IFDBG(1) g_debug ("Layer image data block size %d",
+      IFDBG(1) g_debug ("Layer image data block size %" G_GOFFSET_FORMAT,
                         img_a->layer_data_len);
     }
 
@@ -948,24 +953,24 @@ read_layer_info (PSDimage  *img_a,
 
 
 static PSDlayer **
-read_layer_block (PSDimage  *img_a,
-                  FILE      *f,
-                  GError   **error)
+read_layer_block (PSDimage      *img_a,
+                  GInputStream  *input,
+                  GError       **error)
 {
   PSDlayer **lyr_a = NULL;
-  guint32    block_len;
-  guint32    block_end;
+  guint64    block_len;
+  guint64    block_end;
 
-  if (fread (&block_len, 4, 1, f) < 1)
+  if (psd_read (input, &block_len, 4, error) < 4)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       img_a->num_layers = -1;
       return NULL;
     }
 
   img_a->mask_layer_len = GUINT32_FROM_BE (block_len);
 
-  IFDBG(1) g_debug ("Layer and mask block size = %d", img_a->mask_layer_len);
+  IFDBG(1) g_debug ("Layer and mask block size = %" G_GOFFSET_FORMAT, img_a->mask_layer_len);
 
   img_a->transparency = FALSE;
   img_a->layer_data_len = 0;
@@ -979,16 +984,16 @@ read_layer_block (PSDimage  *img_a,
     {
       guint32 total_len = img_a->mask_layer_len;
 
-      img_a->mask_layer_start = ftell (f);
+      img_a->mask_layer_start = PSD_TELL(input);
       block_end = img_a->mask_layer_start + img_a->mask_layer_len;
 
       /* Layer info */
-      if (fread (&block_len, 4, 1, f) == 1 && block_len)
+      if (psd_read (input, &block_len, 4, error) == 4 && block_len)
         {
           block_len = GUINT32_FROM_BE (block_len);
-          IFDBG(1) g_debug ("Layer info size = %d", block_len);
+          IFDBG(1) g_debug ("Layer info size = %" G_GOFFSET_FORMAT, block_len);
 
-          lyr_a = read_layer_info (img_a, f, error);
+          lyr_a = read_layer_info (img_a, input, error);
 
           total_len -= block_len;
         }
@@ -999,13 +1004,17 @@ read_layer_block (PSDimage  *img_a,
         }
 
       /* Global layer mask info */
-      if (fread (&block_len, 4, 1, f) == 1 && block_len)
+      if (psd_read (input, &block_len, 4, error) == 4 && block_len)
         {
           block_len = GUINT32_FROM_BE (block_len);
-          IFDBG(1) g_debug ("Global layer mask info size = %d", block_len);
+          IFDBG(1) g_debug ("Global layer mask info size = %" G_GOFFSET_FORMAT, block_len);
 
           /* read_global_layer_mask_info (img_a, f, error); */
-          fseek (f, block_len, SEEK_CUR);
+          if (! psd_seek (input, block_len, G_SEEK_CUR, error))
+            {
+              psd_set_error (error);
+              return NULL;
+            }
 
           total_len -= block_len;
         }
@@ -1015,17 +1024,23 @@ read_layer_block (PSDimage  *img_a,
         {
           gchar signature_key[8];
 
-          if (fread (&signature_key, 4, 2, f) == 2 &&
+          if (psd_read (input, &signature_key, 4 * 2, error) == 4 * 2 &&
               (memcmp (signature_key, "8BIMLr16", 8) == 0 ||
                memcmp (signature_key, "8BIMLr32", 8) == 0) &&
-              fread (&block_len, 4, 1, f) == 1 && block_len)
-            lyr_a = read_layer_info (img_a, f, error);
+              psd_read (input, &block_len, 4, error) == 4 && block_len)
+            lyr_a = read_layer_info (img_a, input, error);
+
+          if (*error)
+            {
+              psd_set_error (error);
+              return NULL;
+            }
         }
 
       /* Skip to end of block */
-      if (fseek (f, block_end, SEEK_SET) < 0)
+      if (! psd_seek (input, block_end, G_SEEK_SET, error))
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return NULL;
         }
     }
@@ -1034,20 +1049,20 @@ read_layer_block (PSDimage  *img_a,
 }
 
 static gint
-read_merged_image_block (PSDimage  *img_a,
-                         FILE      *f,
-                         GError   **error)
+read_merged_image_block (PSDimage      *img_a,
+                         GInputStream  *input,
+                         GError       **error)
 {
-  img_a->merged_image_start = ftell(f);
-  if (fseek (f, 0, SEEK_END) < 0)
+  img_a->merged_image_start = PSD_TELL(input);
+  if (! psd_seek (input, 0, G_SEEK_END, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
-  img_a->merged_image_len = ftell(f) - img_a->merged_image_start;
+  img_a->merged_image_len = PSD_TELL(input) - img_a->merged_image_start;
 
-  IFDBG(1) g_debug ("Merged image data block: Start: %d, len: %d",
+  IFDBG(1) g_debug ("Merged image data block: Start: %" G_GOFFSET_FORMAT ", len: %" G_GOFFSET_FORMAT,
                      img_a->merged_image_start, img_a->merged_image_len);
 
   return 0;
@@ -1149,18 +1164,19 @@ add_color_map (GimpImage *image,
 }
 
 static gint
-add_image_resources (GimpImage *image,
-                     PSDimage  *img_a,
-                     FILE      *f,
-                     gboolean  *resolution_loaded,
-                     gboolean  *profile_loaded,
-                     GError   **error)
+add_image_resources (GimpImage     *image,
+                     PSDimage      *img_a,
+                     GInputStream  *input,
+                     gboolean      *resolution_loaded,
+                     gboolean      *profile_loaded,
+                     GError       **error)
 {
   PSDimageres  res_a;
 
-  if (fseek (f, img_a->image_res_start, SEEK_SET) < 0)
+  if (! psd_seek (input, img_a->image_res_start, G_SEEK_SET, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
+      g_debug ("Failed to seek in add_image_resources");
       return -1;
     }
 
@@ -1175,9 +1191,9 @@ add_image_resources (GimpImage *image,
   img_a->alpha_id_count = 0;
   img_a->quick_mask_id = 0;
 
-  while (ftell (f) < img_a->image_res_start + img_a->image_res_len)
+  while (PSD_TELL(input) < img_a->image_res_start + img_a->image_res_len)
     {
-      if (get_image_resource_header (&res_a, f, error) < 0)
+      if (get_image_resource_header (&res_a, input, error) < 0)
         return -1;
 
       if (res_a.data_start + res_a.data_len >
@@ -1187,10 +1203,12 @@ add_image_resources (GimpImage *image,
           return 0;
         }
 
-      if (load_image_resource (&res_a, image, img_a, f,
+      if (load_image_resource (&res_a, image, img_a, input,
                                resolution_loaded, profile_loaded,
                                error) < 0)
-        return -1;
+        {
+          return -1;
+        }
     }
 
   return 0;
@@ -1265,11 +1283,11 @@ psd_convert_cmyk_to_srgb (PSDimage *img_a,
 
 
 static gint
-add_layers (GimpImage *image,
-            PSDimage  *img_a,
-            PSDlayer **lyr_a,
-            FILE      *f,
-            GError   **error)
+add_layers (GimpImage     *image,
+            PSDimage      *img_a,
+            PSDlayer     **lyr_a,
+            GInputStream  *input,
+            GError       **error)
 {
   PSDchannel          **lyr_chn;
   GArray               *parent_group_stack;
@@ -1312,9 +1330,9 @@ add_layers (GimpImage *image,
     }
 
   /* Layered image - Photoshop 3 style */
-  if (fseek (f, img_a->layer_data_start, SEEK_SET) < 0)
+  if (! psd_seek (input, img_a->layer_data_start, G_SEEK_SET, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
@@ -1333,9 +1351,10 @@ add_layers (GimpImage *image,
           /* Step past layer data */
           for (cidx = 0; cidx < lyr_a[lidx]->num_channels; ++cidx)
             {
-              if (fseek (f, lyr_a[lidx]->chn_info[cidx].data_len, SEEK_CUR) < 0)
+              if (! psd_seek (input, lyr_a[lidx]->chn_info[cidx].data_len,
+                              G_SEEK_CUR, error))
                 {
-                  psd_set_error (feof (f), errno, error);
+                  psd_set_error (error);
                   return -1;
                 }
             }
@@ -1378,9 +1397,10 @@ add_layers (GimpImage *image,
 
               if (lyr_chn[cidx]->id == PSD_CHANNEL_EXTRA_MASK)
                 {
-                  if (fseek (f, lyr_a[lidx]->chn_info[cidx].data_len, SEEK_CUR) != 0)
+                  if (! psd_seek (input, lyr_a[lidx]->chn_info[cidx].data_len,
+                                  G_SEEK_CUR, error))
                     {
-                      psd_set_error (feof (f), errno, error);
+                      psd_set_error (error);
                       return -1;
                     }
 
@@ -1422,9 +1442,9 @@ add_layers (GimpImage *image,
                */
               if (lyr_a[lidx]->chn_info[cidx].data_len >= COMP_MODE_SIZE)
                 {
-                  if (fread (&comp_mode, COMP_MODE_SIZE, 1, f) < 1)
+                  if (psd_read (input, &comp_mode, COMP_MODE_SIZE, error) < COMP_MODE_SIZE)
                     {
-                      psd_set_error (feof (f), errno, error);
+                      psd_set_error (error);
                       return -1;
                     }
                   comp_mode = GUINT16_FROM_BE (comp_mode);
@@ -1438,9 +1458,11 @@ add_layers (GimpImage *image,
                         IFDBG(3) g_debug ("Raw data length: %d",
                                           lyr_a[lidx]->chn_info[cidx].data_len - 2);
                         if (read_channel_data (lyr_chn[cidx], img_a->bps,
-                                               PSD_COMP_RAW, NULL, f, 0,
+                                               PSD_COMP_RAW, NULL, input, 0,
                                                error) < 1)
-                          return -1;
+                          {
+                            return -1;
+                          }
                         break;
 
                       case PSD_COMP_RLE:        /* Packbits */
@@ -1453,9 +1475,9 @@ add_layers (GimpImage *image,
                         rle_pack_len = g_malloc (lyr_chn[cidx]->rows * 2);
                         for (rowi = 0; rowi < lyr_chn[cidx]->rows; ++rowi)
                           {
-                            if (fread (&rle_pack_len[rowi], 2, 1, f) < 1)
+                            if (psd_read (input, &rle_pack_len[rowi], 2, error) < 2)
                               {
-                                psd_set_error (feof (f), errno, error);
+                                psd_set_error (error);
                                 g_free (rle_pack_len);
                                 return -1;
                               }
@@ -1464,9 +1486,11 @@ add_layers (GimpImage *image,
 
                         IFDBG(3) g_debug ("RLE decode - data");
                         if (read_channel_data (lyr_chn[cidx], img_a->bps,
-                                               PSD_COMP_RLE, rle_pack_len, f, 0,
+                                               PSD_COMP_RLE, rle_pack_len, input, 0,
                                                error) < 1)
-                          return -1;
+                          {
+                            return -1;
+                          }
 
                         g_free (rle_pack_len);
                         break;
@@ -1474,10 +1498,12 @@ add_layers (GimpImage *image,
                       case PSD_COMP_ZIP:                 /* ? */
                       case PSD_COMP_ZIP_PRED:
                         if (read_channel_data (lyr_chn[cidx], img_a->bps,
-                                               comp_mode, NULL, f,
+                                               comp_mode, NULL, input,
                                                lyr_a[lidx]->chn_info[cidx].data_len - 2,
                                                error) < 1)
-                          return -1;
+                          {
+                            return -1;
+                          }
                         break;
 
                       default:
@@ -1866,10 +1892,10 @@ add_layers (GimpImage *image,
 }
 
 static gint
-add_merged_image (GimpImage *image,
-                  PSDimage  *img_a,
-                  FILE      *f,
-                  GError   **error)
+add_merged_image (GimpImage     *image,
+                  PSDimage      *img_a,
+                  GInputStream  *input,
+                  GError       **error)
 {
   PSDchannel            chn_a[MAX_CHANNELS];
   gchar                *alpha_name;
@@ -1941,11 +1967,10 @@ add_merged_image (GimpImage *image,
       block_start = img_a->merged_image_start;
       block_len = img_a->merged_image_len;
 
-      fseek (f, block_start, SEEK_SET);
-
-      if (fread (&comp_mode, COMP_MODE_SIZE, 1, f) < 1)
+      if (! psd_seek (input, block_start, G_SEEK_SET, error) ||
+          psd_read (input, &comp_mode, COMP_MODE_SIZE, error) < COMP_MODE_SIZE)
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return -1;
         }
       comp_mode = GUINT16_FROM_BE (comp_mode);
@@ -1959,7 +1984,7 @@ add_merged_image (GimpImage *image,
                 chn_a[cidx].columns = img_a->columns;
                 chn_a[cidx].rows = img_a->rows;
                 if (read_channel_data (&chn_a[cidx], img_a->bps,
-                                       PSD_COMP_RAW, NULL, f, 0,
+                                       PSD_COMP_RAW, NULL, input, 0,
                                        error) < 1)
                   return -1;
               }
@@ -1978,9 +2003,9 @@ add_merged_image (GimpImage *image,
                 rle_pack_len[cidx] = g_malloc (img_a->rows * 2);
                 for (rowi = 0; rowi < img_a->rows; ++rowi)
                   {
-                    if (fread (&rle_pack_len[cidx][rowi], 2, 1, f) < 1)
+                    if (psd_read (input, &rle_pack_len[cidx][rowi], 2, error) < 2)
                       {
-                        psd_set_error (feof (f), errno, error);
+                        psd_set_error (error);
                         return -1;
                       }
                     rle_pack_len[cidx][rowi] = GUINT16_FROM_BE (rle_pack_len[cidx][rowi]);
@@ -1988,10 +2013,10 @@ add_merged_image (GimpImage *image,
               }
 
             /* Skip channel length data for unloaded channels */
-            if (fseek (f, (img_a->channels - total_channels) * img_a->rows * 2,
-                       SEEK_CUR) < 0)
+            if (! psd_seek (input, (img_a->channels - total_channels) * img_a->rows * 2,
+                            G_SEEK_CUR, error))
               {
-                psd_set_error (feof (f), errno, error);
+                psd_set_error (error);
                 return -1;
               }
 
@@ -1999,7 +2024,7 @@ add_merged_image (GimpImage *image,
             for (cidx = 0; cidx < total_channels; ++cidx)
               {
                 if (read_channel_data (&chn_a[cidx], img_a->bps,
-                                       PSD_COMP_RLE, rle_pack_len[cidx], f, 0,
+                                       PSD_COMP_RLE, rle_pack_len[cidx], input, 0,
                                        error) < 1)
                   return -1;
                 g_free (rle_pack_len[cidx]);
@@ -2297,7 +2322,7 @@ read_channel_data (PSDchannel     *channel,
                    guint16         bps,
                    guint16         compression,
                    const guint16  *rle_pack_len,
-                   FILE           *f,
+                   GInputStream   *input,
                    guint32         comp_len,
                    GError        **error)
 {
@@ -2327,9 +2352,9 @@ read_channel_data (PSDchannel     *channel,
   switch (compression)
     {
       case PSD_COMP_RAW:
-        if (fread (raw_data, readline_len, channel->rows, f) < 1)
+        if (psd_read (input, raw_data, readline_len * channel->rows, error) < readline_len * channel->rows)
           {
-            psd_set_error (feof (f), errno, error);
+            psd_set_error (error);
             return -1;
           }
         break;
@@ -2339,15 +2364,15 @@ read_channel_data (PSDchannel     *channel,
           {
             src = gegl_scratch_alloc (rle_pack_len[i]);
 /*      FIXME check for over-run
-            if (ftell (f) + rle_pack_len[i] > block_end)
+            if (PSD_TELL(input) + rle_pack_len[i] > block_end)
               {
                 psd_set_error (TRUE, errno, error);
                 return -1;
               }
 */
-            if (fread (src, rle_pack_len[i], 1, f) < 1)
+            if (psd_read (input, src, rle_pack_len[i], error) < rle_pack_len[i])
               {
-                psd_set_error (feof (f), errno, error);
+                psd_set_error (error);
                 gegl_scratch_free (src);
                 return -1;
               }
@@ -2363,9 +2388,9 @@ read_channel_data (PSDchannel     *channel,
           z_stream zs;
 
           src = g_malloc (comp_len);
-          if (fread (src, comp_len, 1, f) < 1)
+          if (psd_read (input, src, comp_len, error) < comp_len)
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               g_free (src);
               return -1;
             }
diff --git a/plug-ins/file-psd/psd-save.c b/plug-ins/file-psd/psd-save.c
index b89ab4fc7e..6bec383208 100644
--- a/plug-ins/file-psd/psd-save.c
+++ b/plug-ins/file-psd/psd-save.c
@@ -83,7 +83,7 @@
 
 
 /* set to TRUE if you want debugging, FALSE otherwise */
-#define DEBUG FALSE
+#define DEBUG TRUE
 
 /* 1: Normal debuggin, 2: Deep debuggin */
 #define DEBUG_LEVEL 2
@@ -137,72 +137,72 @@ static PSD_Image_Data PSDImageData;
 /* Declare some local functions.
  */
 
-static const gchar * psd_lmode_layer      (GimpLayer     *layer,
-                                           gboolean       section_divider);
+static const gchar * psd_lmode_layer      (GimpLayer      *layer,
+                                           gboolean        section_divider);
 
-static void          reshuffle_cmap_write (guchar        *mapGimp);
+static void          reshuffle_cmap_write (guchar         *mapGimp);
 
-static void          save_header          (FILE          *fd,
-                                           GimpImage     *image);
+static void          save_header          (GOutputStream  *output,
+                                           GimpImage      *image);
 
-static void          save_color_mode_data (FILE          *fd,
-                                           GimpImage     *image);
+static void          save_color_mode_data (GOutputStream  *output,
+                                           GimpImage      *image);
 
-static void          save_resources       (FILE          *fd,
-                                           GimpImage     *image);
+static void          save_resources       (GOutputStream  *output,
+                                           GimpImage      *image);
 
-static void          save_layer_and_mask  (FILE          *fd,
-                                           GimpImage     *image);
+static void          save_layer_and_mask  (GOutputStream  *output,
+                                           GimpImage      *image);
 
-static void          save_data            (FILE          *fd,
-                                           GimpImage     *image);
+static void          save_data            (GOutputStream  *output,
+                                           GimpImage      *image);
 
-static void          xfwrite              (FILE          *fd,
-                                           gconstpointer  buf,
-                                           glong          len,
-                                           const gchar   *why);
+static void          xfwrite              (GOutputStream  *output,
+                                           gconstpointer   buf,
+                                           gsize           len,
+                                           const gchar    *why);
 
-static void          write_pascalstring   (FILE          *fd,
-                                           const gchar   *val,
-                                           gint           padding,
-                                           const gchar   *why);
+static void          write_pascalstring   (GOutputStream  *output,
+                                           const gchar    *val,
+                                           gint            padding,
+                                           const gchar    *why);
 
-static void          write_string         (FILE          *fd,
-                                           const gchar   *val,
-                                           const gchar   *why);
+static void          write_string         (GOutputStream  *output,
+                                           const gchar    *val,
+                                           const gchar    *why);
 
-static void          write_gchar          (FILE          *fd,
-                                           guchar         val,
-                                           const gchar   *why);
+static void          write_gchar          (GOutputStream  *output,
+                                           guchar          val,
+                                           const gchar    *why);
 
-static void          write_gint16         (FILE          *fd,
-                                           gint16         val,
-                                           const gchar   *why);
+static void          write_gint16         (GOutputStream  *output,
+                                           gint16          val,
+                                           const gchar    *why);
 
-static void          write_gint32         (FILE          *fd,
-                                           gint32         val,
-                                           const gchar   *why);
+static void          write_gint32         (GOutputStream  *output,
+                                           gint32          val,
+                                           const gchar    *why);
 
-static void          write_datablock_luni (FILE          *fd,
-                                           const gchar   *val,
-                                           const gchar   *why);
+static void          write_datablock_luni (GOutputStream  *output,
+                                           const gchar    *val,
+                                           const gchar    *why);
 
 
-static void          write_pixel_data     (FILE          *fd,
-                                           GimpDrawable  *drawable,
-                                           glong         *ChanLenPosition,
-                                           gint32         rowlenOffset,
-                                           gboolean       write_mask);
+static void          write_pixel_data     (GOutputStream  *output,
+                                           GimpDrawable   *drawable,
+                                           goffset        *ChanLenPosition,
+                                           goffset         rowlenOffset,
+                                           gboolean        write_mask);
 
-static GimpLayer   * create_merged_image  (GimpImage     *image);
+static GimpLayer   * create_merged_image  (GimpImage      *image);
 
-static gint          get_bpc              (GimpImage     *image);
-static const Babl  * get_pixel_format     (GimpDrawable  *drawable);
-static const Babl  * get_channel_format   (GimpDrawable  *drawable);
-static const Babl  * get_mask_format      (GimpLayerMask *mask);
+static gint          get_bpc              (GimpImage      *image);
+static const Babl  * get_pixel_format     (GimpDrawable   *drawable);
+static const Babl  * get_channel_format   (GimpDrawable   *drawable);
+static const Babl  * get_mask_format      (GimpLayerMask  *mask);
 
-static GList       * image_get_all_layers (GimpImage     *image,
-                                           gint          *n_layers);
+static GList       * image_get_all_layers (GimpImage      *image,
+                                           gint           *n_layers);
 
 static const gchar *
 psd_lmode_layer (GimpLayer *layer,
@@ -225,19 +225,19 @@ psd_lmode_layer (GimpLayer *layer,
 }
 
 static void
-write_string (FILE        *fd,
-              const gchar *val,
-              const gchar *why)
+write_string (GOutputStream  *output,
+              const gchar    *val,
+              const gchar    *why)
 {
-  write_gchar (fd, strlen (val), why);
-  xfwrite (fd, val, strlen (val), why);
+  write_gchar (output, strlen (val), why);
+  xfwrite (output, val, strlen (val), why);
 }
 
 static void
-write_pascalstring (FILE        *fd,
-                    const gchar *val,
-                    gint         padding,
-                    const gchar *why)
+write_pascalstring (GOutputStream  *output,
+                    const gchar    *val,
+                    gint            padding,
+                    const gchar    *why)
 {
   guchar len;
   gint   i;
@@ -250,12 +250,12 @@ write_pascalstring (FILE        *fd,
 
   if (len !=  0)
     {
-      write_gchar (fd, len, why);
-      xfwrite (fd, val, len, why);
+      write_gchar (output, len, why);
+      xfwrite (output, val, len, why);
     }
   else
     {
-      write_gchar (fd, 0, why);
+      write_gchar (output, 0, why);
     }
 
   /* If total length (length byte + content) is not a multiple of PADDING,
@@ -267,19 +267,25 @@ write_pascalstring (FILE        *fd,
     return;
 
   for (i = 0; i < (padding - (len % padding)); i++)
-    write_gchar (fd, 0, why);
+    write_gchar (output, 0, why);
 }
 
 static void
-xfwrite (FILE          *fd,
-         gconstpointer  buf,
-         glong          len,
-         const gchar   *why)
+xfwrite (GOutputStream  *output,
+         gconstpointer   buf,
+         gsize           len,
+         const gchar    *why)
 {
+  gsize bytes_written;
+
   if (len == 0)
     return;
 
-  if (fwrite (buf, len, 1, fd) == 0)
+  /* FIXME Instead of NULL use error parameter and add error to all functions!
+   * and then we also need to change functions from void to gboolean or something
+   * and check the return values. */
+  if (! g_output_stream_write_all (output, buf, len,
+                                   &bytes_written, NULL, NULL))
     {
       g_printerr ("%s: Error while writing '%s'\n", G_STRFUNC, why);
       gimp_quit ();
@@ -287,38 +293,47 @@ xfwrite (FILE          *fd,
 }
 
 static void
-write_gchar (FILE        *fd,
-             guchar       val,
-             const gchar *why)
+write_gchar (GOutputStream  *output,
+             guchar          val,
+             const gchar    *why)
 {
-  guchar b[2];
-  glong  pos;
+  guchar   b[2];
+  goffset  pos;
+  gsize    bytes_written;
 
   b[0] = val;
   b[1] = 0;
 
-  pos = ftell (fd);
-  if (fwrite (&b, 1, 2, fd) == 0)
+  pos = g_seekable_tell (G_SEEKABLE (output));
+  /* FIXME: Use error in write and seek */
+  if (! g_output_stream_write_all (output, &b, 2,
+                                   &bytes_written, NULL, NULL))
     {
       g_printerr ("%s: Error while writing '%s'\n", G_STRFUNC, why);
       gimp_quit ();
     }
-  fseek (fd, pos + 1, SEEK_SET);
+  g_seekable_seek (G_SEEKABLE (output),
+                   pos + 1, G_SEEK_SET,
+                   NULL, NULL);
 }
 
 static void
-write_gint16 (FILE        *fd,
-              gint16       val,
-              const gchar *why)
+write_gint16 (GOutputStream  *output,
+              gint16          val,
+              const gchar    *why)
 {
   guchar b[2];
+  gsize  bytes_written;
+
   /*  b[0] = val & 255;
       b[1] = (val >> 8) & 255;*/
 
   b[1] = val & 255;
   b[0] = (val >> 8) & 255;
 
-  if (fwrite (&b, 1, 2, fd) == 0)
+  /* FIXME: Use error */
+  if (! g_output_stream_write_all (output, &b, 2,
+                                   &bytes_written, NULL, NULL))
     {
       g_printerr ("%s: Error while writing '%s'\n", G_STRFUNC, why);
       gimp_quit ();
@@ -326,18 +341,21 @@ write_gint16 (FILE        *fd,
 }
 
 static void
-write_gint32 (FILE        *fd,
-              gint32       val,
-              const gchar *why)
+write_gint32 (GOutputStream  *output,
+              gint32          val,
+              const gchar    *why)
 {
   guchar b[4];
+  gsize  bytes_written;
 
   b[3] = val & 255;
   b[2] = (val >> 8) & 255;
   b[1] = (val >> 16) & 255;
   b[0] = (val >> 24) & 255;
 
-  if (fwrite (&b, 1, 4, fd) == 0)
+  /* FIXME: Use error */
+  if (! g_output_stream_write_all (output, &b, 4,
+                                   &bytes_written, NULL, NULL))
     {
       g_printerr ("%s: Error while writing '%s'\n", G_STRFUNC, why);
       gimp_quit ();
@@ -345,9 +363,9 @@ write_gint32 (FILE        *fd,
 }
 
 static void
-write_datablock_luni (FILE        *fd,
-                      const gchar *val,
-                      const gchar *why)
+write_datablock_luni (GOutputStream  *output,
+                      const gchar    *val,
+                      const gchar    *why)
 {
   if (val)
     {
@@ -371,16 +389,16 @@ write_datablock_luni (FILE        *fd,
           /* 2 bytes / char + 4 bytes for pascal num chars */
           xdBlockSize = (xdBlockSize * 2) + 4;
 
-          xfwrite (fd, "8BIMluni", 8, "luni xdb signature");
-          write_gint32 (fd, xdBlockSize, "luni xdb size");
-          write_gint32 (fd, len, "luni xdb pascal string");
+          xfwrite (output, "8BIMluni", 8, "luni xdb signature");
+          write_gint32 (output, xdBlockSize, "luni xdb size");
+          write_gint32 (output, len, "luni xdb pascal string");
 
           for (count = 0; count < len; count++)
-            write_gint16 (fd, luniName[count], "luni xdb pascal string");
+            write_gint16 (output, luniName[count], "luni xdb pascal string");
 
           /* Pad to an even number of chars */
           if (len % 2)
-            write_gint16 (fd, 0x0000, "luni xdb pascal string padding");
+            write_gint16 (output, 0x0000, "luni xdb pascal string padding");
         }
     }
 }
@@ -516,8 +534,8 @@ reshuffle_cmap_write (guchar *mapGimp)
 }
 
 static void
-save_header (FILE      *fd,
-             GimpImage *image)
+save_header (GOutputStream  *output,
+             GimpImage      *image)
 {
   IFDBG printf (" Function: save_header\n");
   IFDBG printf ("\tRows: %d\n", PSDImageData.image_height);
@@ -525,23 +543,23 @@ save_header (FILE      *fd,
   IFDBG printf ("\tBase type: %d\n", PSDImageData.baseType);
   IFDBG printf ("\tNumber of channels: %d\n", PSDImageData.nChannels);
 
-  xfwrite (fd, "8BPS", 4, "signature");
-  write_gint16 (fd, 1, "version");
-  write_gint32 (fd, 0, "reserved 1");      /* 6 for the 'reserved' field + 4 bytes for a long */
-  write_gint16 (fd, 0, "reserved 1");      /* and 2 bytes for a short */
-  write_gint16 (fd, (PSDImageData.nChannels +
-                     nChansLayer (PSDImageData.baseType,
-                     gimp_drawable_has_alpha (GIMP_DRAWABLE (PSDImageData.merged_layer)), 0)),
-                "channels");
-  write_gint32 (fd, PSDImageData.image_height, "rows");
-  write_gint32 (fd, PSDImageData.image_width, "columns");
-  write_gint16 (fd, 8 * get_bpc (image), "depth");
-  write_gint16 (fd, gimpBaseTypeToPsdMode (PSDImageData.baseType), "mode");
+  xfwrite (output, "8BPS", 4, "signature");
+  write_gint16 (output, 1, "version");
+  write_gint32 (output, 0, "reserved 1");      /* 6 for the 'reserved' field + 4 bytes for a long */
+  write_gint16 (output, 0, "reserved 1");      /* and 2 bytes for a short */
+  write_gint16 (output, (PSDImageData.nChannels +
+                        nChansLayer (PSDImageData.baseType,
+                        gimp_drawable_has_alpha (GIMP_DRAWABLE (PSDImageData.merged_layer)), 0)),
+                        "channels");
+  write_gint32 (output, PSDImageData.image_height, "rows");
+  write_gint32 (output, PSDImageData.image_width, "columns");
+  write_gint16 (output, 8 * get_bpc (image), "depth");
+  write_gint16 (output, gimpBaseTypeToPsdMode (PSDImageData.baseType), "mode");
 }
 
 static void
-save_color_mode_data (FILE      *fd,
-                      GimpImage *image)
+save_color_mode_data (GOutputStream  *output,
+                      GimpImage      *image)
 {
   guchar *cmap;
   guchar *cmap_modified;
@@ -561,13 +579,13 @@ save_color_mode_data (FILE      *fd,
       if (nColors == 0)
         {
           IFDBG printf ("\t\tThe indexed image lacks a colormap\n");
-          write_gint32 (fd, 0, "color data length");
+          write_gint32 (output, 0, "color data length");
         }
       else if (nColors != 256)
         {
           IFDBG printf ("\t\tThe indexed image has %d!=256 colors\n", nColors);
           IFDBG printf ("\t\tPadding with zeros up to 256\n");
-          write_gint32 (fd, 768, "color data length");
+          write_gint32 (output, 768, "color data length");
             /* For this type, length is always 768 */
 
           cmap_modified = g_malloc (768);
@@ -578,36 +596,36 @@ save_color_mode_data (FILE      *fd,
             cmap_modified[i] = 0;
 
           reshuffle_cmap_write (cmap_modified);
-          xfwrite (fd, cmap_modified, 768, "colormap");  /* Write readjusted colormap */
+          xfwrite (output, cmap_modified, 768, "colormap");  /* Write readjusted colormap */
 
           g_free (cmap_modified);
         }
       else         /* nColors equals 256 */
         {
-          write_gint32 (fd, 768, "color data length");   /* For this type, length is always 768 */
+          write_gint32 (output, 768, "color data length");   /* For this type, length is always 768 */
           reshuffle_cmap_write (cmap);
-          xfwrite (fd, cmap, 768, "colormap");  /* Write readjusted colormap */
+          xfwrite (output, cmap, 768, "colormap");  /* Write readjusted colormap */
         }
       break;
 
     default:
       IFDBG printf ("\tImage type: Not INDEXED\n");
-      write_gint32 (fd, 0, "color data length");
+      write_gint32 (output, 0, "color data length");
     }
 }
 
 static void
-save_resources (FILE      *fd,
-                GimpImage *image)
+save_resources (GOutputStream  *output,
+                GimpImage      *image)
 {
   GList        *iter;
   gint          i;
   gchar        *fileName;            /* Image file name */
   GList        *SelLayers;           /* The selected layers */
 
-  glong         eof_pos;             /* Position for End of file */
-  glong         rsc_pos;             /* Position for Lengths of Resources section */
-  glong         name_sec;            /* Position for Lengths of Channel Names */
+  goffset       eof_pos;             /* Position for End of file */
+  goffset       rsc_pos;             /* Position for Lengths of Resources section */
+  goffset       name_sec;            /* Position for Lengths of Channel Names */
 
 
   /* Only relevant resources in GIMP are: 0x03EE, 0x03F0 & 0x0400 */
@@ -628,8 +646,8 @@ save_resources (FILE      *fd,
 
   /* Here's where actual writing starts */
 
-  rsc_pos = ftell (fd);
-  write_gint32 (fd, 0, "image resources length");
+  rsc_pos = g_seekable_tell (G_SEEKABLE (output));
+  write_gint32 (output, 0, "image resources length");
 
 
   /* --------------- Write Channel names --------------- */
@@ -637,45 +655,49 @@ save_resources (FILE      *fd,
   if (PSDImageData.nChannels > 0 ||
       gimp_drawable_has_alpha (GIMP_DRAWABLE (PSDImageData.merged_layer)))
     {
-      xfwrite (fd, "8BIM", 4, "imageresources signature");
-      write_gint16 (fd, 0x03EE, "0x03EE Id"); /* 1006 */
-      /* write_pascalstring (fd, Name, "Id name"); */
-      write_gint16 (fd, 0, "Id name"); /* Set to null string (two zeros) */
+      xfwrite (output, "8BIM", 4, "imageresources signature");
+      write_gint16 (output, 0x03EE, "0x03EE Id"); /* 1006 */
+      /* write_pascalstring (output, Name, "Id name"); */
+      write_gint16 (output, 0, "Id name"); /* Set to null string (two zeros) */
 
       /* Mark current position in the file */
 
-      name_sec = ftell (fd);
-      write_gint32 (fd, 0, "0x03EE resource size");
+      name_sec = g_seekable_tell (G_SEEKABLE (output));
+      write_gint32 (output, 0, "0x03EE resource size");
 
       /* Write all strings */
 
       /* if the merged_image contains transparency, write a name for it first */
       if (gimp_drawable_has_alpha (GIMP_DRAWABLE (PSDImageData.merged_layer)))
-        write_string (fd, "Transparency", "channel name");
+        write_string (output, "Transparency", "channel name");
 
       for (iter = PSDImageData.lChannels; iter; iter = g_list_next (iter))
         {
           char *chName = gimp_item_get_name (iter->data);
-          write_string (fd, chName, "channel name");
+          write_string (output, chName, "channel name");
           g_free (chName);
         }
       /* Calculate and write actual resource's length */
 
-      eof_pos = ftell (fd);
+      eof_pos = g_seekable_tell (G_SEEKABLE (output));
 
-      fseek (fd, name_sec, SEEK_SET);
-      write_gint32 (fd, eof_pos - name_sec - sizeof (gint32), "0x03EE resource size");
+      g_seekable_seek (G_SEEKABLE (output),
+                       name_sec, G_SEEK_SET,
+                       NULL, NULL /*FIXME: error*/);
+      write_gint32 (output, eof_pos - name_sec - sizeof (gint32), "0x03EE resource size");
       IFDBG printf ("\tTotal length of 0x03EE resource: %d\n",
                     (int) (eof_pos - name_sec - sizeof (gint32)));
 
       /* Return to EOF to continue writing */
 
-      fseek (fd, eof_pos, SEEK_SET);
+      g_seekable_seek (G_SEEKABLE (output),
+                       eof_pos, G_SEEK_SET,
+                       NULL, NULL /*FIXME: error*/);
 
       /* Pad if length is odd */
 
       if ((eof_pos - name_sec - sizeof (gint32)) & 1)
-        write_gchar (fd, 0, "pad byte");
+        write_gchar (output, 0, "pad byte");
     }
 
   /* --------------- Write Channel properties --------------- */
@@ -683,11 +705,11 @@ save_resources (FILE      *fd,
   if (PSDImageData.nChannels > 0 ||
       gimp_drawable_has_alpha (GIMP_DRAWABLE (PSDImageData.merged_layer)))
     {
-      xfwrite (fd, "8BIM", 4, "imageresources signature");
-      write_gint16 (fd, 0x0435, "0x0435 Id"); /* 1077 */
-      /* write_pascalstring (fd, Name, "Id name"); */
-      write_gint16 (fd, 0, "Id name"); /* Set to null string (two zeros) */
-      write_gint32 (fd,
+      xfwrite (output, "8BIM", 4, "imageresources signature");
+      write_gint16 (output, 0x0435, "0x0435 Id"); /* 1077 */
+      /* write_pascalstring (output, Name, "Id name"); */
+      write_gint16 (output, 0, "Id name"); /* Set to null string (two zeros) */
+      write_gint32 (output,
                     4  +
                     13 * (gimp_drawable_has_alpha (
                             GIMP_DRAWABLE (PSDImageData.merged_layer)) +
@@ -698,7 +720,7 @@ save_resources (FILE      *fd,
        * load_resource_1077() in psd-image-res-load.c, it seems to be a version
        * number that is always one.
        */
-      write_gint32 (fd, 1, "0x0435 version");
+      write_gint32 (output, 1, "0x0435 version");
 
       /* Write all channel properties */
 
@@ -707,13 +729,13 @@ save_resources (FILE      *fd,
       /* if the merged_image contains transparency, write its properties first */
       if (gimp_drawable_has_alpha (GIMP_DRAWABLE (PSDImageData.merged_layer)))
         {
-          write_gint16 (fd, PSD_CS_RGB, "channel color space");
-          write_gint16 (fd, DOUBLE_TO_INT16 (1.0), "channel color r");
-          write_gint16 (fd, DOUBLE_TO_INT16 (0.0), "channel color g");
-          write_gint16 (fd, DOUBLE_TO_INT16 (0.0), "channel color b");
-          write_gint16 (fd, 0,                     "channel color padding");
-          write_gint16 (fd, 100,                   "channel opacity");
-          write_gchar  (fd, 1,                     "channel mode");
+          write_gint16 (output, PSD_CS_RGB, "channel color space");
+          write_gint16 (output, DOUBLE_TO_INT16 (1.0), "channel color r");
+          write_gint16 (output, DOUBLE_TO_INT16 (0.0), "channel color g");
+          write_gint16 (output, DOUBLE_TO_INT16 (0.0), "channel color b");
+          write_gint16 (output, 0,                     "channel color padding");
+          write_gint16 (output, 100,                   "channel opacity");
+          write_gchar  (output, 1,                     "channel mode");
         }
 
       for (iter = PSDImageData.lChannels; iter; iter = g_list_next (iter))
@@ -725,21 +747,21 @@ save_resources (FILE      *fd,
           gimp_channel_get_color (channel, &color);
           opacity = gimp_channel_get_opacity (channel);
 
-          write_gint16 (fd, PSD_CS_RGB,                "channel color space");
-          write_gint16 (fd, DOUBLE_TO_INT16 (color.r), "channel color r");
-          write_gint16 (fd, DOUBLE_TO_INT16 (color.g), "channel color g");
-          write_gint16 (fd, DOUBLE_TO_INT16 (color.b), "channel color b");
-          write_gint16 (fd, 0,                         "channel color padding");
-          write_gint16 (fd, ROUND (opacity),           "channel opacity");
-          write_gchar  (fd, 1,                         "channel mode");
+          write_gint16 (output, PSD_CS_RGB,                "channel color space");
+          write_gint16 (output, DOUBLE_TO_INT16 (color.r), "channel color r");
+          write_gint16 (output, DOUBLE_TO_INT16 (color.g), "channel color g");
+          write_gint16 (output, DOUBLE_TO_INT16 (color.b), "channel color b");
+          write_gint16 (output, 0,                         "channel color padding");
+          write_gint16 (output, ROUND (opacity),           "channel opacity");
+          write_gchar  (output, 1,                         "channel mode");
         }
 
       #undef DOUBLE_TO_INT16
 
       /* Pad if length is odd */
 
-      if (ftell (fd) & 1)
-        write_gchar (fd, 0, "pad byte");
+      if (g_seekable_tell (G_SEEKABLE (output)) & 1)
+        write_gchar (output, 0, "pad byte");
     }
 
   /* --------------- Write Guides --------------- */
@@ -752,16 +774,16 @@ save_resources (FILE      *fd,
       while ((guide_id = gimp_image_find_next_guide(image, guide_id)))
         n_guides++;
 
-      xfwrite (fd, "8BIM", 4, "imageresources signature");
-      write_gint16 (fd, 0x0408, "0x0408 Id (Guides)"); /* 1032 */
-      /* write_pascalstring (fd, Name, "Id name"); */
-      write_gint16 (fd, 0, "Id name"); /* Set to null string (two zeros) */
-      write_gint32 (fd, 16 + 5 * n_guides, "0x0408 resource size");
+      xfwrite (output, "8BIM", 4, "imageresources signature");
+      write_gint16 (output, 0x0408, "0x0408 Id (Guides)"); /* 1032 */
+      /* write_pascalstring (output, Name, "Id name"); */
+      write_gint16 (output, 0, "Id name"); /* Set to null string (two zeros) */
+      write_gint32 (output, 16 + 5 * n_guides, "0x0408 resource size");
       /* Save grid and guide header */
-      write_gint32 (fd,   1, "grid/guide header version");
-      write_gint32 (fd, 576, "grid custom spacing horizontal");/* dpi*32/4??*/
-      write_gint32 (fd, 576, "grid custom spacing vertical");  /* dpi*32/4??*/
-      write_gint32 (fd, n_guides, "number of guides");
+      write_gint32 (output,   1, "grid/guide header version");
+      write_gint32 (output, 576, "grid custom spacing horizontal");/* dpi*32/4??*/
+      write_gint32 (output, 576, "grid custom spacing vertical");  /* dpi*32/4??*/
+      write_gint32 (output, n_guides, "number of guides");
 
       /* write the guides */
       while ((guide_id = gimp_image_find_next_guide (image, guide_id)))
@@ -771,12 +793,12 @@ save_resources (FILE      *fd,
           orientation = gimp_image_get_guide_orientation (image, guide_id);
           position    = 32 * gimp_image_get_guide_position (image, guide_id);
           orientation ^= 1; /* in the psd vert =0 , horiz = 1 */
-          write_gint32 (fd, position, "Position of guide");
-          write_gchar (fd, orientation, "Orientation of guide");
+          write_gint32 (output, position, "Position of guide");
+          write_gchar (output, orientation, "Orientation of guide");
           n_guides--;
         }
-      if ((ftell(fd) & 1))
-        write_gchar(fd, 0, "pad byte");
+      if ((g_seekable_tell (G_SEEKABLE (output)) & 1))
+        write_gchar(output, 0, "pad byte");
       if (n_guides != 0)
         g_warning("Screwed up guide resource:: wrong number of guides\n");
       IFDBG printf ("\tTotal length of 0x0400 resource: %d\n", (int) sizeof (gint16));
@@ -809,16 +831,16 @@ save_resources (FILE      *fd,
     xres_fix = xres * 65536.0 + .5; /* Convert to 16.16 fixed point */
     yres_fix = yres * 65536.0 + .5; /* Convert to 16.16 fixed point */
 
-    xfwrite (fd, "8BIM", 4, "imageresources signature (for resolution)");
-    write_gint16(fd, 0x03ed, "0x03ed Id (resolution)"); /* 1005 */
-    write_gint16 (fd, 0, "Id name"); /* Set to null string (two zeros) */
-    write_gint32 (fd, 16, "0x0400 resource size");
-    write_gint32 (fd,  xres_fix, "hRes (16.16 fixed point)");
-    write_gint16 (fd, psd_unit, "hRes unit");
-    write_gint16 (fd, psd_unit, "width unit");
-    write_gint32 (fd,  yres_fix, "vRes (16.16 fixed point)");
-    write_gint16 (fd, psd_unit, "vRes unit");
-    write_gint16 (fd, psd_unit, "height unit");
+    xfwrite (output, "8BIM", 4, "imageresources signature (for resolution)");
+    write_gint16(output, 0x03ed, "0x03ed Id (resolution)"); /* 1005 */
+    write_gint16 (output, 0, "Id name"); /* Set to null string (two zeros) */
+    write_gint32 (output, 16, "0x0400 resource size");
+    write_gint32 (output,  xres_fix, "hRes (16.16 fixed point)");
+    write_gint16 (output, psd_unit, "hRes unit");
+    write_gint16 (output, psd_unit, "width unit");
+    write_gint32 (output,  yres_fix, "vRes (16.16 fixed point)");
+    write_gint16 (output, psd_unit, "vRes unit");
+    write_gint16 (output, psd_unit, "height unit");
   }
 
   /* --------------- Write Selected Layers --------------- */
@@ -841,14 +863,14 @@ save_resources (FILE      *fd,
             {
               if (SelLayers->data == ((PSD_Layer *) iter->data)->layer)
                 {
-                  xfwrite (fd, "8BIM", 4, "imageresources signature");
-                  write_gint16 (fd, 0x0400, "0x0400 Id"); /* 1024 */
-                  /* write_pascalstring (fd, Name, "Id name"); */
-                  write_gint16 (fd, 0, "Id name"); /* Set to null string (two zeros) */
-                  write_gint32 (fd, sizeof (gint16), "0x0400 resource size");
+                  xfwrite (output, "8BIM", 4, "imageresources signature");
+                  write_gint16 (output, 0x0400, "0x0400 Id"); /* 1024 */
+                  /* write_pascalstring (output, Name, "Id name"); */
+                  write_gint16 (output, 0, "Id name"); /* Set to null string (two zeros) */
+                  write_gint32 (output, sizeof (gint16), "0x0400 resource size");
 
                   /* Layer State Information uses the layer index. */
-                  write_gint16 (fd, PSDImageData.nLayers - i - 1, "active layer");
+                  write_gint16 (output, PSDImageData.nLayers - i - 1, "active layer");
 
                   IFDBG printf ("\tTotal length of 0x0400 resource: %d\n", (int) sizeof (gint16));
                   break;
@@ -859,13 +881,13 @@ save_resources (FILE      *fd,
       /* Write the Layer Selection ID(s) block when there is at least
        * one selected layer or more.
        */
-      xfwrite (fd, "8BIM", 4, "imageresources signature");
-      write_gint16 (fd, 0x042D, "0x042D Id"); /* 1069 */
-      write_gint16 (fd, 0, "Id name"); /* Set to null string (two zeros) */
-      write_gint32 (fd, sizeof (gint16) + sizeof (gint32) * g_list_length (SelLayers), "0x0400 resource 
size");
-      write_gint16 (fd, g_list_length (SelLayers), "2 bytes count");
+      xfwrite (output, "8BIM", 4, "imageresources signature");
+      write_gint16 (output, 0x042D, "0x042D Id"); /* 1069 */
+      write_gint16 (output, 0, "Id name"); /* Set to null string (two zeros) */
+      write_gint32 (output, sizeof (gint16) + sizeof (gint32) * g_list_length (SelLayers), "0x0400 resource 
size");
+      write_gint16 (output, g_list_length (SelLayers), "2 bytes count");
       for (iter = SelLayers; iter; iter = iter->next)
-        write_gint32 (fd, GPOINTER_TO_INT (gimp_item_get_tattoo (iter->data)), "4 bytes layer ID");
+        write_gint32 (output, GPOINTER_TO_INT (gimp_item_get_tattoo (iter->data)), "4 bytes layer ID");
     }
   g_list_free (SelLayers);
 
@@ -882,11 +904,11 @@ save_resources (FILE      *fd,
 
         icc_data = gimp_color_profile_get_icc_profile (profile, &icc_length);
 
-        xfwrite (fd, "8BIM", 4, "imageresources signature");
-        write_gint16 (fd, 0x040f, "0x040f Id");
-        write_gint16 (fd, 0, "Id name"); /* Set to null string (two zeros) */
-        write_gint32 (fd, icc_length, "0x040f resource size");
-        xfwrite (fd, icc_data, icc_length, "ICC profile");
+        xfwrite (output, "8BIM", 4, "imageresources signature");
+        write_gint16 (output, 0x040f, "0x040f Id");
+        write_gint16 (output, 0, "Id name"); /* Set to null string (two zeros) */
+        write_gint32 (output, icc_length, "0x040f resource size");
+        xfwrite (output, icc_data, icc_length, "ICC profile");
 
         g_object_unref (profile);
       }
@@ -894,16 +916,20 @@ save_resources (FILE      *fd,
 
   /* --------------- Write Total Section Length --------------- */
 
-  eof_pos = ftell (fd);
+  eof_pos = g_seekable_tell (G_SEEKABLE (output));
 
-  fseek (fd, rsc_pos, SEEK_SET);
-  write_gint32 (fd, eof_pos - rsc_pos - sizeof (gint32), "image resources length");
+  g_seekable_seek (G_SEEKABLE (output),
+                   rsc_pos, G_SEEK_SET,
+                   NULL, NULL /*FIXME: error*/);
+  write_gint32 (output, eof_pos - rsc_pos - sizeof (gint32), "image resources length");
   IFDBG printf ("\tResource section total length: %d\n",
                 (int) (eof_pos - rsc_pos - sizeof (gint32)));
 
   /* Return to EOF to continue writing */
 
-  fseek (fd, eof_pos, SEEK_SET);
+  g_seekable_seek (G_SEEKABLE (output),
+                   eof_pos, G_SEEK_SET,
+                   NULL, NULL /*FIXME: error*/);
 }
 
 static int
@@ -994,8 +1020,8 @@ get_compress_channel_data (guchar  *channel_data,
 }
 
 static void
-save_layer_and_mask (FILE      *fd,
-                     GimpImage *image)
+save_layer_and_mask (GOutputStream  *output,
+                     GimpImage      *image)
 {
   gint           i,j;
   gint           idChannel;
@@ -1011,13 +1037,13 @@ save_layer_and_mask (FILE      *fd,
   gchar         *layerName;              /* Layer name */
   GimpLayerMask *mask;                   /* Layer mask */
   gint           depth;                  /* Layer group nesting depth */
-  gint          bpc;                     /* Image BPC */
+  gint           bpc;                    /* Image BPC */
 
-  glong          eof_pos;                /* Position: End of file */
-  glong          ExtraDataPos;           /* Position: Extra data length */
-  glong          LayerMaskPos;           /* Position: Layer & Mask section length */
-  glong          LayerInfoPos;           /* Position: Layer info section length*/
-  glong        **ChannelLengthPos;       /* Position: Channel length */
+  goffset        eof_pos;                /* Position: End of file */
+  goffset        ExtraDataPos;           /* Position: Extra data length */
+  goffset        LayerMaskPos;           /* Position: Layer & Mask section length */
+  goffset        LayerInfoPos;           /* Position: Layer info section length*/
+  goffset      **ChannelLengthPos;       /* Position: Channel length */
   GList         *iter;
 
 
@@ -1025,24 +1051,24 @@ save_layer_and_mask (FILE      *fd,
 
   /* Create first array dimension (layers, channels) */
 
-  ChannelLengthPos = g_newa (glong *, PSDImageData.nLayers);
+  ChannelLengthPos = g_newa (goffset *, PSDImageData.nLayers);
 
   /* Layer and mask information section */
 
-  LayerMaskPos = ftell (fd);
-  write_gint32 (fd, 0, "layers & mask information length");
+  LayerMaskPos = g_seekable_tell (G_SEEKABLE (output));
+  write_gint32 (output, 0, "layers & mask information length");
 
   /* Layer info section */
 
-  LayerInfoPos = ftell (fd);
-  write_gint32 (fd, 0, "layers info section length");
+  LayerInfoPos = g_seekable_tell (G_SEEKABLE (output));
+  write_gint32 (output, 0, "layers info section length");
 
   /* Layer structure section */
 
   if (gimp_drawable_has_alpha (GIMP_DRAWABLE (PSDImageData.merged_layer)))
-    write_gint16 (fd, -PSDImageData.nLayers, "Layer structure count");
+    write_gint16 (output, -PSDImageData.nLayers, "Layer structure count");
   else
-    write_gint16 (fd, PSDImageData.nLayers, "Layer structure count");
+    write_gint16 (output, PSDImageData.nLayers, "Layer structure count");
 
   depth = 0;
 
@@ -1095,10 +1121,10 @@ save_layer_and_mask (FILE      *fd,
       IFDBG printf ("\t\tWidth: %d\n", layerWidth);
       IFDBG printf ("\t\tHeight: %d\n", layerHeight);
 
-      write_gint32 (fd, offset_y,               "Layer top");
-      write_gint32 (fd, offset_x,               "Layer left");
-      write_gint32 (fd, offset_y + layerHeight, "Layer bottom");
-      write_gint32 (fd, offset_x + layerWidth,  "Layer right");
+      write_gint32 (output, offset_y,               "Layer top");
+      write_gint32 (output, offset_x,               "Layer left");
+      write_gint32 (output, offset_y + layerHeight, "Layer bottom");
+      write_gint32 (output, offset_x + layerWidth,  "Layer right");
 
       hasMask = (psd_layer->type != PSD_LAYER_TYPE_GROUP_END &&
                  gimp_layer_get_mask (psd_layer->layer) != NULL);
@@ -1107,12 +1133,12 @@ save_layer_and_mask (FILE      *fd,
                                     hasMask);
 
 
-      write_gint16 (fd, nChannelsLayer, "Number channels in the layer");
+      write_gint16 (output, nChannelsLayer, "Number channels in the layer");
       IFDBG printf ("\t\tNumber of channels: %d\n", nChannelsLayer);
 
       /* Create second array dimension (layers, channels) */
 
-      ChannelLengthPos[i] = g_new (glong, nChannelsLayer);
+      ChannelLengthPos[i] = g_new (goffset, nChannelsLayer);
 
       /* Try with gimp_drawable_get_bpp() */
 
@@ -1125,44 +1151,44 @@ save_layer_and_mask (FILE      *fd,
           if (hasMask && (j+1 == nChannelsLayer)) /* Last channel ... */
             idChannel = -2; /* ... will be layer mask */
 
-          write_gint16 (fd, idChannel, "Channel ID");
+          write_gint16 (output, idChannel, "Channel ID");
           IFDBG printf ("\t\t\tChannel Identifier: %d\n", idChannel);
 
           /* Write the length assuming no compression.  In case there is,
              will modify it later when writing data.  */
 
-          ChannelLengthPos[i][j] = ftell (fd);
+          ChannelLengthPos[i][j] = g_seekable_tell (G_SEEKABLE (output));
           ChanSize = sizeof (gint16) + (layerWidth * layerHeight * bpc);
 
-          write_gint32 (fd, ChanSize, "Channel Size");
+          write_gint32 (output, ChanSize, "Channel Size");
           IFDBG printf ("\t\t\tLength: %d\n", ChanSize);
         }
 
-      xfwrite (fd, "8BIM", 4, "blend mode signature");
+      xfwrite (output, "8BIM", 4, "blend mode signature");
 
       blendMode = psd_lmode_layer (psd_layer->layer, FALSE);
       IFDBG printf ("\t\tBlend mode: %s\n", blendMode);
-      xfwrite (fd, blendMode, 4, "blend mode key");
+      xfwrite (output, blendMode, 4, "blend mode key");
 
       layerOpacity = RINT ((gimp_layer_get_opacity (psd_layer->layer) * 255.0) / 100.0);
       IFDBG printf ("\t\tOpacity: %u\n", layerOpacity);
-      write_gchar (fd, layerOpacity, "Opacity");
+      write_gchar (output, layerOpacity, "Opacity");
 
       /* Apparently this field is not used in GIMP */
-      write_gchar (fd, 0, "Clipping");
+      write_gchar (output, 0, "Clipping");
 
       flags = 0;
       if (gimp_layer_get_lock_alpha (psd_layer->layer)) flags |= 1;
       if (! gimp_item_get_visible (GIMP_ITEM (psd_layer->layer))) flags |= 2;
       if (psd_layer->type != PSD_LAYER_TYPE_LAYER) flags |= 0x18;
       IFDBG printf ("\t\tFlags: %u\n", flags);
-      write_gchar (fd, flags, "Flags");
+      write_gchar (output, flags, "Flags");
 
       /* Padding byte to make the length even */
-      write_gchar (fd, 0, "Filler");
+      write_gchar (output, 0, "Filler");
 
-      ExtraDataPos = ftell (fd); /* Position of Extra Data size */
-      write_gint32 (fd, 0, "Extra data size");
+      ExtraDataPos = g_seekable_tell (G_SEEKABLE (output)); /* Position of Extra Data size */
+      write_gint32 (output, 0, "Extra data size");
 
       if (hasMask)
         {
@@ -1181,56 +1207,56 @@ save_layer_and_mask (FILE      *fd,
           apply      = gimp_layer_get_apply_mask (psd_layer->layer);
 
           IFDBG printf ("\t\tLayer mask size: %d\n", 20);
-          write_gint32 (fd, 20,                        "Layer mask size");
-          write_gint32 (fd, maskOffset_y,              "Layer mask top");
-          write_gint32 (fd, maskOffset_x,              "Layer mask left");
-          write_gint32 (fd, maskOffset_y + maskHeight, "Layer mask bottom");
-          write_gint32 (fd, maskOffset_x + maskWidth,  "Layer mask right");
-          write_gchar  (fd, 0,                         "Layer mask default color");
+          write_gint32 (output, 20,                        "Layer mask size");
+          write_gint32 (output, maskOffset_y,              "Layer mask top");
+          write_gint32 (output, maskOffset_x,              "Layer mask left");
+          write_gint32 (output, maskOffset_y + maskHeight, "Layer mask bottom");
+          write_gint32 (output, maskOffset_x + maskWidth,  "Layer mask right");
+          write_gchar  (output, 0,                         "Layer mask default color");
           flags = (0                    |  /* position relative to layer */
                    (apply ? 0 : 1) << 1 |  /* layer mask disabled        */
                    0 << 2);                /* invert layer mask          */
-          write_gchar  (fd, flags,                     "Layer mask flags");
-          write_gint16 (fd, 0,                         "Layer mask Padding");
+          write_gchar  (output, flags,                     "Layer mask flags");
+          write_gint16 (output, 0,                         "Layer mask Padding");
         }
       else
         {
           /* NOTE Writing empty Layer mask / adjustment layer data */
-          write_gint32 (fd, 0, "Layer mask size");
+          write_gint32 (output, 0, "Layer mask size");
           IFDBG printf ("\t\tLayer mask size: %d\n", 0);
         }
 
       /* NOTE Writing empty Layer blending ranges data */
-      write_gint32 (fd, 0, "Layer blending size");
+      write_gint32 (output, 0, "Layer blending size");
       IFDBG printf ("\t\tLayer blending size: %d\n", 0);
 
       if (psd_layer->type != PSD_LAYER_TYPE_GROUP_END)
         layerName = gimp_item_get_name (GIMP_ITEM (psd_layer->layer));
       else
         layerName = g_strdup ("</Layer group>");
-      write_pascalstring (fd, layerName, 4, "layer name");
+      write_pascalstring (output, layerName, 4, "layer name");
       IFDBG printf ("\t\tLayer name: %s\n", layerName);
 
       /* Additional layer information blocks */
       /* Unicode layer name */
-      write_datablock_luni (fd, layerName, "luni extra data block");
+      write_datablock_luni (output, layerName, "luni extra data block");
 
       g_free (layerName);
 
       /* Layer ID */
-      xfwrite (fd, "8BIMlyid", 8, "lyid signature");
-      write_gint32 (fd, 4, "lyid size");
-      write_gint32 (fd, gimp_item_get_tattoo (GIMP_ITEM (psd_layer->layer)), "Layer ID");
+      xfwrite (output, "8BIMlyid", 8, "lyid signature");
+      write_gint32 (output, 4, "lyid size");
+      write_gint32 (output, gimp_item_get_tattoo (GIMP_ITEM (psd_layer->layer)), "Layer ID");
 
       /* Layer color tag */
-      xfwrite (fd, "8BIMlclr", 8, "sheet color signature");
-      write_gint32 (fd, 8, "sheet color size");
-      write_gint16 (fd,
+      xfwrite (output, "8BIMlclr", 8, "sheet color signature");
+      write_gint32 (output, 8, "sheet color size");
+      write_gint16 (output,
                     gimp_to_psd_layer_color_tag (gimp_item_get_color_tag (GIMP_ITEM (psd_layer->layer))),
                     "sheet color code");
-      write_gint16 (fd, 0, "sheet color unused value");
-      write_gint16 (fd, 0, "sheet color unused value");
-      write_gint16 (fd, 0, "sheet color unused value");
+      write_gint16 (output, 0, "sheet color unused value");
+      write_gint16 (output, 0, "sheet color unused value");
+      write_gint16 (output, 0, "sheet color unused value");
 
       /* Group layer section divider */
       if (psd_layer->type != PSD_LAYER_TYPE_LAYER)
@@ -1257,7 +1283,7 @@ save_layer_and_mask (FILE      *fd,
 
           if (type < 3 || depth <= 5)
             {
-              xfwrite (fd, "8BIMlsct", 8, "section divider");
+              xfwrite (output, "8BIMlsct", 8, "section divider");
             }
           else
             {
@@ -1265,26 +1291,30 @@ save_layer_and_mask (FILE      *fd,
                * by Photoshop CS5 and up, and their end markers use the
                * (undocumented) "lsdk" key, instead of "lsct".
                */
-              xfwrite (fd, "8BIMlsdk", 8, "nested section divider");
+              xfwrite (output, "8BIMlsdk", 8, "nested section divider");
             }
-          write_gint32 (fd, size, "section divider size");
-          write_gint32 (fd, type, "section divider type");
-          xfwrite (fd, "8BIM", 4, "section divider blend mode signature");
-          xfwrite (fd, blendMode, 4, "section divider blend mode key");
+          write_gint32 (output, size, "section divider size");
+          write_gint32 (output, type, "section divider type");
+          xfwrite (output, "8BIM", 4, "section divider blend mode signature");
+          xfwrite (output, blendMode, 4, "section divider blend mode key");
         }
 
       /* Write real length for: Extra data */
 
-      eof_pos = ftell (fd);
+      eof_pos = g_seekable_tell (G_SEEKABLE (output));
 
-      fseek (fd, ExtraDataPos, SEEK_SET);
-      write_gint32 (fd, eof_pos - ExtraDataPos - sizeof (gint32), "Extra data size");
+      g_seekable_seek (G_SEEKABLE (output),
+                       ExtraDataPos, G_SEEK_SET,
+                       NULL, NULL /*FIXME: error*/);
+      write_gint32 (output, eof_pos - ExtraDataPos - sizeof (gint32), "Extra data size");
       IFDBG printf ("\t\tExtraData size: %d\n",
                     (int) (eof_pos - ExtraDataPos - sizeof (gint32)));
 
       /* Return to EOF to continue writing */
 
-      fseek (fd, eof_pos, SEEK_SET);
+      g_seekable_seek (G_SEEKABLE (output),
+                       eof_pos, G_SEEK_SET,
+                       NULL, NULL /*FIXME: error*/);
     }
 
 
@@ -1300,39 +1330,45 @@ save_layer_and_mask (FILE      *fd,
       gimp_progress_update ((PSDImageData.nLayers - i - 1.0) / (PSDImageData.nLayers + 1.0));
 
       IFDBG printf ("\t\tWriting pixel data for layer slot %d\n", i);
-      write_pixel_data (fd, GIMP_DRAWABLE (psd_layer->layer), ChannelLengthPos[i], 0,
+      write_pixel_data (output, GIMP_DRAWABLE (psd_layer->layer), ChannelLengthPos[i], 0,
                         psd_layer->type != PSD_LAYER_TYPE_GROUP_END);
       g_free (ChannelLengthPos[i]);
     }
 
   gimp_progress_update (PSDImageData.nLayers / (PSDImageData.nLayers + 1.0));
-  eof_pos = ftell (fd);
+  eof_pos = g_seekable_tell (G_SEEKABLE (output));
 
   /* Write actual size of Layer info section */
 
-  fseek (fd, LayerInfoPos, SEEK_SET);
-  write_gint32 (fd, eof_pos - LayerInfoPos - sizeof (gint32), "layers info section length");
+  g_seekable_seek (G_SEEKABLE (output),
+                   LayerInfoPos, G_SEEK_SET,
+                   NULL, NULL /*FIXME: error*/);
+  write_gint32 (output, eof_pos - LayerInfoPos - sizeof (gint32), "layers info section length");
   IFDBG printf ("\t\tTotal layers info section length: %d\n",
                 (int) (eof_pos - LayerInfoPos - sizeof (gint32)));
 
   /* Write actual size of Layer and mask information section */
 
-  fseek (fd, LayerMaskPos, SEEK_SET);
-  write_gint32 (fd, eof_pos - LayerMaskPos - sizeof (gint32), "layers & mask information length");
+  g_seekable_seek (G_SEEKABLE (output),
+                   LayerMaskPos, G_SEEK_SET,
+                   NULL, NULL /*FIXME: error*/);
+  write_gint32 (output, eof_pos - LayerMaskPos - sizeof (gint32), "layers & mask information length");
   IFDBG printf ("\t\tTotal layers & mask information length: %d\n",
                 (int) (eof_pos - LayerMaskPos - sizeof (gint32)));
 
   /* Return to EOF to continue writing */
 
-  fseek (fd, eof_pos, SEEK_SET);
+  g_seekable_seek (G_SEEKABLE (output),
+                   eof_pos, G_SEEK_SET,
+                   NULL, NULL /*FIXME: error*/);
 }
 
 static void
-write_pixel_data (FILE         *fd,
-                  GimpDrawable *drawable,
-                  glong        *ChanLenPosition,
-                  gint32        ltable_offset,
-                  gboolean      write_mask)
+write_pixel_data (GOutputStream  *output,
+                  GimpDrawable   *drawable,
+                  goffset        *ChanLenPosition,
+                  goffset         ltable_offset,
+                  gboolean        write_mask)
 {
   GeglBuffer    *buffer = gimp_drawable_get_buffer (drawable);
   const Babl    *format;
@@ -1345,11 +1381,11 @@ write_pixel_data (FILE         *fd,
   gint32         bpc;
   gint32         colors;
   gint32         y;
-  gint32         len;                  /* Length of compressed data */
+  gsize          len;                  /* Length of compressed data */
   gint16        *LengthsTable;         /* Lengths of every compressed row */
   guchar        *rledata;              /* Compressed data from a region */
   guchar        *data;                 /* Temporary copy of pixel data */
-  glong          length_table_pos;     /* position in file of the length table */
+  goffset        length_table_pos;     /* position in file of the length table */
   int            i, j;
 
   IFDBG printf (" Function: write_pixel_data, drw %d, lto %d\n",
@@ -1419,7 +1455,7 @@ write_pixel_data (FILE         *fd,
 
       if (ChanLenPosition)
         {
-          write_gint16 (fd, 1, "Compression type (RLE)");
+          write_gint16 (output, 1, "Compression type (RLE)");
           len += 2;
         }
 
@@ -1429,9 +1465,9 @@ write_pixel_data (FILE         *fd,
         }
       else
         {
-          length_table_pos = ftell(fd);
+          length_table_pos = g_seekable_tell (G_SEEKABLE (output));
 
-          xfwrite (fd, LengthsTable, height * sizeof(gint16),
+          xfwrite (output, LengthsTable, height * sizeof(gint16),
                    "Dummy RLE length");
           len += height * sizeof(gint16);
           IF_DEEP_DBG printf ("\t\t\t\t. ltable, pos %ld len %d\n", length_table_pos, len);
@@ -1453,23 +1489,29 @@ write_pixel_data (FILE         *fd,
                                             &LengthsTable[y],
                                             rledata);
           len += tlen;
-          xfwrite (fd, rledata, tlen, "Compressed pixel data");
+          xfwrite (output, rledata, tlen, "Compressed pixel data");
           IF_DEEP_DBG printf ("\t\t\t\t. Writing compressed pixels, stream of %d\n", tlen);
         }
 
       /* Write compressed lengths table */
-      fseek (fd, length_table_pos, SEEK_SET);
+      g_seekable_seek (G_SEEKABLE (output),
+                       length_table_pos, G_SEEK_SET,
+                       NULL, NULL /*FIXME: error*/);
       for (j = 0; j < height; j++) /* write real length table */
-        write_gint16 (fd, LengthsTable[j], "RLE length");
+        write_gint16 (output, LengthsTable[j], "RLE length");
 
       if (ChanLenPosition)    /* Update total compressed length */
         {
-          fseek (fd, ChanLenPosition[i], SEEK_SET);
-          write_gint32 (fd, len, "channel data length");
+          g_seekable_seek (G_SEEKABLE (output),
+                           ChanLenPosition[i], G_SEEK_SET,
+                           NULL, NULL /*FIXME: error*/);
+          write_gint32 (output, len, "channel data length");
           IFDBG printf ("\t\tUpdating data len to %d\n", len);
         }
-      fseek (fd, 0, SEEK_END);
-      IF_DEEP_DBG printf ("\t\t\t\t. Cur pos %ld\n", ftell(fd));
+      g_seekable_seek (G_SEEKABLE (output),
+                       0, G_SEEK_END,
+                       NULL, NULL /*FIXME: error*/);
+      IF_DEEP_DBG printf ("\t\t\t\t. Cur pos %ld\n", g_seekable_tell (G_SEEKABLE (output)));
     }
 
   /* Write layer mask, as last channel, id -2 */
@@ -1485,7 +1527,7 @@ write_pixel_data (FILE         *fd,
 
       if (ChanLenPosition)
         {
-          write_gint16 (fd, 1, "Compression type (RLE)");
+          write_gint16 (output, 1, "Compression type (RLE)");
           len += 2;
           IF_DEEP_DBG printf ("\t\t\t\t. ChanLenPos, len %d\n", len);
         }
@@ -1498,9 +1540,9 @@ write_pixel_data (FILE         *fd,
         }
       else
         {
-          length_table_pos = ftell(fd);
+          length_table_pos = g_seekable_tell (G_SEEKABLE (output));
 
-          xfwrite (fd, LengthsTable, height * sizeof(gint16),
+          xfwrite (output, LengthsTable, height * sizeof(gint16),
                    "Dummy RLE length");
           len += height * sizeof(gint16);
           IF_DEEP_DBG printf ("\t\t\t\t. ltable, pos %ld len %d\n",
@@ -1523,15 +1565,17 @@ write_pixel_data (FILE         *fd,
                                             &LengthsTable[y],
                                             rledata);
           len += tlen;
-          xfwrite (fd, rledata, tlen, "Compressed mask data");
+          xfwrite (output, rledata, tlen, "Compressed mask data");
           IF_DEEP_DBG printf ("\t\t\t\t. Writing compressed mask, stream of %d\n", tlen);
         }
 
       /* Write compressed lengths table */
-      fseek (fd, length_table_pos, SEEK_SET); /*POS WHERE???*/
+      g_seekable_seek (G_SEEKABLE (output),
+                       length_table_pos, G_SEEK_SET,
+                       NULL, NULL /*FIXME: error*/);
       for (j = 0; j < height; j++) /* write real length table */
         {
-          write_gint16 (fd, LengthsTable[j], "RLE length");
+          write_gint16 (output, LengthsTable[j], "RLE length");
           IF_DEEP_DBG printf ("\t\t\t\t. Updating RLE len %d\n",
                               LengthsTable[j]);
         }
@@ -1539,13 +1583,17 @@ write_pixel_data (FILE         *fd,
       if (ChanLenPosition)    /* Update total compressed length */
         {
           /* Mask follows other components so use that as offset. */
-          fseek (fd, ChanLenPosition[components], SEEK_SET);
+          g_seekable_seek (G_SEEKABLE (output),
+                           ChanLenPosition[components], G_SEEK_SET,
+                           NULL, NULL /*FIXME: error*/);
 
-          write_gint32 (fd, len, "channel data length");
-          IFDBG printf ("\t\tUpdating data len to %d, at %ld\n", len, ftell(fd));
+          write_gint32 (output, len, "channel data length");
+          IFDBG printf ("\t\tUpdating data len to %d, at %ld\n", len, g_seekable_tell (G_SEEKABLE (output)));
         }
-      fseek (fd, 0, SEEK_END);
-      IF_DEEP_DBG printf ("\t\t\t\t. Cur pos %ld\n", ftell(fd));
+      g_seekable_seek (G_SEEKABLE (output),
+                       0, G_SEEK_END,
+                       NULL, NULL /*FIXME: error*/);
+      IF_DEEP_DBG printf ("\t\t\t\t. Cur pos %ld\n", g_seekable_tell (G_SEEKABLE (output)));
 
       g_object_unref (mbuffer);
     }
@@ -1558,14 +1606,14 @@ write_pixel_data (FILE         *fd,
 }
 
 static void
-save_data (FILE      *fd,
-           GimpImage *image)
+save_data (GOutputStream  *output,
+           GimpImage      *image)
 {
   GList  *iter;
   gint    ChanCount;
   gint    i, j;
   gint32  imageHeight;                   /* Height of image */
-  glong   offset;                         /* offset in file of rle lengths */
+  goffset offset;                        /* offset in file of rle lengths */
   gint    chan;
 
   IFDBG printf (" Function: save_data\n");
@@ -1577,18 +1625,18 @@ save_data (FILE      *fd,
 
   imageHeight = gimp_image_get_height (image);
 
-  write_gint16 (fd, 1, "RLE compression");
+  write_gint16 (output, 1, "RLE compression");
 
   /* All line lengths go before the rle pixel data */
 
-  offset = ftell(fd); /* Offset in file of line lengths */
+  offset = g_seekable_tell (G_SEEKABLE (output)); /* Offset in file of line lengths */
 
   for (i = 0; i < ChanCount; i++)
     for (j = 0; j < imageHeight; j++)
-      write_gint16 (fd, 0, "junk line lengths");
+      write_gint16 (output, 0, "junk line lengths");
 
   IFDBG printf ("\t\tWriting compressed image data\n");
-  write_pixel_data (fd, GIMP_DRAWABLE (PSDImageData.merged_layer),
+  write_pixel_data (output, GIMP_DRAWABLE (PSDImageData.merged_layer),
                     NULL, offset, FALSE);
 
   chan = nChansLayer (PSDImageData.baseType,
@@ -1598,7 +1646,7 @@ save_data (FILE      *fd,
     {
       IFDBG printf ("\t\tWriting compressed channel data for channel %d\n",
                     i);
-      write_pixel_data (fd, iter->data, NULL,
+      write_pixel_data (output, iter->data, NULL,
                         offset + 2*imageHeight*chan, FALSE); //check how imgs are channels here
       chan++;
     }
@@ -1706,10 +1754,10 @@ save_image (GFile      *file,
             GimpImage  *image,
             GError    **error)
 {
-  gchar      *filename;
-  FILE       *fd;
-  GeglBuffer *buffer;
-  GList      *iter;
+  GOutputStream  *output;
+  GeglBuffer     *buffer;
+  GList          *iter;
+  GError         *local_error = NULL;
 
   IFDBG printf (" Function: save_image\n");
 
@@ -1754,15 +1802,23 @@ save_image (GFile      *file,
         }
     }
 
-  filename = g_file_get_path (file);
-  fd = g_fopen (filename, "wb");
-  g_free (filename);
+  output = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE,
+                                            G_FILE_CREATE_NONE, NULL,
+                                            &local_error));
 
-  if (! fd)
+  if (! output)
     {
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
-                   _("Could not open '%s' for writing: %s"),
-                   gimp_file_get_utf8_name (file), g_strerror (errno));
+      if (! local_error)
+        g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
+                     _("Could not open '%s' for writing: %s"),
+                       gimp_file_get_utf8_name (file), g_strerror (errno));
+      else
+        {
+          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                       _("Could not open '%s' for reading: %s"),
+                       gimp_file_get_utf8_name (file), local_error->message);
+          g_error_free (local_error);
+        }
       clear_image_data ();
       return FALSE;
     }
@@ -1770,20 +1826,20 @@ save_image (GFile      *file,
   IFDBG g_print ("\tFile '%s' has been opened\n",
                  gimp_file_get_utf8_name (file));
 
-  save_header (fd, image);
-  save_color_mode_data (fd, image);
-  save_resources (fd, image);
+  save_header (output, image);
+  save_color_mode_data (output, image);
+  save_resources (output, image);
 
   /* PSD format does not support layers in indexed images */
 
   if (PSDImageData.baseType == GIMP_INDEXED)
-    write_gint32 (fd, 0, "layers info section length");
+    write_gint32 (output, 0, "layers info section length");
   else
-    save_layer_and_mask (fd, image);
+    save_layer_and_mask (output, image);
 
   /* If this is an indexed image, write now channel and layer info */
 
-  save_data (fd, image);
+  save_data (output, image);
 
   /* Delete merged image now */
 
@@ -1793,7 +1849,7 @@ save_image (GFile      *file,
 
   IFDBG printf ("----- Closing PSD file, done -----\n\n");
 
-  fclose (fd);
+  g_object_unref (output);
 
   gimp_progress_update (1.0);
 
diff --git a/plug-ins/file-psd/psd-thumb-load.c b/plug-ins/file-psd/psd-thumb-load.c
index 041f106e28..b6cc262dd0 100644
--- a/plug-ins/file-psd/psd-thumb-load.c
+++ b/plug-ins/file-psd/psd-thumb-load.c
@@ -34,25 +34,26 @@
 #include "libgimp/stdplugins-intl.h"
 
 /*  Local function prototypes  */
-static gint    read_header_block          (PSDimage     *img_a,
-                                           FILE         *f,
-                                           GError      **error);
+static gint    read_header_block          (PSDimage      *img_a,
+                                           GInputStream  *input,
+                                           GError       **error);
 
-static gint    read_color_mode_block      (PSDimage     *img_a,
-                                           FILE         *f,
-                                           GError      **error);
+static gint    read_color_mode_block      (PSDimage      *img_a,
+                                           GInputStream  *input,
+                                           GError       **error);
 
-static gint    read_image_resource_block  (PSDimage     *img_a,
-                                           FILE         *f,
-                                           GError      **error);
+static gint    read_image_resource_block  (PSDimage      *img_a,
+                                           GInputStream  *input,
+                                           GError       **error);
 
-static GimpImage * create_gimp_image      (PSDimage     *img_a,
-                                           GFile        *file);
+static GimpImage * create_gimp_image      (PSDimage      *img_a,
+                                           GFile         *file);
 
-static gint    add_image_resources        (GimpImage    *image,
-                                           PSDimage     *img_a,
-                                           FILE         *f,
-                                           GError      **error);
+static gint    add_image_resources        (GimpImage     *image,
+                                           PSDimage      *img_a,
+                                           GFile         *file,
+                                           GInputStream  *input,
+                                           GError       **error);
 
 /* Main file load function */
 GimpImage *
@@ -61,52 +62,51 @@ load_thumbnail_image (GFile   *file,
                       gint    *height,
                       GError **load_error)
 {
-  gchar     *filename;
-  FILE      *f;
-  GStatBuf   st;
-  PSDimage   img_a;
-  GimpImage *image = NULL;
-  GError    *error = NULL;
-
-  filename = g_file_get_path (file);
+  GInputStream  *input;
+  PSDimage       img_a;
+  GimpImage     *image = NULL;
+  GError        *error = NULL;
 
   /* ----- Open PSD file ----- */
-  if (g_stat (filename, &st) == -1)
-    {
-      g_free (filename);
-      return NULL;
-    }
 
   gimp_progress_init_printf (_("Opening thumbnail for '%s'"),
                              gimp_file_get_utf8_name (file));
 
   IFDBG(1) g_debug ("Open file %s", gimp_file_get_utf8_name (file));
-  f = g_fopen (filename, "rb");
-  g_free (filename);
 
-  if (! f)
+  input = G_INPUT_STREAM (g_file_read (file, NULL, &error));
+  if (! input)
     {
-      g_set_error (load_error, G_FILE_ERROR, g_file_error_from_errno (errno),
-                   _("Could not open '%s' for reading: %s"),
-                   gimp_file_get_utf8_name (file), g_strerror (errno));
+      if (! error)
+        g_set_error (load_error, G_FILE_ERROR, g_file_error_from_errno (errno),
+                     _("Could not open '%s' for reading: %s"),
+                     gimp_file_get_utf8_name (file), g_strerror (errno));
+      else
+        {
+          g_set_error (load_error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                       _("Could not open '%s' for reading: %s"),
+                       gimp_file_get_utf8_name (file), error->message);
+          g_error_free (error);
+        }
+
       return NULL;
     }
 
   /* ----- Read the PSD file Header block ----- */
   IFDBG(2) g_debug ("Read header block");
-  if (read_header_block (&img_a, f, &error) < 0)
+  if (read_header_block (&img_a, input, &error) < 0)
     goto load_error;
   gimp_progress_update (0.2);
 
   /* ----- Read the PSD file Color Mode block ----- */
   IFDBG(2) g_debug ("Read color mode block");
-  if (read_color_mode_block (&img_a, f, &error) < 0)
+  if (read_color_mode_block (&img_a, input, &error) < 0)
     goto load_error;
   gimp_progress_update (0.4);
 
   /* ----- Read the PSD file Image Resource block ----- */
   IFDBG(2) g_debug ("Read image resource block");
-  if (read_image_resource_block (&img_a, f, &error) < 0)
+  if (read_image_resource_block (&img_a, input, &error) < 0)
     goto load_error;
   gimp_progress_update (0.6);
 
@@ -118,13 +118,13 @@ load_thumbnail_image (GFile   *file,
 
   /* ----- Add image resources ----- */
   IFDBG(2) g_debug ("Add image resources");
-  if (add_image_resources (image, &img_a, f, &error) < 1)
+  if (add_image_resources (image, &img_a, file, input, &error) < 1)
     goto load_error;
   gimp_progress_update (1.0);
 
   gimp_image_clean_all (image);
   gimp_image_undo_enable (image);
-  fclose (f);
+  g_object_unref (input);
 
   *width = img_a.columns;
   *height = img_a.rows;
@@ -144,8 +144,7 @@ load_thumbnail_image (GFile   *file,
     gimp_image_delete (image);
 
   /* Close file if Open */
-  if (! (f == NULL))
-    fclose (f);
+  g_object_unref (input);
 
   return NULL;
 }
@@ -154,24 +153,24 @@ load_thumbnail_image (GFile   *file,
 /* Local functions */
 
 static gint
-read_header_block (PSDimage  *img_a,
-                   FILE      *f,
-                   GError   **error)
+read_header_block (PSDimage      *img_a,
+                   GInputStream  *input,
+                   GError       **error)
 {
   guint16  version;
   gchar    sig[4];
   gchar    buf[6];
 
-  if (fread (sig, 4, 1, f) < 1
-      || fread (&version, 2, 1, f) < 1
-      || fread (buf, 6, 1, f) < 1
-      || fread (&img_a->channels, 2, 1, f) < 1
-      || fread (&img_a->rows, 4, 1, f) < 1
-      || fread (&img_a->columns, 4, 1, f) < 1
-      || fread (&img_a->bps, 2, 1, f) < 1
-      || fread (&img_a->color_mode, 2, 1, f) < 1)
+  if (psd_read (input, sig,                4, error) < 4 ||
+      psd_read (input, &version,           2, error) < 2 ||
+      psd_read (input, buf,                6, error) < 6 ||
+      psd_read (input, &img_a->channels,   2, error) < 2 ||
+      psd_read (input, &img_a->rows,       4, error) < 4 ||
+      psd_read (input, &img_a->columns,    4, error) < 4 ||
+      psd_read (input, &img_a->bps,        2, error) < 2 ||
+      psd_read (input, &img_a->color_mode, 2, error) < 2)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   version = GUINT16_FROM_BE (version);
@@ -206,27 +205,27 @@ read_header_block (PSDimage  *img_a,
 }
 
 static gint
-read_color_mode_block (PSDimage  *img_a,
-                       FILE      *f,
-                       GError   **error)
+read_color_mode_block (PSDimage      *img_a,
+                       GInputStream  *input,
+                       GError       **error)
 {
-  guint32 block_len;
-  guint32 block_start;
-  guint32 block_end;
+  guint64 block_len;
+  guint64 block_start;
+  guint64 block_end;
 
-  if (fread (&block_len, 4, 1, f) < 1)
+  if (psd_read (input, &block_len, 4, error) < 4)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   block_len = GUINT32_FROM_BE (block_len);
 
-  block_start = ftell (f);
+  block_start = g_seekable_tell (G_SEEKABLE (input));
   block_end = block_start + block_len;
 
-  if (fseek (f, block_end, SEEK_SET) < 0)
+  if (! psd_seek (input, block_end, G_SEEK_SET, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
@@ -234,28 +233,28 @@ read_color_mode_block (PSDimage  *img_a,
 }
 
 static gint
-read_image_resource_block (PSDimage  *img_a,
-                           FILE      *f,
-                           GError   **error)
+read_image_resource_block (PSDimage      *img_a,
+                           GInputStream  *input,
+                           GError       **error)
 {
-  guint32 block_len;
-  guint32 block_end;
+  guint64 block_len;
+  guint64 block_end;
 
-  if (fread (&block_len, 4, 1, f) < 1)
+  if (psd_read (input, &block_len, 4, error) < 4)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
   img_a->image_res_len = GUINT32_FROM_BE (block_len);
 
   IFDBG(1) g_debug ("Image resource block size = %d", (int)img_a->image_res_len);
 
-  img_a->image_res_start = ftell (f);
+  img_a->image_res_start = g_seekable_tell (G_SEEKABLE (input));
   block_end = img_a->image_res_start + img_a->image_res_len;
 
-  if (fseek (f, block_end, SEEK_SET) < 0)
+  if (! psd_seek (input, block_end, G_SEEK_SET, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
@@ -281,30 +280,31 @@ create_gimp_image (PSDimage *img_a,
 }
 
 static gint
-add_image_resources (GimpImage *image,
-                     PSDimage  *img_a,
-                     FILE      *f,
-                     GError   **error)
+add_image_resources (GimpImage     *image,
+                     PSDimage      *img_a,
+                     GFile         *file,
+                     GInputStream  *input,
+                     GError       **error)
 {
   PSDimageres   res_a;
   gint          status;
 
-  if (fseek (f, img_a->image_res_start, SEEK_SET) < 0)
+  if (! psd_seek (input, img_a->image_res_start, G_SEEK_SET, error))
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return -1;
     }
 
-  while (ftell (f) < img_a->image_res_start + img_a->image_res_len)
+  while (g_seekable_tell (G_SEEKABLE (input)) < img_a->image_res_start + img_a->image_res_len)
     {
-      if (get_image_resource_header (&res_a, f, error) < 0)
+      if (get_image_resource_header (&res_a, input, error) < 0)
         return -1;
 
       if (res_a.data_start + res_a.data_len >
           img_a->image_res_start + img_a->image_res_len)
         return 0;
 
-      status = load_thumbnail_resource (&res_a, image, f, error);
+      status = load_thumbnail_resource (&res_a, image, file, input, error);
       /* Error */
       if (status < 0)
         return -1;
diff --git a/plug-ins/file-psd/psd-util.c b/plug-ins/file-psd/psd-util.c
index a292aac065..8068d13e39 100644
--- a/plug-ins/file-psd/psd-util.c
+++ b/plug-ins/file-psd/psd-util.c
@@ -169,30 +169,52 @@ static const LayerModeMapping layer_mode_map[] =
 
 /* Utility function */
 void
-psd_set_error (gboolean   file_eof,
-               gint       err_no,
-               GError   **error)
+psd_set_error (GError  **error)
 {
-  if (file_eof)
-    {
-      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
-                   "%s", _("Unexpected end of file"));
-    }
-  else
+  if (! error)
+    g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                 _("Error reading data. Most likely unexpected end of file."));
+
+  return;
+}
+
+gint
+psd_read (GInputStream  *input,
+          gconstpointer  data,
+          gint           count,
+          GError       **error)
+{
+  gsize bytes_read = 0;
+
+  /* we allow for 'data == NULL && count == 0', which g_input_stream_read_all()
+   * rejects.
+   */
+  if (count > 0)
     {
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (err_no),
-                   "%s", g_strerror (err_no));
+      g_input_stream_read_all (input, (void *) data, count,
+                               &bytes_read, NULL, error);
     }
 
-  return;
+  return bytes_read;
+}
+
+gboolean
+psd_seek (GInputStream  *input,
+          goffset        offset,
+          GSeekType      type,
+          GError       **error)
+{
+  return g_seekable_seek (G_SEEKABLE (input),
+                          offset, type,
+                          NULL, error);
 }
 
 gchar *
-fread_pascal_string (gint32   *bytes_read,
-                     gint32   *bytes_written,
-                     guint16   mod_len,
-                     FILE     *f,
-                     GError  **error)
+fread_pascal_string (gint32        *bytes_read,
+                     gint32        *bytes_written,
+                     guint16        mod_len,
+                     GInputStream  *input,
+                     GError       **error)
 {
   /*
    * Reads a pascal string from the file padded to a multiple of mod_len
@@ -207,9 +229,9 @@ fread_pascal_string (gint32   *bytes_read,
   *bytes_read = 0;
   *bytes_written = -1;
 
-  if (fread (&len, 1, 1, f) < 1)
+  if (psd_read (input, &len, 1, error) < 1)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return NULL;
     }
   (*bytes_read)++;
@@ -217,9 +239,9 @@ fread_pascal_string (gint32   *bytes_read,
 
   if (len == 0)
     {
-      if (fseek (f, mod_len - 1, SEEK_CUR) < 0)
+      if (! psd_seek (input, mod_len - 1, G_SEEK_CUR, error))
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return NULL;
         }
       *bytes_read += (mod_len - 1);
@@ -228,9 +250,9 @@ fread_pascal_string (gint32   *bytes_read,
     }
 
   str = g_malloc (len);
-  if (fread (str, len, 1, f) < 1)
+  if (psd_read (input, str, len, error) < len)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       g_free (str);
       return NULL;
     }
@@ -241,9 +263,9 @@ fread_pascal_string (gint32   *bytes_read,
       padded_len = len + 1;
       while (padded_len % mod_len != 0)
         {
-          if (fseek (f, 1, SEEK_CUR) < 0)
+          if (! psd_seek (input, 1, G_SEEK_CUR, error))
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               g_free (str);
               return NULL;
             }
@@ -263,30 +285,34 @@ fread_pascal_string (gint32   *bytes_read,
 }
 
 gint32
-fwrite_pascal_string (const gchar  *src,
-                      guint16       mod_len,
-                      FILE         *f,
-                      GError      **error)
+fwrite_pascal_string (const gchar    *src,
+                      guint16         mod_len,
+                      GOutputStream  *output,
+                      GError        **error)
 {
   /*
    *  Converts utf-8 string to current locale and writes as pascal
    *  string with padding to a multiple of mod_len.
    */
 
-  gchar  *str;
-  gchar  *pascal_str;
-  gchar   null_str = 0x0;
-  guchar  pascal_len;
-  gint32  bytes_written = 0;
-  gsize   len;
+  gchar        *str;
+  gchar        *pascal_str;
+  const gchar   null_str = 0x0;
+  guchar        pascal_len;
+  gsize         bytes_written = 0;
+  gsize         len;
+
+  g_debug ("fwrite_pascal_string %s!", src);
 
   if (src == NULL)
     {
        /* Write null string as two null bytes (0x0) */
-      if (fwrite (&null_str, 1, 1, f) < 1
-          || fwrite (&null_str, 1, 1, f) < 1)
+      if (! g_output_stream_write_all (output, &null_str, 1,
+                                       &bytes_written, NULL, error) ||
+          ! g_output_stream_write_all (output, &null_str, 1,
+                                       &bytes_written, NULL, error))
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return -1;
         }
       bytes_written += 2;
@@ -300,16 +326,19 @@ fwrite_pascal_string (const gchar  *src,
         pascal_len = len;
       pascal_str = g_strndup (str, pascal_len);
       g_free (str);
-      if (fwrite (&pascal_len, 1, 1, f) < 1
-          || fwrite (pascal_str, pascal_len, 1, f) < 1)
+
+      if (! g_output_stream_write_all (output, &pascal_len, 1,
+                                       &bytes_written, NULL, error) ||
+          ! g_output_stream_write_all (output, pascal_str, pascal_len,
+                                       &bytes_written, NULL, error))
         {
-          psd_set_error (feof (f), errno, error);
           g_free (pascal_str);
           return -1;
         }
       bytes_written++;
       bytes_written += pascal_len;
-      IFDBG(2) g_debug ("Pascal string: %s, bytes_written: %d",
+
+      IFDBG(2) g_debug ("Pascal string: %s, bytes_written: %" G_GSIZE_FORMAT,
                         pascal_str, bytes_written);
       g_free (pascal_str);
     }
@@ -319,9 +348,10 @@ fwrite_pascal_string (const gchar  *src,
     {
       while (bytes_written % mod_len != 0)
         {
-          if (fwrite (&null_str, 1, 1, f) < 1)
+
+          if (! g_output_stream_write_all (output, &null_str, 1,
+                                           &bytes_written, NULL, error))
             {
-              psd_set_error (feof (f), errno, error);
               return -1;
             }
           bytes_written++;
@@ -332,11 +362,11 @@ fwrite_pascal_string (const gchar  *src,
 }
 
 gchar *
-fread_unicode_string (gint32   *bytes_read,
-                      gint32   *bytes_written,
-                      guint16   mod_len,
-                      FILE     *f,
-                      GError  **error)
+fread_unicode_string (gint32        *bytes_read,
+                      gint32        *bytes_written,
+                      guint16        mod_len,
+                      GInputStream  *input,
+                      GError       **error)
 {
   /*
    * Reads a utf-16 string from the file padded to a multiple of mod_len
@@ -353,9 +383,9 @@ fread_unicode_string (gint32   *bytes_read,
   *bytes_read = 0;
   *bytes_written = -1;
 
-  if (fread (&len, 4, 1, f) < 1)
+  if (psd_read (input, &len, 4, error) < 4)
     {
-      psd_set_error (feof (f), errno, error);
+      psd_set_error (error);
       return NULL;
     }
   *bytes_read += 4;
@@ -364,9 +394,9 @@ fread_unicode_string (gint32   *bytes_read,
 
   if (len == 0)
     {
-      if (fseek (f, mod_len - 1, SEEK_CUR) < 0)
+      if (! psd_seek (input, mod_len - 1, G_SEEK_CUR, error))
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           return NULL;
         }
       *bytes_read += (mod_len - 1);
@@ -377,9 +407,9 @@ fread_unicode_string (gint32   *bytes_read,
   utf16_str = g_malloc (len * 2);
   for (i = 0; i < len; ++i)
     {
-      if (fread (&utf16_str[i], 2, 1, f) < 1)
+      if (psd_read (input, &utf16_str[i], 2, error) < 2)
         {
-          psd_set_error (feof (f), errno, error);
+          psd_set_error (error);
           g_free (utf16_str);
           return NULL;
         }
@@ -392,9 +422,9 @@ fread_unicode_string (gint32   *bytes_read,
       padded_len = len + 1;
       while (padded_len % mod_len != 0)
         {
-          if (fseek (f, 1, SEEK_CUR) < 0)
+          if (! psd_seek (input, 1, G_SEEK_CUR, error))
             {
-              psd_set_error (feof (f), errno, error);
+              psd_set_error (error);
               g_free (utf16_str);
               return NULL;
             }
@@ -414,10 +444,10 @@ fread_unicode_string (gint32   *bytes_read,
 }
 
 gint32
-fwrite_unicode_string (const gchar  *src,
-                       guint16       mod_len,
-                       FILE         *f,
-                       GError      **error)
+fwrite_unicode_string (const gchar    *src,
+                       guint16         mod_len,
+                       GOutputStream  *output,
+                       GError        **error)
 {
   /*
    *  Converts utf-8 string to utf-16 and writes 4 byte length
@@ -427,16 +457,16 @@ fwrite_unicode_string (const gchar  *src,
   gunichar2 *utf16_str;
   gchar      null_str = 0x0;
   gint32     utf16_len = 0;
-  gint32     bytes_written = 0;
+  gsize      bytes_written = 0;
   gint       i;
   glong      len;
 
   if (src == NULL)
     {
        /* Write null string as four byte 0 int32 */
-      if (fwrite (&utf16_len, 4, 1, f) < 1)
+      if (! g_output_stream_write_all (output, &utf16_len, 4,
+                                       &bytes_written, NULL, error))
         {
-          psd_set_error (feof (f), errno, error);
           return -1;
         }
       bytes_written += 4;
@@ -450,14 +480,15 @@ fwrite_unicode_string (const gchar  *src,
           utf16_str[i] = GINT16_TO_BE (utf16_str[i]);
       utf16_len = GINT32_TO_BE (utf16_len);
 
-      if (fwrite (&utf16_len, 4, 1, f) < 1
-          || fwrite (utf16_str, 2, utf16_len + 1, f) < utf16_len + 1)
+      if (! g_output_stream_write_all (output, &utf16_len, 4,
+                                       &bytes_written, NULL, error) ||
+          ! g_output_stream_write_all (output, &utf16_str, 2 * (utf16_len + 1),
+                                       &bytes_written, NULL, error))
         {
-          psd_set_error (feof (f), errno, error);
           return -1;
         }
       bytes_written += (4 + 2 * utf16_len + 2);
-      IFDBG(2) g_debug ("Unicode string: %s, bytes_written: %d",
+      IFDBG(2) g_debug ("Unicode string: %s, bytes_written: %" G_GSIZE_FORMAT,
                         src, bytes_written);
     }
 
@@ -466,9 +497,9 @@ fwrite_unicode_string (const gchar  *src,
     {
       while (bytes_written % mod_len != 0)
         {
-          if (fwrite (&null_str, 1, 1, f) < 1)
+          if (! g_output_stream_write_all (output, &null_str, 1,
+                                           &bytes_written, NULL, error))
             {
-              psd_set_error (feof (f), errno, error);
               return -1;
             }
           bytes_written++;
diff --git a/plug-ins/file-psd/psd-util.h b/plug-ins/file-psd/psd-util.h
index e82cbd0de5..498622a508 100644
--- a/plug-ins/file-psd/psd-util.h
+++ b/plug-ins/file-psd/psd-util.h
@@ -21,11 +21,21 @@
 #ifndef __PSD_UTIL_H__
 #define __PSD_UTIL_H__
 
+#define PSD_TELL(f)     g_seekable_tell (G_SEEKABLE (input))
+
 /*
  *  Set file read error
  */
-void                    psd_set_error          (gboolean             file_eof,
-                                                gint                 err_no,
+void                    psd_set_error          (GError             **error);
+
+gint                    psd_read               (GInputStream        *input,
+                                                gconstpointer        data,
+                                                gint                 count,
+                                                GError             **error);
+
+gboolean                psd_seek               (GInputStream        *input,
+                                                goffset              offset,
+                                                GSeekType            type,
                                                 GError             **error);
 
 /*
@@ -35,7 +45,7 @@ void                    psd_set_error          (gboolean             file_eof,
 gchar                 * fread_pascal_string    (gint32              *bytes_read,
                                                 gint32              *bytes_written,
                                                 guint16              mod_len,
-                                                FILE                *f,
+                                                GInputStream        *input,
                                                 GError             **error);
 
 /*
@@ -44,7 +54,7 @@ gchar                 * fread_pascal_string    (gint32              *bytes_read,
  */
 gint32                  fwrite_pascal_string   (const gchar         *src,
                                                 guint16              mod_len,
-                                                FILE                *f,
+                                                GOutputStream       *output,
                                                 GError             **error);
 
 /*
@@ -54,7 +64,7 @@ gint32                  fwrite_pascal_string   (const gchar         *src,
 gchar                 * fread_unicode_string   (gint32              *bytes_read,
                                                 gint32              *bytes_written,
                                                 guint16              mod_len,
-                                                FILE                *f,
+                                                GInputStream        *input,
                                                 GError             **error);
 
 /*
@@ -63,7 +73,7 @@ gchar                 * fread_unicode_string   (gint32              *bytes_read,
  */
 gint32                  fwrite_unicode_string  (const gchar         *src,
                                                 guint16              mod_len,
-                                                FILE                *f,
+                                                GOutputStream       *output,
                                                 GError             **error);
 
 gint                    decode_packbits        (const gchar         *src,
diff --git a/plug-ins/file-psd/psd.h b/plug-ins/file-psd/psd.h
index 61f06a1ba5..f14ae4d526 100644
--- a/plug-ins/file-psd/psd.h
+++ b/plug-ins/file-psd/psd.h
@@ -590,9 +590,9 @@ typedef struct
   guchar                clipping;               /* Clipping */
   guchar                flags;                  /* Layer flags */
   guchar                filler;                 /* Filler */
-  guint32               extra_len;              /* Extra data length */
+  guint64               extra_len;              /* Extra data length */
   gchar                *name;                   /* Layer name */
-  guint32               mask_len;               /* Layer mask data length */
+  guint64               mask_len;               /* Layer mask data length */
   LayerMask             layer_mask;             /* Layer mask data */
   LayerMaskExtra        layer_mask_extra;       /* Layer mask extra data */
   LayerFlags            layer_flags;            /* Layer flags */
@@ -629,8 +629,8 @@ typedef struct
   gchar         type[4];                /* Image resource type */
   gint16        id;                     /* Image resource ID */
   gchar         name[256];              /* Image resource name (pascal string) */
-  guint32       data_start;             /* Image resource data start */
-  guint32       data_len;               /* Image resource data length */
+  guint64       data_start;             /* Image resource data start */
+  guint64       data_len;               /* Image resource data length */
 } PSDimageres;
 
 /* PSD Layer Resource data structure */
@@ -638,8 +638,8 @@ typedef struct
 {
   gchar         sig[4];                 /* Layer resource signature */
   gchar         key[4];                 /* Layer resource key */
-  guint32       data_start;             /* Layer resource data start */
-  guint32       data_len;               /* Layer resource data length */
+  guint64       data_start;             /* Layer resource data start */
+  guint64       data_len;               /* Layer resource data length */
 } PSDlayerres;
 
 /* PSD File data structures */
@@ -658,15 +658,15 @@ typedef struct
   guchar               *color_map;              /* Color map data */
   guint32               color_map_len;          /* Color map data length */
   guint32               color_map_entries;      /* Color map number of entries */
-  guint32               image_res_start;        /* Image resource block start address */
-  guint32               image_res_len;          /* Image resource block length */
-  guint32               mask_layer_start;       /* Mask & layer block start address */
-  guint32               mask_layer_len;         /* Mask & layer block length */
+  guint64               image_res_start;        /* Image resource block start address */
+  guint64               image_res_len;          /* Image resource block length */
+  guint64               mask_layer_start;       /* Mask & layer block start address */
+  guint64               mask_layer_len;         /* Mask & layer block length */
   gint16                num_layers;             /* Number of layers */
-  guint32               layer_data_start;       /* Layer pixel data start */
-  guint32               layer_data_len;         /* Layer pixel data length */
-  guint32               merged_image_start;     /* Merged image pixel data block start address */
-  guint32               merged_image_len;       /* Merged image pixel data block length */
+  guint64               layer_data_start;       /* Layer pixel data start */
+  guint64               layer_data_len;         /* Layer pixel data length */
+  guint64               merged_image_start;     /* Merged image pixel data block start address */
+  guint64               merged_image_len;       /* Merged image pixel data block length */
   gboolean              no_icc;                 /* Do not use ICC profile */
   guint16               layer_state;            /* Active layer index counting from bottom up */
   GList                *layer_selection;        /* Selected layer IDs (GIMP layer tattoos) */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]