Branch data Line data Source code
1 : : /* GIO - GLib Input, IO and Streaming Library
2 : : *
3 : : * Copyright (C) 2006-2007 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: Alexander Larsson <alexl@redhat.com>
21 : : */
22 : :
23 : : #include "config.h"
24 : :
25 : : #include <glib.h>
26 : : #include <gfileiostream.h>
27 : : #include <gseekable.h>
28 : : #include "gasyncresult.h"
29 : : #include "gtask.h"
30 : : #include "gcancellable.h"
31 : : #include "gioerror.h"
32 : : #include "gfileoutputstream.h"
33 : : #include "glibintl.h"
34 : :
35 : :
36 : : /**
37 : : * GFileIOStream:
38 : : *
39 : : * `GFileIOStream` provides I/O streams that both read and write to the same
40 : : * file handle.
41 : : *
42 : : * `GFileIOStream` implements [iface@Gio.Seekable], which allows the I/O
43 : : * stream to jump to arbitrary positions in the file and to truncate
44 : : * the file, provided the filesystem of the file supports these
45 : : * operations.
46 : : *
47 : : * To find the position of a file I/O stream, use [method@Gio.Seekable.tell].
48 : : *
49 : : * To find out if a file I/O stream supports seeking, use
50 : : * [method@Gio.Seekable.can_seek]. To position a file I/O stream, use
51 : : * [method@Gio.Seekable.seek]. To find out if a file I/O stream supports
52 : : * truncating, use [method@Gio.Seekable.can_truncate]. To truncate a file I/O
53 : : * stream, use [method@Gio.Seekable.truncate].
54 : : *
55 : : * The default implementation of all the `GFileIOStream` operations
56 : : * and the implementation of [iface@Gio.Seekable] just call into the same
57 : : * operations on the output stream.
58 : : *
59 : : * Since: 2.22
60 : : **/
61 : :
62 : : static void g_file_io_stream_seekable_iface_init (GSeekableIface *iface);
63 : : static goffset g_file_io_stream_seekable_tell (GSeekable *seekable);
64 : : static gboolean g_file_io_stream_seekable_can_seek (GSeekable *seekable);
65 : : static gboolean g_file_io_stream_seekable_seek (GSeekable *seekable,
66 : : goffset offset,
67 : : GSeekType type,
68 : : GCancellable *cancellable,
69 : : GError **error);
70 : : static gboolean g_file_io_stream_seekable_can_truncate (GSeekable *seekable);
71 : : static gboolean g_file_io_stream_seekable_truncate (GSeekable *seekable,
72 : : goffset offset,
73 : : GCancellable *cancellable,
74 : : GError **error);
75 : : static void g_file_io_stream_real_query_info_async (GFileIOStream *stream,
76 : : const char *attributes,
77 : : int io_priority,
78 : : GCancellable *cancellable,
79 : : GAsyncReadyCallback callback,
80 : : gpointer user_data);
81 : : static GFileInfo *g_file_io_stream_real_query_info_finish (GFileIOStream *stream,
82 : : GAsyncResult *result,
83 : : GError **error);
84 : :
85 : : struct _GFileIOStreamPrivate {
86 : : GAsyncReadyCallback outstanding_callback;
87 : : };
88 : :
89 : 452 : G_DEFINE_TYPE_WITH_CODE (GFileIOStream, g_file_io_stream, G_TYPE_IO_STREAM,
90 : : G_ADD_PRIVATE (GFileIOStream)
91 : : G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
92 : : g_file_io_stream_seekable_iface_init))
93 : :
94 : : static void
95 : 8 : g_file_io_stream_seekable_iface_init (GSeekableIface *iface)
96 : : {
97 : 8 : iface->tell = g_file_io_stream_seekable_tell;
98 : 8 : iface->can_seek = g_file_io_stream_seekable_can_seek;
99 : 8 : iface->seek = g_file_io_stream_seekable_seek;
100 : 8 : iface->can_truncate = g_file_io_stream_seekable_can_truncate;
101 : 8 : iface->truncate_fn = g_file_io_stream_seekable_truncate;
102 : 8 : }
103 : :
104 : : static void
105 : 108 : g_file_io_stream_init (GFileIOStream *stream)
106 : : {
107 : 108 : stream->priv = g_file_io_stream_get_instance_private (stream);
108 : 108 : }
109 : :
110 : : /**
111 : : * g_file_io_stream_query_info:
112 : : * @stream: a #GFileIOStream.
113 : : * @attributes: a file attribute query string.
114 : : * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
115 : : * @error: a #GError, %NULL to ignore.
116 : : *
117 : : * Queries a file io stream for the given @attributes.
118 : : * This function blocks while querying the stream. For the asynchronous
119 : : * version of this function, see g_file_io_stream_query_info_async().
120 : : * While the stream is blocked, the stream will set the pending flag
121 : : * internally, and any other operations on the stream will fail with
122 : : * %G_IO_ERROR_PENDING.
123 : : *
124 : : * Can fail if the stream was already closed (with @error being set to
125 : : * %G_IO_ERROR_CLOSED), the stream has pending operations (with @error being
126 : : * set to %G_IO_ERROR_PENDING), or if querying info is not supported for
127 : : * the stream's interface (with @error being set to %G_IO_ERROR_NOT_SUPPORTED). I
128 : : * all cases of failure, %NULL will be returned.
129 : : *
130 : : * If @cancellable is not %NULL, then the operation can be cancelled by
131 : : * triggering the cancellable object from another thread. If the operation
132 : : * was cancelled, the error %G_IO_ERROR_CANCELLED will be set, and %NULL will
133 : : * be returned.
134 : : *
135 : : * Returns: (transfer full): a #GFileInfo for the @stream, or %NULL on error.
136 : : *
137 : : * Since: 2.22
138 : : **/
139 : : GFileInfo *
140 : 1 : g_file_io_stream_query_info (GFileIOStream *stream,
141 : : const char *attributes,
142 : : GCancellable *cancellable,
143 : : GError **error)
144 : : {
145 : : GFileIOStreamClass *class;
146 : : GIOStream *io_stream;
147 : : GFileInfo *info;
148 : :
149 : 1 : g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), NULL);
150 : :
151 : 1 : io_stream = G_IO_STREAM (stream);
152 : :
153 : 1 : if (!g_io_stream_set_pending (io_stream, error))
154 : 0 : return NULL;
155 : :
156 : 1 : info = NULL;
157 : :
158 : 1 : if (cancellable)
159 : 0 : g_cancellable_push_current (cancellable);
160 : :
161 : 1 : class = G_FILE_IO_STREAM_GET_CLASS (stream);
162 : 1 : if (class->query_info)
163 : 1 : info = class->query_info (stream, attributes, cancellable, error);
164 : : else
165 : 0 : g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
166 : : _("Stream doesn’t support query_info"));
167 : :
168 : 1 : if (cancellable)
169 : 0 : g_cancellable_pop_current (cancellable);
170 : :
171 : 1 : g_io_stream_clear_pending (io_stream);
172 : :
173 : 1 : return info;
174 : : }
175 : :
176 : : static void
177 : 0 : async_ready_callback_wrapper (GObject *source_object,
178 : : GAsyncResult *res,
179 : : gpointer user_data)
180 : : {
181 : 0 : GFileIOStream *stream = G_FILE_IO_STREAM (source_object);
182 : :
183 : 0 : g_io_stream_clear_pending (G_IO_STREAM (stream));
184 : 0 : if (stream->priv->outstanding_callback)
185 : 0 : (*stream->priv->outstanding_callback) (source_object, res, user_data);
186 : 0 : g_object_unref (stream);
187 : 0 : }
188 : :
189 : : /**
190 : : * g_file_io_stream_query_info_async:
191 : : * @stream: a #GFileIOStream.
192 : : * @attributes: a file attribute query string.
193 : : * @io_priority: the [I/O priority](iface.AsyncResult.html#io-priority) of the
194 : : * request
195 : : * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
196 : : * @callback: (scope async): a #GAsyncReadyCallback
197 : : * to call when the request is satisfied
198 : : * @user_data: the data to pass to callback function
199 : : *
200 : : * Asynchronously queries the @stream for a #GFileInfo. When completed,
201 : : * @callback will be called with a #GAsyncResult which can be used to
202 : : * finish the operation with g_file_io_stream_query_info_finish().
203 : : *
204 : : * For the synchronous version of this function, see
205 : : * g_file_io_stream_query_info().
206 : : *
207 : : * Since: 2.22
208 : : **/
209 : : void
210 : 0 : g_file_io_stream_query_info_async (GFileIOStream *stream,
211 : : const char *attributes,
212 : : int io_priority,
213 : : GCancellable *cancellable,
214 : : GAsyncReadyCallback callback,
215 : : gpointer user_data)
216 : : {
217 : : GFileIOStreamClass *klass;
218 : : GIOStream *io_stream;
219 : 0 : GError *error = NULL;
220 : :
221 : 0 : g_return_if_fail (G_IS_FILE_IO_STREAM (stream));
222 : :
223 : 0 : io_stream = G_IO_STREAM (stream);
224 : :
225 : 0 : if (!g_io_stream_set_pending (io_stream, &error))
226 : : {
227 : 0 : g_task_report_error (stream, callback, user_data,
228 : : g_file_io_stream_query_info_async,
229 : : error);
230 : 0 : return;
231 : : }
232 : :
233 : 0 : klass = G_FILE_IO_STREAM_GET_CLASS (stream);
234 : :
235 : 0 : stream->priv->outstanding_callback = callback;
236 : 0 : g_object_ref (stream);
237 : 0 : klass->query_info_async (stream, attributes, io_priority, cancellable,
238 : : async_ready_callback_wrapper, user_data);
239 : : }
240 : :
241 : : /**
242 : : * g_file_io_stream_query_info_finish:
243 : : * @stream: a #GFileIOStream.
244 : : * @result: a #GAsyncResult.
245 : : * @error: a #GError, %NULL to ignore.
246 : : *
247 : : * Finalizes the asynchronous query started
248 : : * by g_file_io_stream_query_info_async().
249 : : *
250 : : * Returns: (transfer full): A #GFileInfo for the finished query.
251 : : *
252 : : * Since: 2.22
253 : : **/
254 : : GFileInfo *
255 : 0 : g_file_io_stream_query_info_finish (GFileIOStream *stream,
256 : : GAsyncResult *result,
257 : : GError **error)
258 : : {
259 : : GFileIOStreamClass *class;
260 : :
261 : 0 : g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), NULL);
262 : 0 : g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
263 : :
264 : 0 : if (g_async_result_legacy_propagate_error (result, error))
265 : 0 : return NULL;
266 : 0 : else if (g_async_result_is_tagged (result, g_file_io_stream_query_info_async))
267 : 0 : return g_task_propagate_pointer (G_TASK (result), error);
268 : :
269 : 0 : class = G_FILE_IO_STREAM_GET_CLASS (stream);
270 : 0 : return class->query_info_finish (stream, result, error);
271 : : }
272 : :
273 : : /**
274 : : * g_file_io_stream_get_etag:
275 : : * @stream: a #GFileIOStream.
276 : : *
277 : : * Gets the entity tag for the file when it has been written.
278 : : * This must be called after the stream has been written
279 : : * and closed, as the etag can change while writing.
280 : : *
281 : : * Returns: (nullable) (transfer full): the entity tag for the stream.
282 : : *
283 : : * Since: 2.22
284 : : **/
285 : : char *
286 : 0 : g_file_io_stream_get_etag (GFileIOStream *stream)
287 : : {
288 : : GFileIOStreamClass *class;
289 : : GIOStream *io_stream;
290 : : char *etag;
291 : :
292 : 0 : g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), NULL);
293 : :
294 : 0 : io_stream = G_IO_STREAM (stream);
295 : :
296 : 0 : if (!g_io_stream_is_closed (io_stream))
297 : : {
298 : 0 : g_warning ("stream is not closed yet, can't get etag");
299 : 0 : return NULL;
300 : : }
301 : :
302 : 0 : etag = NULL;
303 : :
304 : 0 : class = G_FILE_IO_STREAM_GET_CLASS (stream);
305 : 0 : if (class->get_etag)
306 : 0 : etag = class->get_etag (stream);
307 : :
308 : 0 : return etag;
309 : : }
310 : :
311 : : static goffset
312 : 33 : g_file_io_stream_tell (GFileIOStream *stream)
313 : : {
314 : : GFileIOStreamClass *class;
315 : : goffset offset;
316 : :
317 : 33 : g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), 0);
318 : :
319 : 33 : class = G_FILE_IO_STREAM_GET_CLASS (stream);
320 : :
321 : 33 : offset = 0;
322 : 33 : if (class->tell)
323 : 33 : offset = class->tell (stream);
324 : :
325 : 33 : return offset;
326 : : }
327 : :
328 : : static goffset
329 : 33 : g_file_io_stream_seekable_tell (GSeekable *seekable)
330 : : {
331 : 33 : return g_file_io_stream_tell (G_FILE_IO_STREAM (seekable));
332 : : }
333 : :
334 : : static gboolean
335 : 0 : g_file_io_stream_can_seek (GFileIOStream *stream)
336 : : {
337 : : GFileIOStreamClass *class;
338 : : gboolean can_seek;
339 : :
340 : 0 : g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), FALSE);
341 : :
342 : 0 : class = G_FILE_IO_STREAM_GET_CLASS (stream);
343 : :
344 : 0 : can_seek = FALSE;
345 : 0 : if (class->seek)
346 : : {
347 : 0 : can_seek = TRUE;
348 : 0 : if (class->can_seek)
349 : 0 : can_seek = class->can_seek (stream);
350 : : }
351 : :
352 : 0 : return can_seek;
353 : : }
354 : :
355 : : static gboolean
356 : 0 : g_file_io_stream_seekable_can_seek (GSeekable *seekable)
357 : : {
358 : 0 : return g_file_io_stream_can_seek (G_FILE_IO_STREAM (seekable));
359 : : }
360 : :
361 : : static gboolean
362 : 17 : g_file_io_stream_seek (GFileIOStream *stream,
363 : : goffset offset,
364 : : GSeekType type,
365 : : GCancellable *cancellable,
366 : : GError **error)
367 : : {
368 : : GFileIOStreamClass *class;
369 : : GIOStream *io_stream;
370 : : gboolean res;
371 : :
372 : 17 : g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), FALSE);
373 : :
374 : 17 : io_stream = G_IO_STREAM (stream);
375 : 17 : class = G_FILE_IO_STREAM_GET_CLASS (stream);
376 : :
377 : 17 : if (!class->seek)
378 : : {
379 : 0 : g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
380 : : _("Seek not supported on stream"));
381 : 0 : return FALSE;
382 : : }
383 : :
384 : 17 : if (!g_io_stream_set_pending (io_stream, error))
385 : 0 : return FALSE;
386 : :
387 : 17 : if (cancellable)
388 : 0 : g_cancellable_push_current (cancellable);
389 : :
390 : 17 : res = class->seek (stream, offset, type, cancellable, error);
391 : :
392 : 17 : if (cancellable)
393 : 0 : g_cancellable_pop_current (cancellable);
394 : :
395 : 17 : g_io_stream_clear_pending (io_stream);
396 : :
397 : 17 : return res;
398 : : }
399 : :
400 : : static gboolean
401 : 17 : g_file_io_stream_seekable_seek (GSeekable *seekable,
402 : : goffset offset,
403 : : GSeekType type,
404 : : GCancellable *cancellable,
405 : : GError **error)
406 : : {
407 : 17 : return g_file_io_stream_seek (G_FILE_IO_STREAM (seekable),
408 : : offset, type, cancellable, error);
409 : : }
410 : :
411 : : static gboolean
412 : 0 : g_file_io_stream_can_truncate (GFileIOStream *stream)
413 : : {
414 : : GFileIOStreamClass *class;
415 : : gboolean can_truncate;
416 : :
417 : 0 : g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), FALSE);
418 : :
419 : 0 : class = G_FILE_IO_STREAM_GET_CLASS (stream);
420 : :
421 : 0 : can_truncate = FALSE;
422 : 0 : if (class->truncate_fn)
423 : : {
424 : 0 : can_truncate = TRUE;
425 : 0 : if (class->can_truncate)
426 : 0 : can_truncate = class->can_truncate (stream);
427 : : }
428 : :
429 : 0 : return can_truncate;
430 : : }
431 : :
432 : : static gboolean
433 : 0 : g_file_io_stream_seekable_can_truncate (GSeekable *seekable)
434 : : {
435 : 0 : return g_file_io_stream_can_truncate (G_FILE_IO_STREAM (seekable));
436 : : }
437 : :
438 : : static gboolean
439 : 0 : g_file_io_stream_truncate (GFileIOStream *stream,
440 : : goffset size,
441 : : GCancellable *cancellable,
442 : : GError **error)
443 : : {
444 : : GFileIOStreamClass *class;
445 : : GIOStream *io_stream;
446 : : gboolean res;
447 : :
448 : 0 : g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), FALSE);
449 : :
450 : 0 : io_stream = G_IO_STREAM (stream);
451 : 0 : class = G_FILE_IO_STREAM_GET_CLASS (stream);
452 : :
453 : 0 : if (!class->truncate_fn)
454 : : {
455 : 0 : g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
456 : : _("Truncate not supported on stream"));
457 : 0 : return FALSE;
458 : : }
459 : :
460 : 0 : if (!g_io_stream_set_pending (io_stream, error))
461 : 0 : return FALSE;
462 : :
463 : 0 : if (cancellable)
464 : 0 : g_cancellable_push_current (cancellable);
465 : :
466 : 0 : res = class->truncate_fn (stream, size, cancellable, error);
467 : :
468 : 0 : if (cancellable)
469 : 0 : g_cancellable_pop_current (cancellable);
470 : :
471 : 0 : g_io_stream_clear_pending (io_stream);
472 : :
473 : 0 : return res;
474 : : }
475 : :
476 : : static gboolean
477 : 0 : g_file_io_stream_seekable_truncate (GSeekable *seekable,
478 : : goffset size,
479 : : GCancellable *cancellable,
480 : : GError **error)
481 : : {
482 : 0 : return g_file_io_stream_truncate (G_FILE_IO_STREAM (seekable),
483 : : size, cancellable, error);
484 : : }
485 : : /*****************************************************
486 : : * Default implementations based on output stream *
487 : : *****************************************************/
488 : :
489 : : static goffset
490 : 33 : g_file_io_stream_real_tell (GFileIOStream *stream)
491 : : {
492 : : GOutputStream *out;
493 : : GSeekable *seekable;
494 : :
495 : 33 : out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
496 : 33 : seekable = G_SEEKABLE (out);
497 : :
498 : 33 : return g_seekable_tell (seekable);
499 : : }
500 : :
501 : : static gboolean
502 : 0 : g_file_io_stream_real_can_seek (GFileIOStream *stream)
503 : : {
504 : : GOutputStream *out;
505 : : GSeekable *seekable;
506 : :
507 : 0 : out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
508 : 0 : seekable = G_SEEKABLE (out);
509 : :
510 : 0 : return g_seekable_can_seek (seekable);
511 : : }
512 : :
513 : : static gboolean
514 : 17 : g_file_io_stream_real_seek (GFileIOStream *stream,
515 : : goffset offset,
516 : : GSeekType type,
517 : : GCancellable *cancellable,
518 : : GError **error)
519 : : {
520 : : GOutputStream *out;
521 : : GSeekable *seekable;
522 : :
523 : 17 : out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
524 : 17 : seekable = G_SEEKABLE (out);
525 : :
526 : 17 : return g_seekable_seek (seekable, offset, type, cancellable, error);
527 : : }
528 : :
529 : : static gboolean
530 : 0 : g_file_io_stream_real_can_truncate (GFileIOStream *stream)
531 : : {
532 : : GOutputStream *out;
533 : : GSeekable *seekable;
534 : :
535 : 0 : out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
536 : 0 : seekable = G_SEEKABLE (out);
537 : :
538 : 0 : return g_seekable_can_truncate (seekable);
539 : : }
540 : :
541 : : static gboolean
542 : 0 : g_file_io_stream_real_truncate_fn (GFileIOStream *stream,
543 : : goffset size,
544 : : GCancellable *cancellable,
545 : : GError **error)
546 : : {
547 : : GOutputStream *out;
548 : : GSeekable *seekable;
549 : :
550 : 0 : out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
551 : 0 : seekable = G_SEEKABLE (out);
552 : :
553 : 0 : return g_seekable_truncate (seekable, size, cancellable, error);
554 : : }
555 : :
556 : : static char *
557 : 0 : g_file_io_stream_real_get_etag (GFileIOStream *stream)
558 : : {
559 : : GOutputStream *out;
560 : : GFileOutputStream *file_out;
561 : :
562 : 0 : out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
563 : 0 : file_out = G_FILE_OUTPUT_STREAM (out);
564 : :
565 : 0 : return g_file_output_stream_get_etag (file_out);
566 : : }
567 : :
568 : : static GFileInfo *
569 : 1 : g_file_io_stream_real_query_info (GFileIOStream *stream,
570 : : const char *attributes,
571 : : GCancellable *cancellable,
572 : : GError **error)
573 : : {
574 : : GOutputStream *out;
575 : : GFileOutputStream *file_out;
576 : :
577 : 1 : out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
578 : 1 : file_out = G_FILE_OUTPUT_STREAM (out);
579 : :
580 : 1 : return g_file_output_stream_query_info (file_out,
581 : : attributes, cancellable, error);
582 : : }
583 : :
584 : : typedef struct {
585 : : GObject *object;
586 : : GAsyncReadyCallback callback;
587 : : gpointer user_data;
588 : : } AsyncOpWrapper;
589 : :
590 : : static AsyncOpWrapper *
591 : 0 : async_op_wrapper_new (gpointer object,
592 : : GAsyncReadyCallback callback,
593 : : gpointer user_data)
594 : : {
595 : : AsyncOpWrapper *data;
596 : :
597 : 0 : data = g_new0 (AsyncOpWrapper, 1);
598 : 0 : data->object = g_object_ref (object);
599 : 0 : data->callback = callback;
600 : 0 : data->user_data = user_data;
601 : :
602 : 0 : return data;
603 : : }
604 : :
605 : : static void
606 : 0 : async_op_wrapper_callback (GObject *source_object,
607 : : GAsyncResult *res,
608 : : gpointer user_data)
609 : : {
610 : 0 : AsyncOpWrapper *data = user_data;
611 : 0 : data->callback (data->object, res, data->user_data);
612 : 0 : g_object_unref (data->object);
613 : 0 : g_free (data);
614 : 0 : }
615 : :
616 : : static void
617 : 0 : g_file_io_stream_real_query_info_async (GFileIOStream *stream,
618 : : const char *attributes,
619 : : int io_priority,
620 : : GCancellable *cancellable,
621 : : GAsyncReadyCallback callback,
622 : : gpointer user_data)
623 : : {
624 : : GOutputStream *out;
625 : : GFileOutputStream *file_out;
626 : : AsyncOpWrapper *data;
627 : :
628 : 0 : out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
629 : 0 : file_out = G_FILE_OUTPUT_STREAM (out);
630 : :
631 : 0 : data = async_op_wrapper_new (stream, callback, user_data);
632 : 0 : g_file_output_stream_query_info_async (file_out,
633 : : attributes, io_priority,
634 : : cancellable, async_op_wrapper_callback, data);
635 : 0 : }
636 : :
637 : : static GFileInfo *
638 : 0 : g_file_io_stream_real_query_info_finish (GFileIOStream *stream,
639 : : GAsyncResult *res,
640 : : GError **error)
641 : : {
642 : : GOutputStream *out;
643 : : GFileOutputStream *file_out;
644 : :
645 : 0 : out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
646 : 0 : file_out = G_FILE_OUTPUT_STREAM (out);
647 : :
648 : 0 : return g_file_output_stream_query_info_finish (file_out, res, error);
649 : : }
650 : :
651 : : static void
652 : 8 : g_file_io_stream_class_init (GFileIOStreamClass *klass)
653 : : {
654 : 8 : klass->tell = g_file_io_stream_real_tell;
655 : 8 : klass->can_seek = g_file_io_stream_real_can_seek;
656 : 8 : klass->seek = g_file_io_stream_real_seek;
657 : 8 : klass->can_truncate = g_file_io_stream_real_can_truncate;
658 : 8 : klass->truncate_fn = g_file_io_stream_real_truncate_fn;
659 : 8 : klass->query_info = g_file_io_stream_real_query_info;
660 : 8 : klass->query_info_async = g_file_io_stream_real_query_info_async;
661 : 8 : klass->query_info_finish = g_file_io_stream_real_query_info_finish;
662 : 8 : klass->get_etag = g_file_io_stream_real_get_etag;
663 : 8 : }
|