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, see <http://www.gnu.org/licenses/>.
18 * Author: Alexander Larsson <alexl@redhat.com>
25 #include "gresource.h"
26 #include "gresourcefile.h"
27 #include "gfileattribute.h"
28 #include <gfileattribute-priv.h>
29 #include <gfileinfo-priv.h>
31 #include "gfilemonitor.h"
32 #include "gseekable.h"
33 #include "gfileinputstream.h"
34 #include "gfileinfo.h"
35 #include "gfileenumerator.h"
36 #include "gcontenttype.h"
38 #include <glib/gstdio.h>
43 GObject parent_instance
;
48 struct _GResourceFileEnumerator
50 GFileEnumerator parent
;
52 GFileAttributeMatcher
*matcher
;
55 GFileQueryInfoFlags flags
;
61 struct _GResourceFileEnumeratorClass
63 GFileEnumeratorClass parent_class
;
66 typedef struct _GResourceFileEnumerator GResourceFileEnumerator
;
67 typedef struct _GResourceFileEnumeratorClass GResourceFileEnumeratorClass
;
69 static void g_resource_file_file_iface_init (GFileIface
*iface
);
71 static GFileAttributeInfoList
*resource_writable_attributes
= NULL
;
72 static GFileAttributeInfoList
*resource_writable_namespaces
= NULL
;
74 static GType
_g_resource_file_enumerator_get_type (void);
76 #define G_TYPE_RESOURCE_FILE_ENUMERATOR (_g_resource_file_enumerator_get_type ())
77 #define G_RESOURCE_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumerator))
78 #define G_RESOURCE_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumeratorClass))
79 #define G_IS_RESOURCE_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR))
80 #define G_IS_RESOURCE_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_RESOURCE_FILE_ENUMERATOR))
81 #define G_RESOURCE_FILE_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_RESOURCE_FILE_ENUMERATOR, GResourceFileEnumeratorClass))
83 #define G_TYPE_RESOURCE_FILE_INPUT_STREAM (_g_resource_file_input_stream_get_type ())
84 #define G_RESOURCE_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStream))
85 #define G_RESOURCE_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStreamClass))
86 #define G_IS_RESOURCE_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM))
87 #define G_IS_RESOURCE_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_RESOURCE_FILE_INPUT_STREAM))
88 #define G_RESOURCE_FILE_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_RESOURCE_FILE_INPUT_STREAM, GResourceFileInputStreamClass))
90 typedef struct _GResourceFileInputStream GResourceFileInputStream
;
91 typedef struct _GResourceFileInputStreamClass GResourceFileInputStreamClass
;
93 #define g_resource_file_get_type _g_resource_file_get_type
94 G_DEFINE_TYPE_WITH_CODE (GResourceFile
, g_resource_file
, G_TYPE_OBJECT
,
95 G_IMPLEMENT_INTERFACE (G_TYPE_FILE
,
96 g_resource_file_file_iface_init
))
98 #define g_resource_file_enumerator_get_type _g_resource_file_enumerator_get_type
99 G_DEFINE_TYPE (GResourceFileEnumerator
, g_resource_file_enumerator
, G_TYPE_FILE_ENUMERATOR
);
101 static GFileEnumerator
*_g_resource_file_enumerator_new (GResourceFile
*file
,
102 const char *attributes
,
103 GFileQueryInfoFlags flags
,
104 GCancellable
*cancellable
,
108 static GType
_g_resource_file_input_stream_get_type (void) G_GNUC_CONST
;
110 static GFileInputStream
*_g_resource_file_input_stream_new (GInputStream
*stream
, GFile
*file
);
114 g_resource_file_finalize (GObject
*object
)
116 GResourceFile
*resource
;
118 resource
= G_RESOURCE_FILE (object
);
120 g_free (resource
->path
);
122 G_OBJECT_CLASS (g_resource_file_parent_class
)->finalize (object
);
126 g_resource_file_class_init (GResourceFileClass
*klass
)
128 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
130 gobject_class
->finalize
= g_resource_file_finalize
;
132 resource_writable_attributes
= g_file_attribute_info_list_new ();
133 resource_writable_namespaces
= g_file_attribute_info_list_new ();
137 g_resource_file_init (GResourceFile
*resource
)
142 canonicalize_filename (const char *filename
)
144 char *canon
, *start
, *p
, *q
;
146 /* Skip multiple inital slashes */
147 while (filename
[0] == '/' && filename
[1] == '/')
150 if (*filename
!= '/')
151 canon
= g_strconcat ("/", filename
, NULL
);
153 canon
= g_strdup (filename
);
160 if (p
[0] == '.' && (p
[1] == 0 || p
[1] == '/'))
162 memmove (p
, p
+1, strlen (p
+1)+1);
164 else if (p
[0] == '.' && p
[1] == '.' && (p
[2] == 0 || p
[2] == '/'))
167 /* Skip previous separator */
171 while (p
> start
&& *p
!= '/')
175 memmove (p
, q
, strlen (q
)+1);
179 /* Skip until next separator */
180 while (*p
!= 0 && *p
!= '/')
185 /* Canonicalize one separator */
190 /* Remove additional separators */
192 while (*q
&& *q
== '/')
196 memmove (p
, q
, strlen (q
)+1);
199 /* Remove trailing slashes */
200 if (p
> start
&& *(p
-1) == '/')
207 g_resource_file_new_for_path (const char *path
)
209 GResourceFile
*resource
= g_object_new (G_TYPE_RESOURCE_FILE
, NULL
);
211 resource
->path
= canonicalize_filename (path
);
213 return G_FILE (resource
);
217 _g_resource_file_new (const char *uri
)
222 path
= g_uri_unescape_string (uri
+ strlen ("resource:"), NULL
);
223 resource
= g_resource_file_new_for_path (path
);
226 return G_FILE (resource
);
230 g_resource_file_is_native (GFile
*file
)
236 g_resource_file_has_uri_scheme (GFile
*file
,
237 const char *uri_scheme
)
239 return g_ascii_strcasecmp (uri_scheme
, "resource") == 0;
243 g_resource_file_get_uri_scheme (GFile
*file
)
245 return g_strdup ("resource");
249 g_resource_file_get_basename (GFile
*file
)
253 base
= strrchr (G_RESOURCE_FILE (file
)->path
, '/');
254 return g_strdup (base
+ 1);
258 g_resource_file_get_path (GFile
*file
)
264 g_resource_file_get_uri (GFile
*file
)
267 escaped
= g_uri_escape_string (G_RESOURCE_FILE (file
)->path
, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH
, FALSE
);
268 res
= g_strconcat ("resource://", escaped
, NULL
);
274 g_resource_file_get_parse_name (GFile
*file
)
276 return g_resource_file_get_uri (file
);
280 g_resource_file_get_parent (GFile
*file
)
282 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
283 GResourceFile
*parent
;
286 end
= strrchr (resource
->path
, '/');
288 if (end
== G_RESOURCE_FILE (file
)->path
)
291 parent
= g_object_new (G_TYPE_RESOURCE_FILE
, NULL
);
292 parent
->path
= g_strndup (resource
->path
,
293 end
- resource
->path
);
295 return G_FILE (parent
);
299 g_resource_file_dup (GFile
*file
)
301 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
303 return g_resource_file_new_for_path (resource
->path
);
307 g_resource_file_hash (GFile
*file
)
309 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
311 return g_str_hash (resource
->path
);
315 g_resource_file_equal (GFile
*file1
,
318 GResourceFile
*resource1
= G_RESOURCE_FILE (file1
);
319 GResourceFile
*resource2
= G_RESOURCE_FILE (file2
);
321 return g_str_equal (resource1
->path
, resource2
->path
);
325 match_prefix (const char *path
,
330 prefix_len
= strlen (prefix
);
331 if (strncmp (path
, prefix
, prefix_len
) != 0)
334 /* Handle the case where prefix is the root, so that
335 * the IS_DIR_SEPRARATOR check below works */
336 if (prefix_len
> 0 &&
337 prefix
[prefix_len
-1] == '/')
340 return path
+ prefix_len
;
344 g_resource_file_prefix_matches (GFile
*parent
,
347 GResourceFile
*parent_resource
= G_RESOURCE_FILE (parent
);
348 GResourceFile
*descendant_resource
= G_RESOURCE_FILE (descendant
);
349 const char *remainder
;
351 remainder
= match_prefix (descendant_resource
->path
, parent_resource
->path
);
352 if (remainder
!= NULL
&& *remainder
== '/')
358 g_resource_file_get_relative_path (GFile
*parent
,
361 GResourceFile
*parent_resource
= G_RESOURCE_FILE (parent
);
362 GResourceFile
*descendant_resource
= G_RESOURCE_FILE (descendant
);
363 const char *remainder
;
365 remainder
= match_prefix (descendant_resource
->path
, parent_resource
->path
);
367 if (remainder
!= NULL
&& *remainder
== '/')
368 return g_strdup (remainder
+ 1);
373 g_resource_file_resolve_relative_path (GFile
*file
,
374 const char *relative_path
)
376 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
380 if (relative_path
[0] == '/')
381 return g_resource_file_new_for_path (relative_path
);
383 filename
= g_build_path ("/", resource
->path
, relative_path
, NULL
);
384 child
= g_resource_file_new_for_path (filename
);
390 static GFileEnumerator
*
391 g_resource_file_enumerate_children (GFile
*file
,
392 const char *attributes
,
393 GFileQueryInfoFlags flags
,
394 GCancellable
*cancellable
,
397 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
398 return _g_resource_file_enumerator_new (resource
,
404 g_resource_file_get_child_for_display_name (GFile
*file
,
405 const char *display_name
,
410 new_file
= g_file_get_child (file
, display_name
);
416 g_resource_file_query_info (GFile
*file
,
417 const char *attributes
,
418 GFileQueryInfoFlags flags
,
419 GCancellable
*cancellable
,
422 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
423 GError
*my_error
= NULL
;
425 GFileAttributeMatcher
*matcher
;
428 guint32 resource_flags
;
434 children
= g_resources_enumerate_children (resource
->path
, 0, NULL
);
435 if (children
!= NULL
)
437 g_strfreev (children
);
441 /* root is always there */
442 if (strcmp ("/", resource
->path
) == 0)
447 res
= g_resources_get_info (resource
->path
, 0, &size
, &resource_flags
, &my_error
);
450 if (g_error_matches (my_error
, G_RESOURCE_ERROR
, G_RESOURCE_ERROR_NOT_FOUND
))
452 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_NOT_FOUND
,
453 _("The resource at “%s” does not exist"),
457 g_set_error_literal (error
, G_IO_ERROR
, G_IO_ERROR_FAILED
,
459 g_clear_error (&my_error
);
464 matcher
= g_file_attribute_matcher_new (attributes
);
466 info
= g_file_info_new ();
467 base
= g_resource_file_get_basename (file
);
468 g_file_info_set_name (info
, base
);
469 g_file_info_set_display_name (info
, base
);
471 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_READ
, TRUE
);
472 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_WRITE
, FALSE
);
473 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_EXECUTE
, FALSE
);
474 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_RENAME
, FALSE
);
475 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE
, FALSE
);
476 _g_file_info_set_attribute_boolean_by_id (info
, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH
, FALSE
);
480 g_file_info_set_file_type (info
, G_FILE_TYPE_DIRECTORY
);
487 g_file_info_set_file_type (info
, G_FILE_TYPE_REGULAR
);
488 g_file_info_set_size (info
, size
);
490 if ((_g_file_attribute_matcher_matches_id (matcher
, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE
) ||
491 ((~resource_flags
& G_RESOURCE_FLAGS_COMPRESSED
) &&
492 _g_file_attribute_matcher_matches_id (matcher
, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE
))) &&
493 (bytes
= g_resources_lookup_data (resource
->path
, 0, NULL
)))
498 data
= g_bytes_get_data (bytes
, &data_size
);
499 content_type
= g_content_type_guess (base
, data
, data_size
, NULL
);
501 g_bytes_unref (bytes
);
508 _g_file_info_set_attribute_string_by_id (info
, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE
, content_type
);
509 _g_file_info_set_attribute_string_by_id (info
, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE
, content_type
);
511 g_free (content_type
);
516 g_file_attribute_matcher_unref (matcher
);
522 g_resource_file_query_filesystem_info (GFile
*file
,
523 const char *attributes
,
524 GCancellable
*cancellable
,
528 GFileAttributeMatcher
*matcher
;
530 info
= g_file_info_new ();
532 matcher
= g_file_attribute_matcher_new (attributes
);
533 if (g_file_attribute_matcher_matches (matcher
, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE
))
534 g_file_info_set_attribute_string (info
, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE
, "resource");
536 if (g_file_attribute_matcher_matches (matcher
, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY
)) g_file_info_set_attribute_boolean (info
, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY
, TRUE
);
538 g_file_attribute_matcher_unref (matcher
);
543 static GFileAttributeInfoList
*
544 g_resource_file_query_settable_attributes (GFile
*file
,
545 GCancellable
*cancellable
,
548 return g_file_attribute_info_list_ref (resource_writable_attributes
);
551 static GFileAttributeInfoList
*
552 g_resource_file_query_writable_namespaces (GFile
*file
,
553 GCancellable
*cancellable
,
556 return g_file_attribute_info_list_ref (resource_writable_namespaces
);
559 static GFileInputStream
*
560 g_resource_file_read (GFile
*file
,
561 GCancellable
*cancellable
,
564 GResourceFile
*resource
= G_RESOURCE_FILE (file
);
565 GError
*my_error
= NULL
;
566 GInputStream
*stream
;
567 GFileInputStream
*res
;
569 stream
= g_resources_open_stream (resource
->path
, 0, &my_error
);
573 if (g_error_matches (my_error
, G_RESOURCE_ERROR
, G_RESOURCE_ERROR_NOT_FOUND
))
575 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_NOT_FOUND
,
576 _("The resource at “%s” does not exist"),
580 g_set_error_literal (error
, G_IO_ERROR
, G_IO_ERROR_FAILED
,
582 g_clear_error (&my_error
);
586 res
= _g_resource_file_input_stream_new (stream
, file
);
587 g_object_unref (stream
);
591 typedef GFileMonitor GResourceFileMonitor
;
592 typedef GFileMonitorClass GResourceFileMonitorClass
;
594 GType
g_resource_file_monitor_get_type (void);
596 G_DEFINE_TYPE (GResourceFileMonitor
, g_resource_file_monitor
, G_TYPE_FILE_MONITOR
)
599 g_resource_file_monitor_cancel (GFileMonitor
*monitor
)
605 g_resource_file_monitor_init (GResourceFileMonitor
*monitor
)
610 g_resource_file_monitor_class_init (GResourceFileMonitorClass
*class)
612 class->cancel
= g_resource_file_monitor_cancel
;
615 static GFileMonitor
*
616 g_resource_file_monitor_file (GFile
*file
,
617 GFileMonitorFlags flags
,
618 GCancellable
*cancellable
,
621 return g_object_new (g_resource_file_monitor_get_type (), NULL
);
625 g_resource_file_file_iface_init (GFileIface
*iface
)
627 iface
->dup
= g_resource_file_dup
;
628 iface
->hash
= g_resource_file_hash
;
629 iface
->equal
= g_resource_file_equal
;
630 iface
->is_native
= g_resource_file_is_native
;
631 iface
->has_uri_scheme
= g_resource_file_has_uri_scheme
;
632 iface
->get_uri_scheme
= g_resource_file_get_uri_scheme
;
633 iface
->get_basename
= g_resource_file_get_basename
;
634 iface
->get_path
= g_resource_file_get_path
;
635 iface
->get_uri
= g_resource_file_get_uri
;
636 iface
->get_parse_name
= g_resource_file_get_parse_name
;
637 iface
->get_parent
= g_resource_file_get_parent
;
638 iface
->prefix_matches
= g_resource_file_prefix_matches
;
639 iface
->get_relative_path
= g_resource_file_get_relative_path
;
640 iface
->resolve_relative_path
= g_resource_file_resolve_relative_path
;
641 iface
->get_child_for_display_name
= g_resource_file_get_child_for_display_name
;
642 iface
->enumerate_children
= g_resource_file_enumerate_children
;
643 iface
->query_info
= g_resource_file_query_info
;
644 iface
->query_filesystem_info
= g_resource_file_query_filesystem_info
;
645 iface
->query_settable_attributes
= g_resource_file_query_settable_attributes
;
646 iface
->query_writable_namespaces
= g_resource_file_query_writable_namespaces
;
647 iface
->read_fn
= g_resource_file_read
;
648 iface
->monitor_file
= g_resource_file_monitor_file
;
650 iface
->supports_thread_contexts
= TRUE
;
653 static GFileInfo
*g_resource_file_enumerator_next_file (GFileEnumerator
*enumerator
,
654 GCancellable
*cancellable
,
656 static gboolean
g_resource_file_enumerator_close (GFileEnumerator
*enumerator
,
657 GCancellable
*cancellable
,
661 g_resource_file_enumerator_finalize (GObject
*object
)
663 GResourceFileEnumerator
*resource
;
665 resource
= G_RESOURCE_FILE_ENUMERATOR (object
);
667 g_strfreev (resource
->children
);
668 g_free (resource
->path
);
669 g_free (resource
->attributes
);
671 G_OBJECT_CLASS (g_resource_file_enumerator_parent_class
)->finalize (object
);
675 g_resource_file_enumerator_class_init (GResourceFileEnumeratorClass
*klass
)
677 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
678 GFileEnumeratorClass
*enumerator_class
= G_FILE_ENUMERATOR_CLASS (klass
);
680 gobject_class
->finalize
= g_resource_file_enumerator_finalize
;
682 enumerator_class
->next_file
= g_resource_file_enumerator_next_file
;
683 enumerator_class
->close_fn
= g_resource_file_enumerator_close
;
687 g_resource_file_enumerator_init (GResourceFileEnumerator
*resource
)
691 static GFileEnumerator
*
692 _g_resource_file_enumerator_new (GResourceFile
*file
,
693 const char *attributes
,
694 GFileQueryInfoFlags flags
,
695 GCancellable
*cancellable
,
698 GResourceFileEnumerator
*resource
;
702 children
= g_resources_enumerate_children (file
->path
, 0, NULL
);
703 if (children
== NULL
&&
704 strcmp ("/", file
->path
) != 0)
706 res
= g_resources_get_info (file
->path
, 0, NULL
, NULL
, NULL
);
708 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_NOT_DIRECTORY
,
709 _("The resource at “%s” is not a directory"),
712 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_NOT_FOUND
,
713 _("The resource at “%s” does not exist"),
718 resource
= g_object_new (G_TYPE_RESOURCE_FILE_ENUMERATOR
,
722 resource
->children
= children
;
723 resource
->path
= g_strdup (file
->path
);
724 resource
->attributes
= g_strdup (attributes
);
725 resource
->flags
= flags
;
727 return G_FILE_ENUMERATOR (resource
);
731 g_resource_file_enumerator_next_file (GFileEnumerator
*enumerator
,
732 GCancellable
*cancellable
,
735 GResourceFileEnumerator
*resource
= G_RESOURCE_FILE_ENUMERATOR (enumerator
);
740 if (resource
->children
== NULL
||
741 resource
->children
[resource
->index
] == NULL
)
744 path
= g_build_path ("/", resource
->path
, resource
->children
[resource
->index
++], NULL
);
745 file
= g_resource_file_new_for_path (path
);
748 info
= g_file_query_info (file
,
749 resource
->attributes
,
754 g_object_unref (file
);
760 g_resource_file_enumerator_close (GFileEnumerator
*enumerator
,
761 GCancellable
*cancellable
,
768 struct _GResourceFileInputStream
770 GFileInputStream parent_instance
;
771 GInputStream
*stream
;
775 struct _GResourceFileInputStreamClass
777 GFileInputStreamClass parent_class
;
780 #define g_resource_file_input_stream_get_type _g_resource_file_input_stream_get_type
781 G_DEFINE_TYPE (GResourceFileInputStream
, g_resource_file_input_stream
, G_TYPE_FILE_INPUT_STREAM
);
783 static gssize
g_resource_file_input_stream_read (GInputStream
*stream
,
786 GCancellable
*cancellable
,
788 static gssize
g_resource_file_input_stream_skip (GInputStream
*stream
,
790 GCancellable
*cancellable
,
792 static gboolean
g_resource_file_input_stream_close (GInputStream
*stream
,
793 GCancellable
*cancellable
,
795 static goffset
g_resource_file_input_stream_tell (GFileInputStream
*stream
);
796 static gboolean
g_resource_file_input_stream_can_seek (GFileInputStream
*stream
);
797 static gboolean
g_resource_file_input_stream_seek (GFileInputStream
*stream
,
800 GCancellable
*cancellable
,
802 static GFileInfo
*g_resource_file_input_stream_query_info (GFileInputStream
*stream
,
803 const char *attributes
,
804 GCancellable
*cancellable
,
808 g_resource_file_input_stream_finalize (GObject
*object
)
810 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (object
);
812 g_object_unref (file
->stream
);
813 g_object_unref (file
->file
);
814 G_OBJECT_CLASS (g_resource_file_input_stream_parent_class
)->finalize (object
);
818 g_resource_file_input_stream_class_init (GResourceFileInputStreamClass
*klass
)
820 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
821 GInputStreamClass
*stream_class
= G_INPUT_STREAM_CLASS (klass
);
822 GFileInputStreamClass
*file_stream_class
= G_FILE_INPUT_STREAM_CLASS (klass
);
824 gobject_class
->finalize
= g_resource_file_input_stream_finalize
;
826 stream_class
->read_fn
= g_resource_file_input_stream_read
;
827 stream_class
->skip
= g_resource_file_input_stream_skip
;
828 stream_class
->close_fn
= g_resource_file_input_stream_close
;
829 file_stream_class
->tell
= g_resource_file_input_stream_tell
;
830 file_stream_class
->can_seek
= g_resource_file_input_stream_can_seek
;
831 file_stream_class
->seek
= g_resource_file_input_stream_seek
;
832 file_stream_class
->query_info
= g_resource_file_input_stream_query_info
;
836 g_resource_file_input_stream_init (GResourceFileInputStream
*info
)
840 static GFileInputStream
*
841 _g_resource_file_input_stream_new (GInputStream
*in_stream
, GFile
*file
)
843 GResourceFileInputStream
*stream
;
845 stream
= g_object_new (G_TYPE_RESOURCE_FILE_INPUT_STREAM
, NULL
);
846 stream
->stream
= g_object_ref (in_stream
);
847 stream
->file
= g_object_ref (file
);
849 return G_FILE_INPUT_STREAM (stream
);
853 g_resource_file_input_stream_read (GInputStream
*stream
,
856 GCancellable
*cancellable
,
859 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
860 return g_input_stream_read (file
->stream
,
861 buffer
, count
, cancellable
, error
);
865 g_resource_file_input_stream_skip (GInputStream
*stream
,
867 GCancellable
*cancellable
,
870 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
871 return g_input_stream_skip (file
->stream
,
872 count
, cancellable
, error
);
876 g_resource_file_input_stream_close (GInputStream
*stream
,
877 GCancellable
*cancellable
,
880 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
881 return g_input_stream_close (file
->stream
,
887 g_resource_file_input_stream_tell (GFileInputStream
*stream
)
889 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
891 if (!G_IS_SEEKABLE (file
->stream
))
894 return g_seekable_tell (G_SEEKABLE (file
->stream
));
898 g_resource_file_input_stream_can_seek (GFileInputStream
*stream
)
900 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
902 return G_IS_SEEKABLE (file
->stream
) && g_seekable_can_seek (G_SEEKABLE (file
->stream
));
906 g_resource_file_input_stream_seek (GFileInputStream
*stream
,
909 GCancellable
*cancellable
,
912 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
914 if (!G_IS_SEEKABLE (file
->stream
))
916 g_set_error_literal (error
, G_IO_ERROR
, G_IO_ERROR_NOT_SUPPORTED
,
917 _("Input stream doesn’t implement seek"));
921 return g_seekable_seek (G_SEEKABLE (file
->stream
),
922 offset
, type
, cancellable
, error
);
926 g_resource_file_input_stream_query_info (GFileInputStream
*stream
,
927 const char *attributes
,
928 GCancellable
*cancellable
,
931 GResourceFileInputStream
*file
= G_RESOURCE_FILE_INPUT_STREAM (stream
);
933 return g_file_query_info (file
->file
, attributes
, 0, cancellable
, error
);