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 static GType
_g_resource_file_enumerator_get_type (void);
77 #define G_TYPE_RESOURCE_FILE_ENUMERATOR (_g_resource_file_enumerator_get_type ())
78 #define G_RESOURCE_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumerator))
79 #define G_RESOURCE_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumeratorClass))
80 #define G_IS_RESOURCE_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR))
81 #define G_IS_RESOURCE_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_RESOURCE_FILE_ENUMERATOR))
82 #define G_RESOURCE_FILE_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumeratorClass))
84 #define G_TYPE_RESOURCE_FILE_INPUT_STREAM (_g_resource_file_input_stream_get_type ())
85 #define G_RESOURCE_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStream))
86 #define G_RESOURCE_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStreamClass))
87 #define G_IS_RESOURCE_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM))
88 #define G_IS_RESOURCE_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_RESOURCE_FILE_INPUT_STREAM))
89 #define G_RESOURCE_FILE_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStreamClass))
91 typedef struct _GResourceFileInputStream GResourceFileInputStream
;
92 typedef struct _GResourceFileInputStreamClass GResourceFileInputStreamClass
;
94 #define g_resource_file_get_type _g_resource_file_get_type
95 G_DEFINE_TYPE_WITH_CODE (GResourceFile
, g_resource_file
, G_TYPE_OBJECT
,
96 G_IMPLEMENT_INTERFACE (G_TYPE_FILE
,
97 g_resource_file_file_iface_init
))
99 #define g_resource_file_enumerator_get_type _g_resource_file_enumerator_get_type
100 G_DEFINE_TYPE (GResourceFileEnumerator
, g_resource_file_enumerator
, G_TYPE_FILE_ENUMERATOR
);
102 static GFileEnumerator
*_g_resource_file_enumerator_new (GResourceFile
*file
,
103 const char *attributes
,
104 GFileQueryInfoFlags flags
,
105 GCancellable
*cancellable
,
109 static GType
_g_resource_file_input_stream_get_type (void) G_GNUC_CONST
;
111 static GFileInputStream
*_g_resource_file_input_stream_new (GInputStream
*stream
, GFile
*file
);
115 g_resource_file_finalize (GObject
*object
)
117 GResourceFile
*resource
;
119 resource
= G_RESOURCE_FILE (object
);
121 g_free (resource
->path
);
123 G_OBJECT_CLASS (g_resource_file_parent_class
)->finalize (object
);
127 g_resource_file_class_init (GResourceFileClass
*klass
)
129 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
131 gobject_class
->finalize
= g_resource_file_finalize
;
133 resource_writable_attributes
= g_file_attribute_info_list_new ();
134 resource_writable_namespaces
= g_file_attribute_info_list_new ();
138 g_resource_file_init (GResourceFile
*resource
)
143 canonicalize_filename (const char *filename
)
145 char *canon
, *start
, *p
, *q
;
147 /* Skip multiple inital slashes */
148 while (filename
[0] == '/' && filename
[1] == '/')
151 if (*filename
!= '/')
152 canon
= g_strconcat ("/", filename
, NULL
);
154 canon
= g_strdup (filename
);
161 if (p
[0] == '.' && (p
[1] == 0 || p
[1] == '/'))
163 memmove (p
, p
+1, strlen (p
+1)+1);
165 else if (p
[0] == '.' && p
[1] == '.' && (p
[2] == 0 || p
[2] == '/'))
168 /* Skip previous separator */
172 while (p
> start
&& *p
!= '/')
176 memmove (p
, q
, strlen (q
)+1);
180 /* Skip until next separator */
181 while (*p
!= 0 && *p
!= '/')
186 /* Canonicalize one separator */
191 /* Remove additional separators */
193 while (*q
&& *q
== '/')
197 memmove (p
, q
, strlen (q
)+1);
200 /* Remove trailing slashes */
201 if (p
> start
&& *(p
-1) == '/')
208 g_resource_file_new_for_path (const char *path
)
210 GResourceFile
*resource
= g_object_new (G_TYPE_RESOURCE_FILE
, NULL
);
212 resource
->path
= canonicalize_filename (path
);
214 return G_FILE (resource
);
218 _g_resource_file_new (const char *uri
)
223 path
= g_uri_unescape_string (uri
+ strlen ("resource:"), NULL
);
224 resource
= g_resource_file_new_for_path (path
);
227 return G_FILE (resource
);
231 g_resource_file_is_native (GFile
*file
)
237 g_resource_file_has_uri_scheme (GFile
*file
,
238 const char *uri_scheme
)
240 return g_ascii_strcasecmp (uri_scheme
, "resource") == 0;
244 g_resource_file_get_uri_scheme (GFile
*file
)
246 return g_strdup ("resource");
250 g_resource_file_get_basename (GFile
*file
)
254 base
= strrchr (G_RESOURCE_FILE (file
)->path
, '/');
255 return g_strdup (base
+ 1);
259 g_resource_file_get_path (GFile
*file
)
265 g_resource_file_get_uri (GFile
*file
)
268 escaped
= g_uri_escape_string (G_RESOURCE_FILE (file
)->path
, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH
, FALSE
);
269 res
= g_strconcat ("resource://", escaped
, NULL
);
275 g_resource_file_get_parse_name (GFile
*file
)
277 return g_resource_file_get_uri (file
);
281 g_resource_file_get_parent (GFile
*file
)
283 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
284 GResourceFile
*parent
;
287 end
= strrchr (resource
->path
, '/');
289 if (end
== G_RESOURCE_FILE (file
)->path
)
292 parent
= g_object_new (G_TYPE_RESOURCE_FILE
, NULL
);
293 parent
->path
= g_strndup (resource
->path
,
294 end
- resource
->path
);
296 return G_FILE (parent
);
300 g_resource_file_dup (GFile
*file
)
302 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
304 return g_resource_file_new_for_path (resource
->path
);
308 g_resource_file_hash (GFile
*file
)
310 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
312 return g_str_hash (resource
->path
);
316 g_resource_file_equal (GFile
*file1
,
319 GResourceFile
*resource1
= G_RESOURCE_FILE (file1
);
320 GResourceFile
*resource2
= G_RESOURCE_FILE (file2
);
322 return g_str_equal (resource1
->path
, resource2
->path
);
326 match_prefix (const char *path
,
331 prefix_len
= strlen (prefix
);
332 if (strncmp (path
, prefix
, prefix_len
) != 0)
335 /* Handle the case where prefix is the root, so that
336 * the IS_DIR_SEPRARATOR check below works */
337 if (prefix_len
> 0 &&
338 prefix
[prefix_len
-1] == '/')
341 return path
+ prefix_len
;
345 g_resource_file_prefix_matches (GFile
*parent
,
348 GResourceFile
*parent_resource
= G_RESOURCE_FILE (parent
);
349 GResourceFile
*descendant_resource
= G_RESOURCE_FILE (descendant
);
350 const char *remainder
;
352 remainder
= match_prefix (descendant_resource
->path
, parent_resource
->path
);
353 if (remainder
!= NULL
&& *remainder
== '/')
359 g_resource_file_get_relative_path (GFile
*parent
,
362 GResourceFile
*parent_resource
= G_RESOURCE_FILE (parent
);
363 GResourceFile
*descendant_resource
= G_RESOURCE_FILE (descendant
);
364 const char *remainder
;
366 remainder
= match_prefix (descendant_resource
->path
, parent_resource
->path
);
368 if (remainder
!= NULL
&& *remainder
== '/')
369 return g_strdup (remainder
+ 1);
374 g_resource_file_resolve_relative_path (GFile
*file
,
375 const char *relative_path
)
377 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
381 if (relative_path
[0] == '/')
382 return g_resource_file_new_for_path (relative_path
);
384 filename
= g_build_path ("/", resource
->path
, relative_path
, NULL
);
385 child
= g_resource_file_new_for_path (filename
);
391 static GFileEnumerator
*
392 g_resource_file_enumerate_children (GFile
*file
,
393 const char *attributes
,
394 GFileQueryInfoFlags flags
,
395 GCancellable
*cancellable
,
398 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
399 return _g_resource_file_enumerator_new (resource
,
405 g_resource_file_get_child_for_display_name (GFile
*file
,
406 const char *display_name
,
411 new_file
= g_file_get_child (file
, display_name
);
417 g_resource_file_query_info (GFile
*file
,
418 const char *attributes
,
419 GFileQueryInfoFlags flags
,
420 GCancellable
*cancellable
,
423 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
424 GError
*my_error
= NULL
;
426 GFileAttributeMatcher
*matcher
;
429 guint32 resource_flags
;
435 children
= g_resources_enumerate_children (resource
->path
, 0, NULL
);
436 if (children
!= NULL
)
438 g_strfreev (children
);
442 /* root is always there */
443 if (strcmp ("/", resource
->path
) == 0)
448 res
= g_resources_get_info (resource
->path
, 0, &size
, &resource_flags
, &my_error
);
451 if (g_error_matches (my_error
, G_RESOURCE_ERROR
, G_RESOURCE_ERROR_NOT_FOUND
))
453 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_NOT_FOUND
,
454 _("The resource at '%s' does not exist"),
458 g_set_error_literal (error
, G_IO_ERROR
, G_IO_ERROR_FAILED
,
460 g_clear_error (&my_error
);
465 matcher
= g_file_attribute_matcher_new (attributes
);
467 info
= g_file_info_new ();
468 base
= g_resource_file_get_basename (file
);
469 g_file_info_set_name (info
, base
);
470 g_file_info_set_display_name (info
, base
);
472 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_READ
, TRUE
);
473 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_WRITE
, FALSE
);
474 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_EXECUTE
, FALSE
);
475 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_RENAME
, FALSE
);
476 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE
, FALSE
);
477 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH
, FALSE
);
481 g_file_info_set_file_type (info
, G_FILE_TYPE_DIRECTORY
);
488 g_file_info_set_file_type (info
, G_FILE_TYPE_REGULAR
);
489 g_file_info_set_size (info
, size
);
491 if ((_g_file_attribute_matcher_matches_id (matcher
, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE
) ||
492 ((~resource_flags
& G_RESOURCE_FLAGS_COMPRESSED
) &&
493 _g_file_attribute_matcher_matches_id (matcher
, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE
))) &&
494 (bytes
= g_resources_lookup_data (resource
->path
, 0, NULL
)))
499 data
= g_bytes_get_data (bytes
, &data_size
);
500 content_type
= g_content_type_guess (base
, data
, data_size
, NULL
);
502 g_bytes_unref (bytes
);
509 _g_file_info_set_attribute_string_by_id (info
, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE
, content_type
);
510 _g_file_info_set_attribute_string_by_id (info
, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE
, content_type
);
512 g_free (content_type
);
517 g_file_attribute_matcher_unref (matcher
);
522 static GFileAttributeInfoList
*
523 g_resource_file_query_settable_attributes (GFile
*file
,
524 GCancellable
*cancellable
,
527 return g_file_attribute_info_list_ref (resource_writable_attributes
);
530 static GFileAttributeInfoList
*
531 g_resource_file_query_writable_namespaces (GFile
*file
,
532 GCancellable
*cancellable
,
535 return g_file_attribute_info_list_ref (resource_writable_namespaces
);
538 static GFileInputStream
*
539 g_resource_file_read (GFile
*file
,
540 GCancellable
*cancellable
,
543 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
544 GError
*my_error
= NULL
;
545 GInputStream
*stream
;
546 GFileInputStream
*res
;
548 stream
= g_resources_open_stream (resource
->path
, 0, &my_error
);
552 if (g_error_matches (my_error
, G_RESOURCE_ERROR
, G_RESOURCE_ERROR_NOT_FOUND
))
554 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_NOT_FOUND
,
555 _("The resource at '%s' does not exist"),
559 g_set_error_literal (error
, G_IO_ERROR
, G_IO_ERROR_FAILED
,
561 g_clear_error (&my_error
);
565 res
= _g_resource_file_input_stream_new (stream
, file
);
566 g_object_unref (stream
);
571 g_resource_file_file_iface_init (GFileIface
*iface
)
573 iface
->dup
= g_resource_file_dup
;
574 iface
->hash
= g_resource_file_hash
;
575 iface
->equal
= g_resource_file_equal
;
576 iface
->is_native
= g_resource_file_is_native
;
577 iface
->has_uri_scheme
= g_resource_file_has_uri_scheme
;
578 iface
->get_uri_scheme
= g_resource_file_get_uri_scheme
;
579 iface
->get_basename
= g_resource_file_get_basename
;
580 iface
->get_path
= g_resource_file_get_path
;
581 iface
->get_uri
= g_resource_file_get_uri
;
582 iface
->get_parse_name
= g_resource_file_get_parse_name
;
583 iface
->get_parent
= g_resource_file_get_parent
;
584 iface
->prefix_matches
= g_resource_file_prefix_matches
;
585 iface
->get_relative_path
= g_resource_file_get_relative_path
;
586 iface
->resolve_relative_path
= g_resource_file_resolve_relative_path
;
587 iface
->get_child_for_display_name
= g_resource_file_get_child_for_display_name
;
588 iface
->enumerate_children
= g_resource_file_enumerate_children
;
589 iface
->query_info
= g_resource_file_query_info
;
590 iface
->query_settable_attributes
= g_resource_file_query_settable_attributes
;
591 iface
->query_writable_namespaces
= g_resource_file_query_writable_namespaces
;
592 iface
->read_fn
= g_resource_file_read
;
594 iface
->supports_thread_contexts
= TRUE
;
597 static GFileInfo
*g_resource_file_enumerator_next_file (GFileEnumerator
*enumerator
,
598 GCancellable
*cancellable
,
600 static gboolean
g_resource_file_enumerator_close (GFileEnumerator
*enumerator
,
601 GCancellable
*cancellable
,
605 g_resource_file_enumerator_finalize (GObject
*object
)
607 GResourceFileEnumerator
*resource
;
609 resource
= G_RESOURCE_FILE_ENUMERATOR (object
);
611 g_strfreev (resource
->children
);
612 g_free (resource
->path
);
613 g_free (resource
->attributes
);
615 G_OBJECT_CLASS (g_resource_file_enumerator_parent_class
)->finalize (object
);
619 g_resource_file_enumerator_class_init (GResourceFileEnumeratorClass
*klass
)
621 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
622 GFileEnumeratorClass
*enumerator_class
= G_FILE_ENUMERATOR_CLASS (klass
);
624 gobject_class
->finalize
= g_resource_file_enumerator_finalize
;
626 enumerator_class
->next_file
= g_resource_file_enumerator_next_file
;
627 enumerator_class
->close_fn
= g_resource_file_enumerator_close
;
631 g_resource_file_enumerator_init (GResourceFileEnumerator
*resource
)
635 static GFileEnumerator
*
636 _g_resource_file_enumerator_new (GResourceFile
*file
,
637 const char *attributes
,
638 GFileQueryInfoFlags flags
,
639 GCancellable
*cancellable
,
642 GResourceFileEnumerator
*resource
;
646 children
= g_resources_enumerate_children (file
->path
, 0, NULL
);
647 if (children
== NULL
&&
648 strcmp ("/", file
->path
) != 0)
650 res
= g_resources_get_info (file
->path
, 0, NULL
, NULL
, NULL
);
652 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_NOT_DIRECTORY
,
653 _("The resource at '%s' is not a directory"),
656 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_NOT_FOUND
,
657 _("The resource at '%s' does not exist"),
662 resource
= g_object_new (G_TYPE_RESOURCE_FILE_ENUMERATOR
,
666 resource
->children
= children
;
667 resource
->path
= g_strdup (file
->path
);
668 resource
->attributes
= g_strdup (attributes
);
669 resource
->flags
= flags
;
671 return G_FILE_ENUMERATOR (resource
);
675 g_resource_file_enumerator_next_file (GFileEnumerator
*enumerator
,
676 GCancellable
*cancellable
,
679 GResourceFileEnumerator
*resource
= G_RESOURCE_FILE_ENUMERATOR (enumerator
);
684 if (resource
->children
== NULL
||
685 resource
->children
[resource
->index
] == NULL
)
688 path
= g_build_path ("/", resource
->path
, resource
->children
[resource
->index
++], NULL
);
689 file
= g_resource_file_new_for_path (path
);
692 info
= g_file_query_info (file
,
693 resource
->attributes
,
698 g_object_unref (file
);
704 g_resource_file_enumerator_close (GFileEnumerator
*enumerator
,
705 GCancellable
*cancellable
,
712 struct _GResourceFileInputStream
714 GFileInputStream parent_instance
;
715 GInputStream
*stream
;
719 struct _GResourceFileInputStreamClass
721 GFileInputStreamClass parent_class
;
724 #define g_resource_file_input_stream_get_type _g_resource_file_input_stream_get_type
725 G_DEFINE_TYPE (GResourceFileInputStream
, g_resource_file_input_stream
, G_TYPE_FILE_INPUT_STREAM
);
727 static gssize
g_resource_file_input_stream_read (GInputStream
*stream
,
730 GCancellable
*cancellable
,
732 static gssize
g_resource_file_input_stream_skip (GInputStream
*stream
,
734 GCancellable
*cancellable
,
736 static gboolean
g_resource_file_input_stream_close (GInputStream
*stream
,
737 GCancellable
*cancellable
,
739 static goffset
g_resource_file_input_stream_tell (GFileInputStream
*stream
);
740 static gboolean
g_resource_file_input_stream_can_seek (GFileInputStream
*stream
);
741 static gboolean
g_resource_file_input_stream_seek (GFileInputStream
*stream
,
744 GCancellable
*cancellable
,
746 static GFileInfo
*g_resource_file_input_stream_query_info (GFileInputStream
*stream
,
747 const char *attributes
,
748 GCancellable
*cancellable
,
752 g_resource_file_input_stream_finalize (GObject
*object
)
754 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (object
);
756 g_object_unref (file
->stream
);
757 g_object_unref (file
->file
);
758 G_OBJECT_CLASS (g_resource_file_input_stream_parent_class
)->finalize (object
);
762 g_resource_file_input_stream_class_init (GResourceFileInputStreamClass
*klass
)
764 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
765 GInputStreamClass
*stream_class
= G_INPUT_STREAM_CLASS (klass
);
766 GFileInputStreamClass
*file_stream_class
= G_FILE_INPUT_STREAM_CLASS (klass
);
768 gobject_class
->finalize
= g_resource_file_input_stream_finalize
;
770 stream_class
->read_fn
= g_resource_file_input_stream_read
;
771 stream_class
->skip
= g_resource_file_input_stream_skip
;
772 stream_class
->close_fn
= g_resource_file_input_stream_close
;
773 file_stream_class
->tell
= g_resource_file_input_stream_tell
;
774 file_stream_class
->can_seek
= g_resource_file_input_stream_can_seek
;
775 file_stream_class
->seek
= g_resource_file_input_stream_seek
;
776 file_stream_class
->query_info
= g_resource_file_input_stream_query_info
;
780 g_resource_file_input_stream_init (GResourceFileInputStream
*info
)
784 static GFileInputStream
*
785 _g_resource_file_input_stream_new (GInputStream
*in_stream
, GFile
*file
)
787 GResourceFileInputStream
*stream
;
789 stream
= g_object_new (G_TYPE_RESOURCE_FILE_INPUT_STREAM
, NULL
);
790 stream
->stream
= g_object_ref (in_stream
);
791 stream
->file
= g_object_ref (file
);
793 return G_FILE_INPUT_STREAM (stream
);
797 g_resource_file_input_stream_read (GInputStream
*stream
,
800 GCancellable
*cancellable
,
803 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
804 return g_input_stream_read (file
->stream
,
805 buffer
, count
, cancellable
, error
);
809 g_resource_file_input_stream_skip (GInputStream
*stream
,
811 GCancellable
*cancellable
,
814 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
815 return g_input_stream_skip (file
->stream
,
816 count
, cancellable
, error
);
820 g_resource_file_input_stream_close (GInputStream
*stream
,
821 GCancellable
*cancellable
,
824 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
825 return g_input_stream_close (file
->stream
,
831 g_resource_file_input_stream_tell (GFileInputStream
*stream
)
833 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
835 if (!G_IS_SEEKABLE (file
->stream
))
838 return g_seekable_tell (G_SEEKABLE (file
->stream
));
842 g_resource_file_input_stream_can_seek (GFileInputStream
*stream
)
844 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
846 return G_IS_SEEKABLE (file
->stream
) && g_seekable_can_seek (G_SEEKABLE (file
->stream
));
850 g_resource_file_input_stream_seek (GFileInputStream
*stream
,
853 GCancellable
*cancellable
,
856 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
858 if (!G_IS_SEEKABLE (file
->stream
))
860 g_set_error_literal (error
, G_IO_ERROR
, G_IO_ERROR_NOT_SUPPORTED
,
861 _("Input stream doesn't implement seek"));
865 return g_seekable_seek (G_SEEKABLE (file
->stream
),
866 offset
, type
, cancellable
, error
);
870 g_resource_file_input_stream_query_info (GFileInputStream
*stream
,
871 const char *attributes
,
872 GCancellable
*cancellable
,
875 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
877 return g_file_query_info (file
->file
, attributes
, 0, cancellable
, error
);