1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2006-2007 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: Alexander Larsson <alexl@redhat.com>
27 #include "gresource.h"
28 #include "gresourcefile.h"
29 #include "gfileattribute.h"
30 #include <gfileattribute-priv.h>
31 #include <gfileinfo-priv.h>
33 #include "gseekable.h"
34 #include "gfileinputstream.h"
35 #include "gfileinfo.h"
36 #include "gfileenumerator.h"
37 #include "gcontenttype.h"
39 #include <glib/gstdio.h>
44 GObject parent_instance
;
49 struct _GResourceFileEnumerator
51 GFileEnumerator parent
;
53 GFileAttributeMatcher
*matcher
;
56 GFileQueryInfoFlags flags
;
62 struct _GResourceFileEnumeratorClass
64 GFileEnumeratorClass parent_class
;
67 typedef struct _GResourceFileEnumerator GResourceFileEnumerator
;
68 typedef struct _GResourceFileEnumeratorClass GResourceFileEnumeratorClass
;
70 static void g_resource_file_file_iface_init (GFileIface
*iface
);
72 static GFileAttributeInfoList
*resource_writable_attributes
= NULL
;
73 static GFileAttributeInfoList
*resource_writable_namespaces
= NULL
;
75 #define G_TYPE_RESOURCE_FILE_ENUMERATOR (_g_resource_file_enumerator_get_type ())
76 #define G_RESOURCE_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumerator))
77 #define G_RESOURCE_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumeratorClass))
78 #define G_IS_RESOURCE_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR))
79 #define G_IS_RESOURCE_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_RESOURCE_FILE_ENUMERATOR))
80 #define G_RESOURCE_FILE_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumeratorClass))
82 #define G_TYPE_RESOURCE_FILE_INPUT_STREAM (_g_resource_file_input_stream_get_type ())
83 #define G_RESOURCE_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStream))
84 #define G_RESOURCE_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStreamClass))
85 #define G_IS_RESOURCE_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM))
86 #define G_IS_RESOURCE_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_RESOURCE_FILE_INPUT_STREAM))
87 #define G_RESOURCE_FILE_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStreamClass))
89 typedef struct _GResourceFileInputStream GResourceFileInputStream
;
90 typedef struct _GResourceFileInputStreamClass GResourceFileInputStreamClass
;
92 #define g_resource_file_get_type _g_resource_file_get_type
93 G_DEFINE_TYPE_WITH_CODE (GResourceFile
, g_resource_file
, G_TYPE_OBJECT
,
94 G_IMPLEMENT_INTERFACE (G_TYPE_FILE
,
95 g_resource_file_file_iface_init
))
97 #define g_resource_file_enumerator_get_type _g_resource_file_enumerator_get_type
98 G_DEFINE_TYPE (GResourceFileEnumerator
, g_resource_file_enumerator
, G_TYPE_FILE_ENUMERATOR
);
100 static GFileEnumerator
*_g_resource_file_enumerator_new (GResourceFile
*file
,
101 const char *attributes
,
102 GFileQueryInfoFlags flags
,
103 GCancellable
*cancellable
,
107 static GType
_g_resource_file_input_stream_get_type (void) G_GNUC_CONST
;
109 static GFileInputStream
*_g_resource_file_input_stream_new (GInputStream
*stream
, GFile
*file
);
113 g_resource_file_finalize (GObject
*object
)
115 GResourceFile
*resource
;
117 resource
= G_RESOURCE_FILE (object
);
119 g_free (resource
->path
);
121 G_OBJECT_CLASS (g_resource_file_parent_class
)->finalize (object
);
125 g_resource_file_class_init (GResourceFileClass
*klass
)
127 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
129 gobject_class
->finalize
= g_resource_file_finalize
;
131 resource_writable_attributes
= g_file_attribute_info_list_new ();
132 resource_writable_namespaces
= g_file_attribute_info_list_new ();
136 g_resource_file_init (GResourceFile
*resource
)
141 canonicalize_filename (const char *filename
)
143 char *canon
, *start
, *p
, *q
;
145 /* Skip multiple inital slashes */
146 while (filename
[0] == '/' && filename
[1] == '/')
149 if (*filename
!= '/')
150 canon
= g_strconcat ("/", filename
, NULL
);
152 canon
= g_strdup (filename
);
159 if (p
[0] == '.' && (p
[1] == 0 || p
[1] == '/'))
161 memmove (p
, p
+1, strlen (p
+1)+1);
163 else if (p
[0] == '.' && p
[1] == '.' && (p
[2] == 0 || p
[2] == '/'))
166 /* Skip previous separator */
170 while (p
> start
&& *p
!= '/')
174 memmove (p
, q
, strlen (q
)+1);
178 /* Skip until next separator */
179 while (*p
!= 0 && *p
!= '/')
184 /* Canonicalize one separator */
189 /* Remove additional separators */
191 while (*q
&& *q
== '/')
195 memmove (p
, q
, strlen (q
)+1);
198 /* Remove trailing slashes */
199 if (p
> start
&& *(p
-1) == '/')
206 g_resource_file_new_for_path (const char *path
)
208 GResourceFile
*resource
= g_object_new (G_TYPE_RESOURCE_FILE
, NULL
);
210 resource
->path
= canonicalize_filename (path
);
212 return G_FILE (resource
);
216 _g_resource_file_new (const char *uri
)
221 path
= g_uri_unescape_string (uri
+ strlen ("resource:"), NULL
);
222 resource
= g_resource_file_new_for_path (path
);
225 return G_FILE (resource
);
229 g_resource_file_is_native (GFile
*file
)
235 g_resource_file_has_uri_scheme (GFile
*file
,
236 const char *uri_scheme
)
238 return g_ascii_strcasecmp (uri_scheme
, "resource") == 0;
242 g_resource_file_get_uri_scheme (GFile
*file
)
244 return g_strdup ("resource");
248 g_resource_file_get_basename (GFile
*file
)
252 base
= strrchr (G_RESOURCE_FILE (file
)->path
, '/');
253 return g_strdup (base
+ 1);
257 g_resource_file_get_path (GFile
*file
)
263 g_resource_file_get_uri (GFile
*file
)
266 escaped
= g_uri_escape_string (G_RESOURCE_FILE (file
)->path
, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH
, FALSE
);
267 res
= g_strconcat ("resource://", escaped
, NULL
);
273 g_resource_file_get_parse_name (GFile
*file
)
275 return g_resource_file_get_uri (file
);
279 g_resource_file_get_parent (GFile
*file
)
281 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
282 GResourceFile
*parent
;
285 end
= strrchr (resource
->path
, '/');
287 if (end
== G_RESOURCE_FILE (file
)->path
)
290 parent
= g_object_new (G_TYPE_RESOURCE_FILE
, NULL
);
291 parent
->path
= g_strndup (resource
->path
,
292 end
- resource
->path
);
294 return G_FILE (parent
);
298 g_resource_file_dup (GFile
*file
)
300 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
302 return g_resource_file_new_for_path (resource
->path
);
306 g_resource_file_hash (GFile
*file
)
308 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
310 return g_str_hash (resource
->path
);
314 g_resource_file_equal (GFile
*file1
,
317 GResourceFile
*resource1
= G_RESOURCE_FILE (file1
);
318 GResourceFile
*resource2
= G_RESOURCE_FILE (file2
);
320 return g_str_equal (resource1
->path
, resource2
->path
);
324 match_prefix (const char *path
,
329 prefix_len
= strlen (prefix
);
330 if (strncmp (path
, prefix
, prefix_len
) != 0)
333 /* Handle the case where prefix is the root, so that
334 * the IS_DIR_SEPRARATOR check below works */
335 if (prefix_len
> 0 &&
336 prefix
[prefix_len
-1] == '/')
339 return path
+ prefix_len
;
343 g_resource_file_prefix_matches (GFile
*parent
,
346 GResourceFile
*parent_resource
= G_RESOURCE_FILE (parent
);
347 GResourceFile
*descendant_resource
= G_RESOURCE_FILE (descendant
);
348 const char *remainder
;
350 remainder
= match_prefix (descendant_resource
->path
, parent_resource
->path
);
351 if (remainder
!= NULL
&& *remainder
== '/')
357 g_resource_file_get_relative_path (GFile
*parent
,
360 GResourceFile
*parent_resource
= G_RESOURCE_FILE (parent
);
361 GResourceFile
*descendant_resource
= G_RESOURCE_FILE (descendant
);
362 const char *remainder
;
364 remainder
= match_prefix (descendant_resource
->path
, parent_resource
->path
);
366 if (remainder
!= NULL
&& *remainder
== '/')
367 return g_strdup (remainder
+ 1);
372 g_resource_file_resolve_relative_path (GFile
*file
,
373 const char *relative_path
)
375 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
379 if (relative_path
[0] == '/')
380 return g_resource_file_new_for_path (relative_path
);
382 filename
= g_build_path ("/", resource
->path
, relative_path
, NULL
);
383 child
= g_resource_file_new_for_path (filename
);
389 static GFileEnumerator
*
390 g_resource_file_enumerate_children (GFile
*file
,
391 const char *attributes
,
392 GFileQueryInfoFlags flags
,
393 GCancellable
*cancellable
,
396 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
397 return _g_resource_file_enumerator_new (resource
,
403 g_resource_file_get_child_for_display_name (GFile
*file
,
404 const char *display_name
,
409 new_file
= g_file_get_child (file
, display_name
);
415 g_resource_file_query_info (GFile
*file
,
416 const char *attributes
,
417 GFileQueryInfoFlags flags
,
418 GCancellable
*cancellable
,
421 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
422 GError
*my_error
= NULL
;
424 GFileAttributeMatcher
*matcher
;
427 guint32 resource_flags
;
433 children
= g_resources_enumerate_children (resource
->path
, 0, NULL
);
434 if (children
!= NULL
)
436 g_strfreev (children
);
440 /* root is always there */
441 if (strcmp ("/", resource
->path
) == 0)
446 res
= g_resources_get_info (resource
->path
, 0, &size
, &resource_flags
, &my_error
);
449 if (g_error_matches (my_error
, G_RESOURCE_ERROR
, G_RESOURCE_ERROR_NOT_FOUND
))
451 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_NOT_FOUND
,
452 _("The resource at '%s' does not exist"),
456 g_set_error_literal (error
, G_IO_ERROR
, G_IO_ERROR_FAILED
,
458 g_clear_error (&my_error
);
463 matcher
= g_file_attribute_matcher_new (attributes
);
465 info
= g_file_info_new ();
466 base
= g_resource_file_get_basename (file
);
467 g_file_info_set_name (info
, base
);
468 g_file_info_set_display_name (info
, base
);
470 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_READ
, TRUE
);
471 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_WRITE
, FALSE
);
472 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_EXECUTE
, FALSE
);
473 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_RENAME
, FALSE
);
474 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE
, FALSE
);
475 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH
, FALSE
);
479 g_file_info_set_file_type (info
, G_FILE_TYPE_DIRECTORY
);
486 g_file_info_set_file_type (info
, G_FILE_TYPE_REGULAR
);
487 g_file_info_set_size (info
, size
);
489 if ((_g_file_attribute_matcher_matches_id (matcher
, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE
) ||
490 ((~resource_flags
& G_RESOURCE_FLAGS_COMPRESSED
) &&
491 _g_file_attribute_matcher_matches_id (matcher
, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE
))) &&
492 (bytes
= g_resources_lookup_data (resource
->path
, 0, NULL
)))
497 data
= g_bytes_get_data (bytes
, &data_size
);
498 content_type
= g_content_type_guess (base
, data
, data_size
, NULL
);
500 g_bytes_unref (bytes
);
507 _g_file_info_set_attribute_string_by_id (info
, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE
, content_type
);
508 _g_file_info_set_attribute_string_by_id (info
, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE
, content_type
);
510 g_free (content_type
);
515 g_file_attribute_matcher_unref (matcher
);
520 static GFileAttributeInfoList
*
521 g_resource_file_query_settable_attributes (GFile
*file
,
522 GCancellable
*cancellable
,
525 return g_file_attribute_info_list_ref (resource_writable_attributes
);
528 static GFileAttributeInfoList
*
529 g_resource_file_query_writable_namespaces (GFile
*file
,
530 GCancellable
*cancellable
,
533 return g_file_attribute_info_list_ref (resource_writable_namespaces
);
536 static GFileInputStream
*
537 g_resource_file_read (GFile
*file
,
538 GCancellable
*cancellable
,
541 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
542 GError
*my_error
= NULL
;
543 GInputStream
*stream
;
544 GFileInputStream
*res
;
546 stream
= g_resources_open_stream (resource
->path
, 0, &my_error
);
550 if (g_error_matches (my_error
, G_RESOURCE_ERROR
, G_RESOURCE_ERROR_NOT_FOUND
))
552 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_NOT_FOUND
,
553 _("The resource at '%s' does not exist"),
557 g_set_error_literal (error
, G_IO_ERROR
, G_IO_ERROR_FAILED
,
559 g_clear_error (&my_error
);
563 res
= _g_resource_file_input_stream_new (stream
, file
);
564 g_object_unref (stream
);
569 g_resource_file_file_iface_init (GFileIface
*iface
)
571 iface
->dup
= g_resource_file_dup
;
572 iface
->hash
= g_resource_file_hash
;
573 iface
->equal
= g_resource_file_equal
;
574 iface
->is_native
= g_resource_file_is_native
;
575 iface
->has_uri_scheme
= g_resource_file_has_uri_scheme
;
576 iface
->get_uri_scheme
= g_resource_file_get_uri_scheme
;
577 iface
->get_basename
= g_resource_file_get_basename
;
578 iface
->get_path
= g_resource_file_get_path
;
579 iface
->get_uri
= g_resource_file_get_uri
;
580 iface
->get_parse_name
= g_resource_file_get_parse_name
;
581 iface
->get_parent
= g_resource_file_get_parent
;
582 iface
->prefix_matches
= g_resource_file_prefix_matches
;
583 iface
->get_relative_path
= g_resource_file_get_relative_path
;
584 iface
->resolve_relative_path
= g_resource_file_resolve_relative_path
;
585 iface
->get_child_for_display_name
= g_resource_file_get_child_for_display_name
;
586 iface
->enumerate_children
= g_resource_file_enumerate_children
;
587 iface
->query_info
= g_resource_file_query_info
;
588 iface
->query_settable_attributes
= g_resource_file_query_settable_attributes
;
589 iface
->query_writable_namespaces
= g_resource_file_query_writable_namespaces
;
590 iface
->read_fn
= g_resource_file_read
;
592 iface
->supports_thread_contexts
= TRUE
;
595 static GFileInfo
*g_resource_file_enumerator_next_file (GFileEnumerator
*enumerator
,
596 GCancellable
*cancellable
,
598 static gboolean
g_resource_file_enumerator_close (GFileEnumerator
*enumerator
,
599 GCancellable
*cancellable
,
603 g_resource_file_enumerator_finalize (GObject
*object
)
605 GResourceFileEnumerator
*resource
;
607 resource
= G_RESOURCE_FILE_ENUMERATOR (object
);
609 g_strfreev (resource
->children
);
610 g_free (resource
->path
);
611 g_free (resource
->attributes
);
613 G_OBJECT_CLASS (g_resource_file_enumerator_parent_class
)->finalize (object
);
617 g_resource_file_enumerator_class_init (GResourceFileEnumeratorClass
*klass
)
619 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
620 GFileEnumeratorClass
*enumerator_class
= G_FILE_ENUMERATOR_CLASS (klass
);
622 gobject_class
->finalize
= g_resource_file_enumerator_finalize
;
624 enumerator_class
->next_file
= g_resource_file_enumerator_next_file
;
625 enumerator_class
->close_fn
= g_resource_file_enumerator_close
;
629 g_resource_file_enumerator_init (GResourceFileEnumerator
*resource
)
633 static GFileEnumerator
*
634 _g_resource_file_enumerator_new (GResourceFile
*file
,
635 const char *attributes
,
636 GFileQueryInfoFlags flags
,
637 GCancellable
*cancellable
,
640 GResourceFileEnumerator
*resource
;
644 children
= g_resources_enumerate_children (file
->path
, 0, NULL
);
645 if (children
== NULL
&&
646 strcmp ("/", file
->path
) != 0)
648 res
= g_resources_get_info (file
->path
, 0, NULL
, NULL
, NULL
);
650 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_NOT_DIRECTORY
,
651 _("The resource at '%s' is not a directory"),
654 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_NOT_FOUND
,
655 _("The resource at '%s' does not exist"),
660 resource
= g_object_new (G_TYPE_RESOURCE_FILE_ENUMERATOR
,
664 resource
->children
= children
;
665 resource
->path
= g_strdup (file
->path
);
666 resource
->attributes
= g_strdup (attributes
);
667 resource
->flags
= flags
;
669 return G_FILE_ENUMERATOR (resource
);
673 g_resource_file_enumerator_next_file (GFileEnumerator
*enumerator
,
674 GCancellable
*cancellable
,
677 GResourceFileEnumerator
*resource
= G_RESOURCE_FILE_ENUMERATOR (enumerator
);
682 if (resource
->children
== NULL
||
683 resource
->children
[resource
->index
] == NULL
)
686 path
= g_build_path ("/", resource
->path
, resource
->children
[resource
->index
++], NULL
);
687 file
= g_resource_file_new_for_path (path
);
690 info
= g_file_query_info (file
,
691 resource
->attributes
,
696 g_object_unref (file
);
702 g_resource_file_enumerator_close (GFileEnumerator
*enumerator
,
703 GCancellable
*cancellable
,
710 struct _GResourceFileInputStream
712 GFileInputStream parent_instance
;
713 GInputStream
*stream
;
717 struct _GResourceFileInputStreamClass
719 GFileInputStreamClass parent_class
;
722 #define g_resource_file_input_stream_get_type _g_resource_file_input_stream_get_type
723 G_DEFINE_TYPE (GResourceFileInputStream
, g_resource_file_input_stream
, G_TYPE_FILE_INPUT_STREAM
);
725 static gssize
g_resource_file_input_stream_read (GInputStream
*stream
,
728 GCancellable
*cancellable
,
730 static gssize
g_resource_file_input_stream_skip (GInputStream
*stream
,
732 GCancellable
*cancellable
,
734 static gboolean
g_resource_file_input_stream_close (GInputStream
*stream
,
735 GCancellable
*cancellable
,
737 static goffset
g_resource_file_input_stream_tell (GFileInputStream
*stream
);
738 static gboolean
g_resource_file_input_stream_can_seek (GFileInputStream
*stream
);
739 static gboolean
g_resource_file_input_stream_seek (GFileInputStream
*stream
,
742 GCancellable
*cancellable
,
744 static GFileInfo
*g_resource_file_input_stream_query_info (GFileInputStream
*stream
,
745 const char *attributes
,
746 GCancellable
*cancellable
,
750 g_resource_file_input_stream_finalize (GObject
*object
)
752 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (object
);
754 g_object_unref (file
->stream
);
755 g_object_unref (file
->file
);
756 G_OBJECT_CLASS (g_resource_file_input_stream_parent_class
)->finalize (object
);
760 g_resource_file_input_stream_class_init (GResourceFileInputStreamClass
*klass
)
762 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
763 GInputStreamClass
*stream_class
= G_INPUT_STREAM_CLASS (klass
);
764 GFileInputStreamClass
*file_stream_class
= G_FILE_INPUT_STREAM_CLASS (klass
);
766 gobject_class
->finalize
= g_resource_file_input_stream_finalize
;
768 stream_class
->read_fn
= g_resource_file_input_stream_read
;
769 stream_class
->skip
= g_resource_file_input_stream_skip
;
770 stream_class
->close_fn
= g_resource_file_input_stream_close
;
771 file_stream_class
->tell
= g_resource_file_input_stream_tell
;
772 file_stream_class
->can_seek
= g_resource_file_input_stream_can_seek
;
773 file_stream_class
->seek
= g_resource_file_input_stream_seek
;
774 file_stream_class
->query_info
= g_resource_file_input_stream_query_info
;
778 g_resource_file_input_stream_init (GResourceFileInputStream
*info
)
782 static GFileInputStream
*
783 _g_resource_file_input_stream_new (GInputStream
*in_stream
, GFile
*file
)
785 GResourceFileInputStream
*stream
;
787 stream
= g_object_new (G_TYPE_RESOURCE_FILE_INPUT_STREAM
, NULL
);
788 stream
->stream
= g_object_ref (in_stream
);
789 stream
->file
= g_object_ref (file
);
791 return G_FILE_INPUT_STREAM (stream
);
795 g_resource_file_input_stream_read (GInputStream
*stream
,
798 GCancellable
*cancellable
,
801 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
802 return g_input_stream_read (file
->stream
,
803 buffer
, count
, cancellable
, error
);
807 g_resource_file_input_stream_skip (GInputStream
*stream
,
809 GCancellable
*cancellable
,
812 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
813 return g_input_stream_skip (file
->stream
,
814 count
, cancellable
, error
);
818 g_resource_file_input_stream_close (GInputStream
*stream
,
819 GCancellable
*cancellable
,
822 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
823 return g_input_stream_close (file
->stream
,
829 g_resource_file_input_stream_tell (GFileInputStream
*stream
)
831 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
833 if (!G_IS_SEEKABLE (file
->stream
))
836 return g_seekable_tell (G_SEEKABLE (file
->stream
));
840 g_resource_file_input_stream_can_seek (GFileInputStream
*stream
)
842 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
844 return G_IS_SEEKABLE (file
->stream
) && g_seekable_can_seek (G_SEEKABLE (file
->stream
));
848 g_resource_file_input_stream_seek (GFileInputStream
*stream
,
851 GCancellable
*cancellable
,
854 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
856 if (!G_IS_SEEKABLE (file
->stream
))
858 g_set_error_literal (error
, G_IO_ERROR
, G_IO_ERROR_NOT_SUPPORTED
,
859 _("Input stream doesn't implement seek"));
863 return g_seekable_seek (G_SEEKABLE (file
->stream
),
864 offset
, type
, cancellable
, error
);
868 g_resource_file_input_stream_query_info (GFileInputStream
*stream
,
869 const char *attributes
,
870 GCancellable
*cancellable
,
873 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
875 return g_file_query_info (file
->file
, attributes
, 0, cancellable
, error
);