• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 
3 /* GIO - GLib Input, Output and Streaming Library
4  *
5  * Copyright (C) 2006-2007 Red Hat, Inc.
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 #ifdef __linux__
26 #include <sys/ioctl.h>
27 #include <errno.h>
28 /* See linux.git/fs/btrfs/ioctl.h */
29 #define BTRFS_IOCTL_MAGIC 0x94
30 #define BTRFS_IOC_CLONE _IOW(BTRFS_IOCTL_MAGIC, 9, int)
31 #endif
32 
33 #ifdef HAVE_SPLICE
34 #include <sys/stat.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 
39 /*
40  * We duplicate the following Linux kernel header defines here so we can still
41  * run at full speed on modern kernels in cases where an old toolchain was used
42  * to build GLib. This is often done deliberately to allow shipping binaries
43  * that need to run on a wide range of systems.
44  */
45 #ifndef F_SETPIPE_SZ
46 #define F_SETPIPE_SZ 1031
47 #endif
48 #ifndef F_GETPIPE_SZ
49 #define F_GETPIPE_SZ 1032
50 #endif
51 
52 #endif
53 
54 #include <string.h>
55 #include <sys/types.h>
56 
57 #include "gfile.h"
58 #include "glib/gstdio.h"
59 #ifdef G_OS_UNIX
60 #include "glib-unix.h"
61 #endif
62 #include "gvfs.h"
63 #include "gtask.h"
64 #include "gfileattribute-priv.h"
65 #include "gfiledescriptorbased.h"
66 #include "gpollfilemonitor.h"
67 #include "gappinfo.h"
68 #include "gfileinputstream.h"
69 #include "gfileoutputstream.h"
70 #include "glocalfileoutputstream.h"
71 #include "glocalfileiostream.h"
72 #include "glocalfile.h"
73 #include "gcancellable.h"
74 #include "gasyncresult.h"
75 #include "gioerror.h"
76 #include "glibintl.h"
77 
78 
79 /**
80  * SECTION:gfile
81  * @short_description: File and Directory Handling
82  * @include: gio/gio.h
83  * @see_also: #GFileInfo, #GFileEnumerator
84  *
85  * #GFile is a high level abstraction for manipulating files on a
86  * virtual file system. #GFiles are lightweight, immutable objects
87  * that do no I/O upon creation. It is necessary to understand that
88  * #GFile objects do not represent files, merely an identifier for a
89  * file. All file content I/O is implemented as streaming operations
90  * (see #GInputStream and #GOutputStream).
91  *
92  * To construct a #GFile, you can use:
93  * - g_file_new_for_path() if you have a path.
94  * - g_file_new_for_uri() if you have a URI.
95  * - g_file_new_for_commandline_arg() for a command line argument.
96  * - g_file_new_tmp() to create a temporary file from a template.
97  * - g_file_parse_name() from a UTF-8 string gotten from g_file_get_parse_name().
98  * - g_file_new_build_filename() to create a file from path elements.
99  *
100  * One way to think of a #GFile is as an abstraction of a pathname. For
101  * normal files the system pathname is what is stored internally, but as
102  * #GFiles are extensible it could also be something else that corresponds
103  * to a pathname in a userspace implementation of a filesystem.
104  *
105  * #GFiles make up hierarchies of directories and files that correspond to
106  * the files on a filesystem. You can move through the file system with
107  * #GFile using g_file_get_parent() to get an identifier for the parent
108  * directory, g_file_get_child() to get a child within a directory,
109  * g_file_resolve_relative_path() to resolve a relative path between two
110  * #GFiles. There can be multiple hierarchies, so you may not end up at
111  * the same root if you repeatedly call g_file_get_parent() on two different
112  * files.
113  *
114  * All #GFiles have a basename (get with g_file_get_basename()). These names
115  * are byte strings that are used to identify the file on the filesystem
116  * (relative to its parent directory) and there is no guarantees that they
117  * have any particular charset encoding or even make any sense at all. If
118  * you want to use filenames in a user interface you should use the display
119  * name that you can get by requesting the
120  * %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME attribute with g_file_query_info().
121  * This is guaranteed to be in UTF-8 and can be used in a user interface.
122  * But always store the real basename or the #GFile to use to actually
123  * access the file, because there is no way to go from a display name to
124  * the actual name.
125  *
126  * Using #GFile as an identifier has the same weaknesses as using a path
127  * in that there may be multiple aliases for the same file. For instance,
128  * hard or soft links may cause two different #GFiles to refer to the same
129  * file. Other possible causes for aliases are: case insensitive filesystems,
130  * short and long names on FAT/NTFS, or bind mounts in Linux. If you want to
131  * check if two #GFiles point to the same file you can query for the
132  * %G_FILE_ATTRIBUTE_ID_FILE attribute. Note that #GFile does some trivial
133  * canonicalization of pathnames passed in, so that trivial differences in
134  * the path string used at creation (duplicated slashes, slash at end of
135  * path, "." or ".." path segments, etc) does not create different #GFiles.
136  *
137  * Many #GFile operations have both synchronous and asynchronous versions
138  * to suit your application. Asynchronous versions of synchronous functions
139  * simply have _async() appended to their function names. The asynchronous
140  * I/O functions call a #GAsyncReadyCallback which is then used to finalize
141  * the operation, producing a GAsyncResult which is then passed to the
142  * function's matching _finish() operation.
143  *
144  * It is highly recommended to use asynchronous calls when running within a
145  * shared main loop, such as in the main thread of an application. This avoids
146  * I/O operations blocking other sources on the main loop from being dispatched.
147  * Synchronous I/O operations should be performed from worker threads. See the
148  * [introduction to asynchronous programming section][async-programming] for
149  * more.
150  *
151  * Some #GFile operations almost always take a noticeable amount of time, and
152  * so do not have synchronous analogs. Notable cases include:
153  * - g_file_mount_mountable() to mount a mountable file.
154  * - g_file_unmount_mountable_with_operation() to unmount a mountable file.
155  * - g_file_eject_mountable_with_operation() to eject a mountable file.
156  *
157  * ## Entity Tags # {#gfile-etag}
158  *
159  * One notable feature of #GFiles are entity tags, or "etags" for
160  * short. Entity tags are somewhat like a more abstract version of the
161  * traditional mtime, and can be used to quickly determine if the file
162  * has been modified from the version on the file system. See the
163  * HTTP 1.1
164  * [specification](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html)
165  * for HTTP Etag headers, which are a very similar concept.
166  */
167 
168 static void               g_file_real_query_info_async            (GFile                  *file,
169                                                                    const char             *attributes,
170                                                                    GFileQueryInfoFlags     flags,
171                                                                    int                     io_priority,
172                                                                    GCancellable           *cancellable,
173                                                                    GAsyncReadyCallback     callback,
174                                                                    gpointer                user_data);
175 static GFileInfo *        g_file_real_query_info_finish           (GFile                  *file,
176                                                                    GAsyncResult           *res,
177                                                                    GError                **error);
178 static void               g_file_real_query_filesystem_info_async (GFile                  *file,
179                                                                    const char             *attributes,
180                                                                    int                     io_priority,
181                                                                    GCancellable           *cancellable,
182                                                                    GAsyncReadyCallback     callback,
183                                                                    gpointer                user_data);
184 static GFileInfo *        g_file_real_query_filesystem_info_finish (GFile                  *file,
185                                                                    GAsyncResult           *res,
186                                                                    GError                **error);
187 static void               g_file_real_enumerate_children_async    (GFile                  *file,
188                                                                    const char             *attributes,
189                                                                    GFileQueryInfoFlags     flags,
190                                                                    int                     io_priority,
191                                                                    GCancellable           *cancellable,
192                                                                    GAsyncReadyCallback     callback,
193                                                                    gpointer                user_data);
194 static GFileEnumerator *  g_file_real_enumerate_children_finish   (GFile                  *file,
195                                                                    GAsyncResult           *res,
196                                                                    GError                **error);
197 static void               g_file_real_read_async                  (GFile                  *file,
198                                                                    int                     io_priority,
199                                                                    GCancellable           *cancellable,
200                                                                    GAsyncReadyCallback     callback,
201                                                                    gpointer                user_data);
202 static GFileInputStream * g_file_real_read_finish                 (GFile                  *file,
203                                                                    GAsyncResult           *res,
204                                                                    GError                **error);
205 static void               g_file_real_append_to_async             (GFile                  *file,
206                                                                    GFileCreateFlags        flags,
207                                                                    int                     io_priority,
208                                                                    GCancellable           *cancellable,
209                                                                    GAsyncReadyCallback     callback,
210                                                                    gpointer                user_data);
211 static GFileOutputStream *g_file_real_append_to_finish            (GFile                  *file,
212                                                                    GAsyncResult           *res,
213                                                                    GError                **error);
214 static void               g_file_real_create_async                (GFile                  *file,
215                                                                    GFileCreateFlags        flags,
216                                                                    int                     io_priority,
217                                                                    GCancellable           *cancellable,
218                                                                    GAsyncReadyCallback     callback,
219                                                                    gpointer                user_data);
220 static GFileOutputStream *g_file_real_create_finish               (GFile                  *file,
221                                                                    GAsyncResult           *res,
222                                                                    GError                **error);
223 static void               g_file_real_replace_async               (GFile                  *file,
224                                                                    const char             *etag,
225                                                                    gboolean                make_backup,
226                                                                    GFileCreateFlags        flags,
227                                                                    int                     io_priority,
228                                                                    GCancellable           *cancellable,
229                                                                    GAsyncReadyCallback     callback,
230                                                                    gpointer                user_data);
231 static GFileOutputStream *g_file_real_replace_finish              (GFile                  *file,
232                                                                    GAsyncResult           *res,
233                                                                    GError                **error);
234 static void               g_file_real_delete_async                (GFile                  *file,
235                                                                    int                     io_priority,
236                                                                    GCancellable           *cancellable,
237                                                                    GAsyncReadyCallback     callback,
238                                                                    gpointer                user_data);
239 static gboolean           g_file_real_delete_finish               (GFile                  *file,
240                                                                    GAsyncResult           *res,
241                                                                    GError                **error);
242 static void               g_file_real_trash_async                 (GFile                  *file,
243                                                                    int                     io_priority,
244                                                                    GCancellable           *cancellable,
245                                                                    GAsyncReadyCallback     callback,
246                                                                    gpointer                user_data);
247 static gboolean           g_file_real_trash_finish                (GFile                  *file,
248                                                                    GAsyncResult           *res,
249                                                                    GError                **error);
250 static void               g_file_real_make_directory_async        (GFile                  *file,
251                                                                    int                     io_priority,
252                                                                    GCancellable           *cancellable,
253                                                                    GAsyncReadyCallback     callback,
254                                                                    gpointer                user_data);
255 static gboolean           g_file_real_make_directory_finish       (GFile                  *file,
256                                                                    GAsyncResult           *res,
257                                                                    GError                **error);
258 static void               g_file_real_open_readwrite_async        (GFile                  *file,
259                                                                    int                  io_priority,
260                                                                    GCancellable           *cancellable,
261                                                                    GAsyncReadyCallback     callback,
262                                                                    gpointer                user_data);
263 static GFileIOStream *    g_file_real_open_readwrite_finish       (GFile                  *file,
264                                                                    GAsyncResult           *res,
265                                                                    GError                **error);
266 static void               g_file_real_create_readwrite_async      (GFile                  *file,
267                                                                    GFileCreateFlags        flags,
268                                                                    int                     io_priority,
269                                                                    GCancellable           *cancellable,
270                                                                    GAsyncReadyCallback     callback,
271                                                                    gpointer                user_data);
272 static GFileIOStream *    g_file_real_create_readwrite_finish     (GFile                  *file,
273                                                                    GAsyncResult           *res,
274                                                                    GError                **error);
275 static void               g_file_real_replace_readwrite_async     (GFile                  *file,
276                                                                    const char             *etag,
277                                                                    gboolean                make_backup,
278                                                                    GFileCreateFlags        flags,
279                                                                    int                     io_priority,
280                                                                    GCancellable           *cancellable,
281                                                                    GAsyncReadyCallback     callback,
282                                                                    gpointer                user_data);
283 static GFileIOStream *    g_file_real_replace_readwrite_finish    (GFile                  *file,
284                                                                   GAsyncResult            *res,
285                                                                   GError                 **error);
286 static gboolean           g_file_real_set_attributes_from_info    (GFile                  *file,
287                                                                    GFileInfo              *info,
288                                                                    GFileQueryInfoFlags     flags,
289                                                                    GCancellable           *cancellable,
290                                                                    GError                **error);
291 static void               g_file_real_set_display_name_async      (GFile                  *file,
292                                                                    const char             *display_name,
293                                                                    int                     io_priority,
294                                                                    GCancellable           *cancellable,
295                                                                    GAsyncReadyCallback     callback,
296                                                                    gpointer                user_data);
297 static GFile *            g_file_real_set_display_name_finish     (GFile                  *file,
298                                                                    GAsyncResult           *res,
299                                                                    GError                **error);
300 static void               g_file_real_set_attributes_async        (GFile                  *file,
301                                                                    GFileInfo              *info,
302                                                                    GFileQueryInfoFlags     flags,
303                                                                    int                     io_priority,
304                                                                    GCancellable           *cancellable,
305                                                                    GAsyncReadyCallback     callback,
306                                                                    gpointer                user_data);
307 static gboolean           g_file_real_set_attributes_finish       (GFile                  *file,
308                                                                    GAsyncResult           *res,
309                                                                    GFileInfo             **info,
310                                                                    GError                **error);
311 static void               g_file_real_find_enclosing_mount_async  (GFile                  *file,
312                                                                    int                     io_priority,
313                                                                    GCancellable           *cancellable,
314                                                                    GAsyncReadyCallback     callback,
315                                                                    gpointer                user_data);
316 static GMount *           g_file_real_find_enclosing_mount_finish (GFile                  *file,
317                                                                    GAsyncResult           *res,
318                                                                    GError                **error);
319 static void               g_file_real_copy_async                  (GFile                  *source,
320                                                                    GFile                  *destination,
321                                                                    GFileCopyFlags          flags,
322                                                                    int                     io_priority,
323                                                                    GCancellable           *cancellable,
324                                                                    GFileProgressCallback   progress_callback,
325                                                                    gpointer                progress_callback_data,
326                                                                    GAsyncReadyCallback     callback,
327                                                                    gpointer                user_data);
328 static gboolean           g_file_real_copy_finish                 (GFile                  *file,
329                                                                    GAsyncResult           *res,
330                                                                    GError                **error);
331 
332 static gboolean           g_file_real_measure_disk_usage          (GFile                         *file,
333                                                                    GFileMeasureFlags              flags,
334                                                                    GCancellable                  *cancellable,
335                                                                    GFileMeasureProgressCallback   progress_callback,
336                                                                    gpointer                       progress_data,
337                                                                    guint64                       *disk_usage,
338                                                                    guint64                       *num_dirs,
339                                                                    guint64                       *num_files,
340                                                                    GError                       **error);
341 static void               g_file_real_measure_disk_usage_async    (GFile                         *file,
342                                                                    GFileMeasureFlags              flags,
343                                                                    gint                           io_priority,
344                                                                    GCancellable                  *cancellable,
345                                                                    GFileMeasureProgressCallback   progress_callback,
346                                                                    gpointer                       progress_data,
347                                                                    GAsyncReadyCallback            callback,
348                                                                    gpointer                       user_data);
349 static gboolean           g_file_real_measure_disk_usage_finish   (GFile                         *file,
350                                                                    GAsyncResult                  *result,
351                                                                    guint64                       *disk_usage,
352                                                                    guint64                       *num_dirs,
353                                                                    guint64                       *num_files,
354                                                                    GError                       **error);
355 
356 typedef GFileIface GFileInterface;
G_DEFINE_INTERFACE(GFile,g_file,G_TYPE_OBJECT)357 G_DEFINE_INTERFACE (GFile, g_file, G_TYPE_OBJECT)
358 
359 static void
360 g_file_default_init (GFileIface *iface)
361 {
362   iface->enumerate_children_async = g_file_real_enumerate_children_async;
363   iface->enumerate_children_finish = g_file_real_enumerate_children_finish;
364   iface->set_display_name_async = g_file_real_set_display_name_async;
365   iface->set_display_name_finish = g_file_real_set_display_name_finish;
366   iface->query_info_async = g_file_real_query_info_async;
367   iface->query_info_finish = g_file_real_query_info_finish;
368   iface->query_filesystem_info_async = g_file_real_query_filesystem_info_async;
369   iface->query_filesystem_info_finish = g_file_real_query_filesystem_info_finish;
370   iface->set_attributes_async = g_file_real_set_attributes_async;
371   iface->set_attributes_finish = g_file_real_set_attributes_finish;
372   iface->read_async = g_file_real_read_async;
373   iface->read_finish = g_file_real_read_finish;
374   iface->append_to_async = g_file_real_append_to_async;
375   iface->append_to_finish = g_file_real_append_to_finish;
376   iface->create_async = g_file_real_create_async;
377   iface->create_finish = g_file_real_create_finish;
378   iface->replace_async = g_file_real_replace_async;
379   iface->replace_finish = g_file_real_replace_finish;
380   iface->delete_file_async = g_file_real_delete_async;
381   iface->delete_file_finish = g_file_real_delete_finish;
382   iface->trash_async = g_file_real_trash_async;
383   iface->trash_finish = g_file_real_trash_finish;
384   iface->make_directory_async = g_file_real_make_directory_async;
385   iface->make_directory_finish = g_file_real_make_directory_finish;
386   iface->open_readwrite_async = g_file_real_open_readwrite_async;
387   iface->open_readwrite_finish = g_file_real_open_readwrite_finish;
388   iface->create_readwrite_async = g_file_real_create_readwrite_async;
389   iface->create_readwrite_finish = g_file_real_create_readwrite_finish;
390   iface->replace_readwrite_async = g_file_real_replace_readwrite_async;
391   iface->replace_readwrite_finish = g_file_real_replace_readwrite_finish;
392   iface->find_enclosing_mount_async = g_file_real_find_enclosing_mount_async;
393   iface->find_enclosing_mount_finish = g_file_real_find_enclosing_mount_finish;
394   iface->set_attributes_from_info = g_file_real_set_attributes_from_info;
395   iface->copy_async = g_file_real_copy_async;
396   iface->copy_finish = g_file_real_copy_finish;
397   iface->measure_disk_usage = g_file_real_measure_disk_usage;
398   iface->measure_disk_usage_async = g_file_real_measure_disk_usage_async;
399   iface->measure_disk_usage_finish = g_file_real_measure_disk_usage_finish;
400 }
401 
402 
403 /**
404  * g_file_is_native:
405  * @file: input #GFile
406  *
407  * Checks to see if a file is native to the platform.
408  *
409  * A native file is one expressed in the platform-native filename format,
410  * e.g. "C:\Windows" or "/usr/bin/". This does not mean the file is local,
411  * as it might be on a locally mounted remote filesystem.
412  *
413  * On some systems non-native files may be available using the native
414  * filesystem via a userspace filesystem (FUSE), in these cases this call
415  * will return %FALSE, but g_file_get_path() will still return a native path.
416  *
417  * This call does no blocking I/O.
418  *
419  * Returns: %TRUE if @file is native
420  */
421 gboolean
g_file_is_native(GFile * file)422 g_file_is_native (GFile *file)
423 {
424   GFileIface *iface;
425 
426   g_return_val_if_fail (G_IS_FILE (file), FALSE);
427 
428   iface = G_FILE_GET_IFACE (file);
429 
430   return (* iface->is_native) (file);
431 }
432 
433 
434 /**
435  * g_file_has_uri_scheme:
436  * @file: input #GFile
437  * @uri_scheme: a string containing a URI scheme
438  *
439  * Checks to see if a #GFile has a given URI scheme.
440  *
441  * This call does no blocking I/O.
442  *
443  * Returns: %TRUE if #GFile's backend supports the
444  *     given URI scheme, %FALSE if URI scheme is %NULL,
445  *     not supported, or #GFile is invalid.
446  */
447 gboolean
g_file_has_uri_scheme(GFile * file,const char * uri_scheme)448 g_file_has_uri_scheme (GFile      *file,
449                        const char *uri_scheme)
450 {
451   GFileIface *iface;
452 
453   g_return_val_if_fail (G_IS_FILE (file), FALSE);
454   g_return_val_if_fail (uri_scheme != NULL, FALSE);
455 
456   iface = G_FILE_GET_IFACE (file);
457 
458   return (* iface->has_uri_scheme) (file, uri_scheme);
459 }
460 
461 
462 /**
463  * g_file_get_uri_scheme:
464  * @file: input #GFile
465  *
466  * Gets the URI scheme for a #GFile.
467  * RFC 3986 decodes the scheme as:
468  * |[
469  * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
470  * ]|
471  * Common schemes include "file", "http", "ftp", etc.
472  *
473  * The scheme can be different from the one used to construct the #GFile,
474  * in that it might be replaced with one that is logically equivalent to the #GFile.
475  *
476  * This call does no blocking I/O.
477  *
478  * Returns: (nullable): a string containing the URI scheme for the given
479  *     #GFile or %NULL if the #GFile was constructed with an invalid URI. The
480  *     returned string should be freed with g_free() when no longer needed.
481  */
482 char *
g_file_get_uri_scheme(GFile * file)483 g_file_get_uri_scheme (GFile *file)
484 {
485   GFileIface *iface;
486 
487   g_return_val_if_fail (G_IS_FILE (file), NULL);
488 
489   iface = G_FILE_GET_IFACE (file);
490 
491   return (* iface->get_uri_scheme) (file);
492 }
493 
494 
495 /**
496  * g_file_get_basename: (virtual get_basename)
497  * @file: input #GFile
498  *
499  * Gets the base name (the last component of the path) for a given #GFile.
500  *
501  * If called for the top level of a system (such as the filesystem root
502  * or a uri like sftp://host/) it will return a single directory separator
503  * (and on Windows, possibly a drive letter).
504  *
505  * The base name is a byte string (not UTF-8). It has no defined encoding
506  * or rules other than it may not contain zero bytes.  If you want to use
507  * filenames in a user interface you should use the display name that you
508  * can get by requesting the %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
509  * attribute with g_file_query_info().
510  *
511  * This call does no blocking I/O.
512  *
513  * Returns: (type filename) (nullable): string containing the #GFile's
514  *     base name, or %NULL if given #GFile is invalid. The returned string
515  *     should be freed with g_free() when no longer needed.
516  */
517 char *
g_file_get_basename(GFile * file)518 g_file_get_basename (GFile *file)
519 {
520   GFileIface *iface;
521 
522   g_return_val_if_fail (G_IS_FILE (file), NULL);
523 
524   iface = G_FILE_GET_IFACE (file);
525 
526   return (* iface->get_basename) (file);
527 }
528 
529 /**
530  * g_file_get_path: (virtual get_path)
531  * @file: input #GFile
532  *
533  * Gets the local pathname for #GFile, if one exists. If non-%NULL, this is
534  * guaranteed to be an absolute, canonical path. It might contain symlinks.
535  *
536  * This call does no blocking I/O.
537  *
538  * Returns: (type filename) (nullable): string containing the #GFile's path,
539  *     or %NULL if no such path exists. The returned string should be freed
540  *     with g_free() when no longer needed.
541  */
542 char *
g_file_get_path(GFile * file)543 g_file_get_path (GFile *file)
544 {
545   GFileIface *iface;
546 
547   g_return_val_if_fail (G_IS_FILE (file), NULL);
548 
549   iface = G_FILE_GET_IFACE (file);
550 
551   return (* iface->get_path) (file);
552 }
553 
554 static const char *
file_peek_path_generic(GFile * file)555 file_peek_path_generic (GFile *file)
556 {
557   const char *path;
558   static GQuark _file_path_quark = 0;
559 
560   if (G_UNLIKELY (_file_path_quark) == 0)
561     _file_path_quark = g_quark_from_static_string ("gio-file-path");
562 
563   /* We need to be careful about threading, as two threads calling
564    * g_file_peek_path() on the same file could race: both would see
565    * (g_object_get_qdata(…) == NULL) to begin with, both would generate and add
566    * the path, but the second thread to add it would end up freeing the path
567    * set by the first thread. The first thread would still return the pointer
568    * to that freed path, though, resulting an a read-after-free. Handle that
569    * with a compare-and-swap loop. The g_object_*_qdata() functions are atomic. */
570 
571   while (TRUE)
572     {
573       gchar *new_path = NULL;
574 
575       path = g_object_get_qdata ((GObject*)file, _file_path_quark);
576 
577       if (path != NULL)
578         break;
579 
580       new_path = g_file_get_path (file);
581       if (new_path == NULL)
582         return NULL;
583 
584       /* By passing NULL here, we ensure we never replace existing data: */
585       if (g_object_replace_qdata ((GObject *) file, _file_path_quark,
586                                   NULL, (gpointer) new_path,
587                                   (GDestroyNotify) g_free, NULL))
588         {
589           path = new_path;
590           break;
591         }
592       else
593         g_free (new_path);
594     }
595 
596   return path;
597 }
598 
599 /**
600  * g_file_peek_path:
601  * @file: input #GFile
602  *
603  * Exactly like g_file_get_path(), but caches the result via
604  * g_object_set_qdata_full().  This is useful for example in C
605  * applications which mix `g_file_*` APIs with native ones.  It
606  * also avoids an extra duplicated string when possible, so will be
607  * generally more efficient.
608  *
609  * This call does no blocking I/O.
610  *
611  * Returns: (type filename) (nullable): string containing the #GFile's path,
612  *     or %NULL if no such path exists. The returned string is owned by @file.
613  * Since: 2.56
614  */
615 const char *
g_file_peek_path(GFile * file)616 g_file_peek_path (GFile *file)
617 {
618   if (G_IS_LOCAL_FILE (file))
619     return _g_local_file_get_filename ((GLocalFile *) file);
620   return file_peek_path_generic (file);
621 }
622 
623 /**
624  * g_file_get_uri:
625  * @file: input #GFile
626  *
627  * Gets the URI for the @file.
628  *
629  * This call does no blocking I/O.
630  *
631  * Returns: a string containing the #GFile's URI. If the #GFile was constructed
632  *     with an invalid URI, an invalid URI is returned.
633  *     The returned string should be freed with g_free()
634  *     when no longer needed.
635  */
636 char *
g_file_get_uri(GFile * file)637 g_file_get_uri (GFile *file)
638 {
639   GFileIface *iface;
640 
641   g_return_val_if_fail (G_IS_FILE (file), NULL);
642 
643   iface = G_FILE_GET_IFACE (file);
644 
645   return (* iface->get_uri) (file);
646 }
647 
648 /**
649  * g_file_get_parse_name:
650  * @file: input #GFile
651  *
652  * Gets the parse name of the @file.
653  * A parse name is a UTF-8 string that describes the
654  * file such that one can get the #GFile back using
655  * g_file_parse_name().
656  *
657  * This is generally used to show the #GFile as a nice
658  * full-pathname kind of string in a user interface,
659  * like in a location entry.
660  *
661  * For local files with names that can safely be converted
662  * to UTF-8 the pathname is used, otherwise the IRI is used
663  * (a form of URI that allows UTF-8 characters unescaped).
664  *
665  * This call does no blocking I/O.
666  *
667  * Returns: a string containing the #GFile's parse name.
668  *     The returned string should be freed with g_free()
669  *     when no longer needed.
670  */
671 char *
g_file_get_parse_name(GFile * file)672 g_file_get_parse_name (GFile *file)
673 {
674   GFileIface *iface;
675 
676   g_return_val_if_fail (G_IS_FILE (file), NULL);
677 
678   iface = G_FILE_GET_IFACE (file);
679 
680   return (* iface->get_parse_name) (file);
681 }
682 
683 /**
684  * g_file_dup:
685  * @file: input #GFile
686  *
687  * Duplicates a #GFile handle. This operation does not duplicate
688  * the actual file or directory represented by the #GFile; see
689  * g_file_copy() if attempting to copy a file.
690  *
691  * g_file_dup() is useful when a second handle is needed to the same underlying
692  * file, for use in a separate thread (#GFile is not thread-safe). For use
693  * within the same thread, use g_object_ref() to increment the existing object’s
694  * reference count.
695  *
696  * This call does no blocking I/O.
697  *
698  * Returns: (transfer full): a new #GFile that is a duplicate
699  *     of the given #GFile.
700  */
701 GFile *
g_file_dup(GFile * file)702 g_file_dup (GFile *file)
703 {
704   GFileIface *iface;
705 
706   g_return_val_if_fail (G_IS_FILE (file), NULL);
707 
708   iface = G_FILE_GET_IFACE (file);
709 
710   return (* iface->dup) (file);
711 }
712 
713 /**
714  * g_file_hash:
715  * @file: (type GFile): #gconstpointer to a #GFile
716  *
717  * Creates a hash value for a #GFile.
718  *
719  * This call does no blocking I/O.
720  *
721  * Virtual: hash
722  * Returns: 0 if @file is not a valid #GFile, otherwise an
723  *     integer that can be used as hash value for the #GFile.
724  *     This function is intended for easily hashing a #GFile to
725  *     add to a #GHashTable or similar data structure.
726  */
727 guint
g_file_hash(gconstpointer file)728 g_file_hash (gconstpointer file)
729 {
730   GFileIface *iface;
731 
732   g_return_val_if_fail (G_IS_FILE (file), 0);
733 
734   iface = G_FILE_GET_IFACE (file);
735 
736   return (* iface->hash) ((GFile *)file);
737 }
738 
739 /**
740  * g_file_equal:
741  * @file1: the first #GFile
742  * @file2: the second #GFile
743  *
744  * Checks if the two given #GFiles refer to the same file.
745  *
746  * Note that two #GFiles that differ can still refer to the same
747  * file on the filesystem due to various forms of filename
748  * aliasing.
749  *
750  * This call does no blocking I/O.
751  *
752  * Returns: %TRUE if @file1 and @file2 are equal.
753  */
754 gboolean
g_file_equal(GFile * file1,GFile * file2)755 g_file_equal (GFile *file1,
756               GFile *file2)
757 {
758   GFileIface *iface;
759 
760   g_return_val_if_fail (G_IS_FILE (file1), FALSE);
761   g_return_val_if_fail (G_IS_FILE (file2), FALSE);
762 
763   if (file1 == file2)
764     return TRUE;
765 
766   if (G_TYPE_FROM_INSTANCE (file1) != G_TYPE_FROM_INSTANCE (file2))
767     return FALSE;
768 
769   iface = G_FILE_GET_IFACE (file1);
770 
771   return (* iface->equal) (file1, file2);
772 }
773 
774 
775 /**
776  * g_file_get_parent:
777  * @file: input #GFile
778  *
779  * Gets the parent directory for the @file.
780  * If the @file represents the root directory of the
781  * file system, then %NULL will be returned.
782  *
783  * This call does no blocking I/O.
784  *
785  * Returns: (nullable) (transfer full): a #GFile structure to the
786  *     parent of the given #GFile or %NULL if there is no parent. Free
787  *     the returned object with g_object_unref().
788  */
789 GFile *
g_file_get_parent(GFile * file)790 g_file_get_parent (GFile *file)
791 {
792   GFileIface *iface;
793 
794   g_return_val_if_fail (G_IS_FILE (file), NULL);
795 
796   iface = G_FILE_GET_IFACE (file);
797 
798   return (* iface->get_parent) (file);
799 }
800 
801 /**
802  * g_file_has_parent:
803  * @file: input #GFile
804  * @parent: (nullable): the parent to check for, or %NULL
805  *
806  * Checks if @file has a parent, and optionally, if it is @parent.
807  *
808  * If @parent is %NULL then this function returns %TRUE if @file has any
809  * parent at all.  If @parent is non-%NULL then %TRUE is only returned
810  * if @file is an immediate child of @parent.
811  *
812  * Returns: %TRUE if @file is an immediate child of @parent (or any parent in
813  *          the case that @parent is %NULL).
814  *
815  * Since: 2.24
816  */
817 gboolean
g_file_has_parent(GFile * file,GFile * parent)818 g_file_has_parent (GFile *file,
819                    GFile *parent)
820 {
821   GFile *actual_parent;
822   gboolean result;
823 
824   g_return_val_if_fail (G_IS_FILE (file), FALSE);
825   g_return_val_if_fail (parent == NULL || G_IS_FILE (parent), FALSE);
826 
827   actual_parent = g_file_get_parent (file);
828 
829   if (actual_parent != NULL)
830     {
831       if (parent != NULL)
832         result = g_file_equal (parent, actual_parent);
833       else
834         result = TRUE;
835 
836       g_object_unref (actual_parent);
837     }
838   else
839     result = FALSE;
840 
841   return result;
842 }
843 
844 /**
845  * g_file_get_child:
846  * @file: input #GFile
847  * @name: (type filename): string containing the child's basename
848  *
849  * Gets a child of @file with basename equal to @name.
850  *
851  * Note that the file with that specific name might not exist, but
852  * you can still have a #GFile that points to it. You can use this
853  * for instance to create that file.
854  *
855  * This call does no blocking I/O.
856  *
857  * Returns: (transfer full): a #GFile to a child specified by @name.
858  *     Free the returned object with g_object_unref().
859  */
860 GFile *
g_file_get_child(GFile * file,const char * name)861 g_file_get_child (GFile      *file,
862                   const char *name)
863 {
864   g_return_val_if_fail (G_IS_FILE (file), NULL);
865   g_return_val_if_fail (name != NULL, NULL);
866 
867   return g_file_resolve_relative_path (file, name);
868 }
869 
870 /**
871  * g_file_get_child_for_display_name:
872  * @file: input #GFile
873  * @display_name: string to a possible child
874  * @error: return location for an error
875  *
876  * Gets the child of @file for a given @display_name (i.e. a UTF-8
877  * version of the name). If this function fails, it returns %NULL
878  * and @error will be set. This is very useful when constructing a
879  * #GFile for a new file and the user entered the filename in the
880  * user interface, for instance when you select a directory and
881  * type a filename in the file selector.
882  *
883  * This call does no blocking I/O.
884  *
885  * Returns: (transfer full): a #GFile to the specified child, or
886  *     %NULL if the display name couldn't be converted.
887  *     Free the returned object with g_object_unref().
888  */
889 GFile *
g_file_get_child_for_display_name(GFile * file,const char * display_name,GError ** error)890 g_file_get_child_for_display_name (GFile      *file,
891                                    const char *display_name,
892                                    GError **error)
893 {
894   GFileIface *iface;
895 
896   g_return_val_if_fail (G_IS_FILE (file), NULL);
897   g_return_val_if_fail (display_name != NULL, NULL);
898 
899   iface = G_FILE_GET_IFACE (file);
900 
901   return (* iface->get_child_for_display_name) (file, display_name, error);
902 }
903 
904 /**
905  * g_file_has_prefix:
906  * @file: input #GFile
907  * @prefix: input #GFile
908  *
909  * Checks whether @file has the prefix specified by @prefix.
910  *
911  * In other words, if the names of initial elements of @file's
912  * pathname match @prefix. Only full pathname elements are matched,
913  * so a path like /foo is not considered a prefix of /foobar, only
914  * of /foo/bar.
915  *
916  * A #GFile is not a prefix of itself. If you want to check for
917  * equality, use g_file_equal().
918  *
919  * This call does no I/O, as it works purely on names. As such it can
920  * sometimes return %FALSE even if @file is inside a @prefix (from a
921  * filesystem point of view), because the prefix of @file is an alias
922  * of @prefix.
923  *
924  * Virtual: prefix_matches
925  * Returns:  %TRUE if the @file's parent, grandparent, etc is @prefix,
926  *     %FALSE otherwise.
927  */
928 gboolean
g_file_has_prefix(GFile * file,GFile * prefix)929 g_file_has_prefix (GFile *file,
930                    GFile *prefix)
931 {
932   GFileIface *iface;
933 
934   g_return_val_if_fail (G_IS_FILE (file), FALSE);
935   g_return_val_if_fail (G_IS_FILE (prefix), FALSE);
936 
937   if (G_TYPE_FROM_INSTANCE (file) != G_TYPE_FROM_INSTANCE (prefix))
938     return FALSE;
939 
940   iface = G_FILE_GET_IFACE (file);
941 
942   /* The vtable function differs in arg order since
943    * we're using the old contains_file call
944    */
945   return (* iface->prefix_matches) (prefix, file);
946 }
947 
948 /**
949  * g_file_get_relative_path: (virtual get_relative_path)
950  * @parent: input #GFile
951  * @descendant: input #GFile
952  *
953  * Gets the path for @descendant relative to @parent.
954  *
955  * This call does no blocking I/O.
956  *
957  * Returns: (type filename) (nullable): string with the relative path from
958  *     @descendant to @parent, or %NULL if @descendant doesn't have @parent as
959  *     prefix. The returned string should be freed with g_free() when
960  *     no longer needed.
961  */
962 char *
g_file_get_relative_path(GFile * parent,GFile * descendant)963 g_file_get_relative_path (GFile *parent,
964                           GFile *descendant)
965 {
966   GFileIface *iface;
967 
968   g_return_val_if_fail (G_IS_FILE (parent), NULL);
969   g_return_val_if_fail (G_IS_FILE (descendant), NULL);
970 
971   if (G_TYPE_FROM_INSTANCE (parent) != G_TYPE_FROM_INSTANCE (descendant))
972     return NULL;
973 
974   iface = G_FILE_GET_IFACE (parent);
975 
976   return (* iface->get_relative_path) (parent, descendant);
977 }
978 
979 /**
980  * g_file_resolve_relative_path:
981  * @file: input #GFile
982  * @relative_path: (type filename): a given relative path string
983  *
984  * Resolves a relative path for @file to an absolute path.
985  *
986  * This call does no blocking I/O.
987  *
988  * Returns: (transfer full): #GFile to the resolved path.
989  *     %NULL if @relative_path is %NULL or if @file is invalid.
990  *     Free the returned object with g_object_unref().
991  */
992 GFile *
g_file_resolve_relative_path(GFile * file,const char * relative_path)993 g_file_resolve_relative_path (GFile      *file,
994                               const char *relative_path)
995 {
996   GFileIface *iface;
997 
998   g_return_val_if_fail (G_IS_FILE (file), NULL);
999   g_return_val_if_fail (relative_path != NULL, NULL);
1000 
1001   iface = G_FILE_GET_IFACE (file);
1002 
1003   return (* iface->resolve_relative_path) (file, relative_path);
1004 }
1005 
1006 /**
1007  * g_file_enumerate_children:
1008  * @file: input #GFile
1009  * @attributes: an attribute query string
1010  * @flags: a set of #GFileQueryInfoFlags
1011  * @cancellable: (nullable): optional #GCancellable object,
1012  *     %NULL to ignore
1013  * @error: #GError for error reporting
1014  *
1015  * Gets the requested information about the files in a directory.
1016  * The result is a #GFileEnumerator object that will give out
1017  * #GFileInfo objects for all the files in the directory.
1018  *
1019  * The @attributes value is a string that specifies the file
1020  * attributes that should be gathered. It is not an error if
1021  * it's not possible to read a particular requested attribute
1022  * from a file - it just won't be set. @attributes should
1023  * be a comma-separated list of attributes or attribute wildcards.
1024  * The wildcard "*" means all attributes, and a wildcard like
1025  * "standard::*" means all attributes in the standard namespace.
1026  * An example attribute query be "standard::*,owner::user".
1027  * The standard attributes are available as defines, like
1028  * #G_FILE_ATTRIBUTE_STANDARD_NAME.
1029  *
1030  * If @cancellable is not %NULL, then the operation can be cancelled
1031  * by triggering the cancellable object from another thread. If the
1032  * operation was cancelled, the error %G_IO_ERROR_CANCELLED will be
1033  * returned.
1034  *
1035  * If the file does not exist, the %G_IO_ERROR_NOT_FOUND error will
1036  * be returned. If the file is not a directory, the %G_IO_ERROR_NOT_DIRECTORY
1037  * error will be returned. Other errors are possible too.
1038  *
1039  * Returns: (transfer full): A #GFileEnumerator if successful,
1040  *     %NULL on error. Free the returned object with g_object_unref().
1041  */
1042 GFileEnumerator *
g_file_enumerate_children(GFile * file,const char * attributes,GFileQueryInfoFlags flags,GCancellable * cancellable,GError ** error)1043 g_file_enumerate_children (GFile                *file,
1044                            const char           *attributes,
1045                            GFileQueryInfoFlags   flags,
1046                            GCancellable         *cancellable,
1047                            GError              **error)
1048 {
1049   GFileIface *iface;
1050 
1051   g_return_val_if_fail (G_IS_FILE (file), NULL);
1052 
1053   if (g_cancellable_set_error_if_cancelled (cancellable, error))
1054     return NULL;
1055 
1056   iface = G_FILE_GET_IFACE (file);
1057 
1058   if (iface->enumerate_children == NULL)
1059     {
1060       g_set_error_literal (error, G_IO_ERROR,
1061                            G_IO_ERROR_NOT_SUPPORTED,
1062                            _("Operation not supported"));
1063       return NULL;
1064     }
1065 
1066   return (* iface->enumerate_children) (file, attributes, flags,
1067                                         cancellable, error);
1068 }
1069 
1070 /**
1071  * g_file_enumerate_children_async:
1072  * @file: input #GFile
1073  * @attributes: an attribute query string
1074  * @flags: a set of #GFileQueryInfoFlags
1075  * @io_priority: the [I/O priority][io-priority] of the request
1076  * @cancellable: (nullable): optional #GCancellable object,
1077  *     %NULL to ignore
1078  * @callback: (scope async): a #GAsyncReadyCallback to call when the
1079  *     request is satisfied
1080  * @user_data: (closure): the data to pass to callback function
1081  *
1082  * Asynchronously gets the requested information about the files
1083  * in a directory. The result is a #GFileEnumerator object that will
1084  * give out #GFileInfo objects for all the files in the directory.
1085  *
1086  * For more details, see g_file_enumerate_children() which is
1087  * the synchronous version of this call.
1088  *
1089  * When the operation is finished, @callback will be called. You can
1090  * then call g_file_enumerate_children_finish() to get the result of
1091  * the operation.
1092  */
1093 void
g_file_enumerate_children_async(GFile * file,const char * attributes,GFileQueryInfoFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1094 g_file_enumerate_children_async (GFile               *file,
1095                                  const char          *attributes,
1096                                  GFileQueryInfoFlags  flags,
1097                                  int                  io_priority,
1098                                  GCancellable        *cancellable,
1099                                  GAsyncReadyCallback  callback,
1100                                  gpointer             user_data)
1101 {
1102   GFileIface *iface;
1103 
1104   g_return_if_fail (G_IS_FILE (file));
1105 
1106   iface = G_FILE_GET_IFACE (file);
1107   (* iface->enumerate_children_async) (file,
1108                                        attributes,
1109                                        flags,
1110                                        io_priority,
1111                                        cancellable,
1112                                        callback,
1113                                        user_data);
1114 }
1115 
1116 /**
1117  * g_file_enumerate_children_finish:
1118  * @file: input #GFile
1119  * @res: a #GAsyncResult
1120  * @error: a #GError
1121  *
1122  * Finishes an async enumerate children operation.
1123  * See g_file_enumerate_children_async().
1124  *
1125  * Returns: (transfer full): a #GFileEnumerator or %NULL
1126  *     if an error occurred.
1127  *     Free the returned object with g_object_unref().
1128  */
1129 GFileEnumerator *
g_file_enumerate_children_finish(GFile * file,GAsyncResult * res,GError ** error)1130 g_file_enumerate_children_finish (GFile         *file,
1131                                   GAsyncResult  *res,
1132                                   GError       **error)
1133 {
1134   GFileIface *iface;
1135 
1136   g_return_val_if_fail (G_IS_FILE (file), NULL);
1137   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
1138 
1139   if (g_async_result_legacy_propagate_error (res, error))
1140     return NULL;
1141 
1142   iface = G_FILE_GET_IFACE (file);
1143   return (* iface->enumerate_children_finish) (file, res, error);
1144 }
1145 
1146 /**
1147  * g_file_query_exists:
1148  * @file: input #GFile
1149  * @cancellable: (nullable): optional #GCancellable object,
1150  *     %NULL to ignore
1151  *
1152  * Utility function to check if a particular file exists. This is
1153  * implemented using g_file_query_info() and as such does blocking I/O.
1154  *
1155  * Note that in many cases it is [racy to first check for file existence](https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use)
1156  * and then execute something based on the outcome of that, because the
1157  * file might have been created or removed in between the operations. The
1158  * general approach to handling that is to not check, but just do the
1159  * operation and handle the errors as they come.
1160  *
1161  * As an example of race-free checking, take the case of reading a file,
1162  * and if it doesn't exist, creating it. There are two racy versions: read
1163  * it, and on error create it; and: check if it exists, if not create it.
1164  * These can both result in two processes creating the file (with perhaps
1165  * a partially written file as the result). The correct approach is to
1166  * always try to create the file with g_file_create() which will either
1167  * atomically create the file or fail with a %G_IO_ERROR_EXISTS error.
1168  *
1169  * However, in many cases an existence check is useful in a user interface,
1170  * for instance to make a menu item sensitive/insensitive, so that you don't
1171  * have to fool users that something is possible and then just show an error
1172  * dialog. If you do this, you should make sure to also handle the errors
1173  * that can happen due to races when you execute the operation.
1174  *
1175  * Returns: %TRUE if the file exists (and can be detected without error),
1176  *     %FALSE otherwise (or if cancelled).
1177  */
1178 gboolean
g_file_query_exists(GFile * file,GCancellable * cancellable)1179 g_file_query_exists (GFile        *file,
1180                      GCancellable *cancellable)
1181 {
1182   GFileInfo *info;
1183 
1184   g_return_val_if_fail (G_IS_FILE(file), FALSE);
1185 
1186   info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE,
1187                             G_FILE_QUERY_INFO_NONE, cancellable, NULL);
1188   if (info != NULL)
1189     {
1190       g_object_unref (info);
1191       return TRUE;
1192     }
1193 
1194   return FALSE;
1195 }
1196 
1197 /**
1198  * g_file_query_file_type:
1199  * @file: input #GFile
1200  * @flags: a set of #GFileQueryInfoFlags passed to g_file_query_info()
1201  * @cancellable: (nullable): optional #GCancellable object,
1202  *     %NULL to ignore
1203  *
1204  * Utility function to inspect the #GFileType of a file. This is
1205  * implemented using g_file_query_info() and as such does blocking I/O.
1206  *
1207  * The primary use case of this method is to check if a file is
1208  * a regular file, directory, or symlink.
1209  *
1210  * Returns: The #GFileType of the file and #G_FILE_TYPE_UNKNOWN
1211  *     if the file does not exist
1212  *
1213  * Since: 2.18
1214  */
1215 GFileType
g_file_query_file_type(GFile * file,GFileQueryInfoFlags flags,GCancellable * cancellable)1216 g_file_query_file_type (GFile               *file,
1217                         GFileQueryInfoFlags  flags,
1218                         GCancellable        *cancellable)
1219 {
1220   GFileInfo *info;
1221   GFileType file_type;
1222 
1223   g_return_val_if_fail (G_IS_FILE(file), G_FILE_TYPE_UNKNOWN);
1224   info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, flags,
1225                             cancellable, NULL);
1226   if (info != NULL)
1227     {
1228       file_type = g_file_info_get_file_type (info);
1229       g_object_unref (info);
1230     }
1231   else
1232     file_type = G_FILE_TYPE_UNKNOWN;
1233 
1234   return file_type;
1235 }
1236 
1237 /**
1238  * g_file_query_info:
1239  * @file: input #GFile
1240  * @attributes: an attribute query string
1241  * @flags: a set of #GFileQueryInfoFlags
1242  * @cancellable: (nullable): optional #GCancellable object,
1243  *     %NULL to ignore
1244  * @error: a #GError
1245  *
1246  * Gets the requested information about specified @file.
1247  * The result is a #GFileInfo object that contains key-value
1248  * attributes (such as the type or size of the file).
1249  *
1250  * The @attributes value is a string that specifies the file
1251  * attributes that should be gathered. It is not an error if
1252  * it's not possible to read a particular requested attribute
1253  * from a file - it just won't be set. @attributes should be a
1254  * comma-separated list of attributes or attribute wildcards.
1255  * The wildcard "*" means all attributes, and a wildcard like
1256  * "standard::*" means all attributes in the standard namespace.
1257  * An example attribute query be "standard::*,owner::user".
1258  * The standard attributes are available as defines, like
1259  * #G_FILE_ATTRIBUTE_STANDARD_NAME.
1260  *
1261  * If @cancellable is not %NULL, then the operation can be cancelled
1262  * by triggering the cancellable object from another thread. If the
1263  * operation was cancelled, the error %G_IO_ERROR_CANCELLED will be
1264  * returned.
1265  *
1266  * For symlinks, normally the information about the target of the
1267  * symlink is returned, rather than information about the symlink
1268  * itself. However if you pass #G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS
1269  * in @flags the information about the symlink itself will be returned.
1270  * Also, for symlinks that point to non-existing files the information
1271  * about the symlink itself will be returned.
1272  *
1273  * If the file does not exist, the %G_IO_ERROR_NOT_FOUND error will be
1274  * returned. Other errors are possible too, and depend on what kind of
1275  * filesystem the file is on.
1276  *
1277  * Returns: (transfer full): a #GFileInfo for the given @file, or %NULL
1278  *     on error. Free the returned object with g_object_unref().
1279  */
1280 GFileInfo *
g_file_query_info(GFile * file,const char * attributes,GFileQueryInfoFlags flags,GCancellable * cancellable,GError ** error)1281 g_file_query_info (GFile                *file,
1282                    const char           *attributes,
1283                    GFileQueryInfoFlags   flags,
1284                    GCancellable         *cancellable,
1285                    GError              **error)
1286 {
1287   GFileIface *iface;
1288 
1289   g_return_val_if_fail (G_IS_FILE (file), NULL);
1290 
1291   if (g_cancellable_set_error_if_cancelled (cancellable, error))
1292     return NULL;
1293 
1294   iface = G_FILE_GET_IFACE (file);
1295 
1296   if (iface->query_info == NULL)
1297     {
1298       g_set_error_literal (error, G_IO_ERROR,
1299                            G_IO_ERROR_NOT_SUPPORTED,
1300                            _("Operation not supported"));
1301       return NULL;
1302     }
1303 
1304   return (* iface->query_info) (file, attributes, flags, cancellable, error);
1305 }
1306 
1307 /**
1308  * g_file_query_info_async:
1309  * @file: input #GFile
1310  * @attributes: an attribute query string
1311  * @flags: a set of #GFileQueryInfoFlags
1312  * @io_priority: the [I/O priority][io-priority] of the request
1313  * @cancellable: (nullable): optional #GCancellable object,
1314  *     %NULL to ignore
1315  * @callback: (scope async): a #GAsyncReadyCallback to call when the
1316  *     request is satisfied
1317  * @user_data: (closure): the data to pass to callback function
1318  *
1319  * Asynchronously gets the requested information about specified @file.
1320  * The result is a #GFileInfo object that contains key-value attributes
1321  * (such as type or size for the file).
1322  *
1323  * For more details, see g_file_query_info() which is the synchronous
1324  * version of this call.
1325  *
1326  * When the operation is finished, @callback will be called. You can
1327  * then call g_file_query_info_finish() to get the result of the operation.
1328  */
1329 void
g_file_query_info_async(GFile * file,const char * attributes,GFileQueryInfoFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1330 g_file_query_info_async (GFile               *file,
1331                          const char          *attributes,
1332                          GFileQueryInfoFlags  flags,
1333                          int                  io_priority,
1334                          GCancellable        *cancellable,
1335                          GAsyncReadyCallback  callback,
1336                          gpointer             user_data)
1337 {
1338   GFileIface *iface;
1339 
1340   g_return_if_fail (G_IS_FILE (file));
1341 
1342   iface = G_FILE_GET_IFACE (file);
1343   (* iface->query_info_async) (file,
1344                                attributes,
1345                                flags,
1346                                io_priority,
1347                                cancellable,
1348                                callback,
1349                                user_data);
1350 }
1351 
1352 /**
1353  * g_file_query_info_finish:
1354  * @file: input #GFile
1355  * @res: a #GAsyncResult
1356  * @error: a #GError
1357  *
1358  * Finishes an asynchronous file info query.
1359  * See g_file_query_info_async().
1360  *
1361  * Returns: (transfer full): #GFileInfo for given @file
1362  *     or %NULL on error. Free the returned object with
1363  *     g_object_unref().
1364  */
1365 GFileInfo *
g_file_query_info_finish(GFile * file,GAsyncResult * res,GError ** error)1366 g_file_query_info_finish (GFile         *file,
1367                           GAsyncResult  *res,
1368                           GError       **error)
1369 {
1370   GFileIface *iface;
1371 
1372   g_return_val_if_fail (G_IS_FILE (file), NULL);
1373   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
1374 
1375   if (g_async_result_legacy_propagate_error (res, error))
1376     return NULL;
1377 
1378   iface = G_FILE_GET_IFACE (file);
1379   return (* iface->query_info_finish) (file, res, error);
1380 }
1381 
1382 /**
1383  * g_file_query_filesystem_info:
1384  * @file: input #GFile
1385  * @attributes:  an attribute query string
1386  * @cancellable: (nullable): optional #GCancellable object,
1387  *     %NULL to ignore
1388  * @error: a #GError
1389  *
1390  * Similar to g_file_query_info(), but obtains information
1391  * about the filesystem the @file is on, rather than the file itself.
1392  * For instance the amount of space available and the type of
1393  * the filesystem.
1394  *
1395  * The @attributes value is a string that specifies the attributes
1396  * that should be gathered. It is not an error if it's not possible
1397  * to read a particular requested attribute from a file - it just
1398  * won't be set. @attributes should be a comma-separated list of
1399  * attributes or attribute wildcards. The wildcard "*" means all
1400  * attributes, and a wildcard like "filesystem::*" means all attributes
1401  * in the filesystem namespace. The standard namespace for filesystem
1402  * attributes is "filesystem". Common attributes of interest are
1403  * #G_FILE_ATTRIBUTE_FILESYSTEM_SIZE (the total size of the filesystem
1404  * in bytes), #G_FILE_ATTRIBUTE_FILESYSTEM_FREE (number of bytes available),
1405  * and #G_FILE_ATTRIBUTE_FILESYSTEM_TYPE (type of the filesystem).
1406  *
1407  * If @cancellable is not %NULL, then the operation can be cancelled
1408  * by triggering the cancellable object from another thread. If the
1409  * operation was cancelled, the error %G_IO_ERROR_CANCELLED will be
1410  * returned.
1411  *
1412  * If the file does not exist, the %G_IO_ERROR_NOT_FOUND error will
1413  * be returned. Other errors are possible too, and depend on what
1414  * kind of filesystem the file is on.
1415  *
1416  * Returns: (transfer full): a #GFileInfo or %NULL if there was an error.
1417  *     Free the returned object with g_object_unref().
1418  */
1419 GFileInfo *
g_file_query_filesystem_info(GFile * file,const char * attributes,GCancellable * cancellable,GError ** error)1420 g_file_query_filesystem_info (GFile         *file,
1421                               const char    *attributes,
1422                               GCancellable  *cancellable,
1423                               GError       **error)
1424 {
1425   GFileIface *iface;
1426 
1427   g_return_val_if_fail (G_IS_FILE (file), NULL);
1428 
1429   if (g_cancellable_set_error_if_cancelled (cancellable, error))
1430     return NULL;
1431 
1432   iface = G_FILE_GET_IFACE (file);
1433 
1434   if (iface->query_filesystem_info == NULL)
1435     {
1436       g_set_error_literal (error, G_IO_ERROR,
1437                            G_IO_ERROR_NOT_SUPPORTED,
1438                            _("Operation not supported"));
1439       return NULL;
1440     }
1441 
1442   return (* iface->query_filesystem_info) (file, attributes, cancellable, error);
1443 }
1444 
1445 /**
1446  * g_file_query_filesystem_info_async:
1447  * @file: input #GFile
1448  * @attributes: an attribute query string
1449  * @io_priority: the [I/O priority][io-priority] of the request
1450  * @cancellable: (nullable): optional #GCancellable object,
1451  *     %NULL to ignore
1452  * @callback: (scope async): a #GAsyncReadyCallback to call
1453  *     when the request is satisfied
1454  * @user_data: (closure): the data to pass to callback function
1455  *
1456  * Asynchronously gets the requested information about the filesystem
1457  * that the specified @file is on. The result is a #GFileInfo object
1458  * that contains key-value attributes (such as type or size for the
1459  * file).
1460  *
1461  * For more details, see g_file_query_filesystem_info() which is the
1462  * synchronous version of this call.
1463  *
1464  * When the operation is finished, @callback will be called. You can
1465  * then call g_file_query_info_finish() to get the result of the
1466  * operation.
1467  */
1468 void
g_file_query_filesystem_info_async(GFile * file,const char * attributes,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1469 g_file_query_filesystem_info_async (GFile               *file,
1470                                     const char          *attributes,
1471                                     int                  io_priority,
1472                                     GCancellable        *cancellable,
1473                                     GAsyncReadyCallback  callback,
1474                                     gpointer             user_data)
1475 {
1476   GFileIface *iface;
1477 
1478   g_return_if_fail (G_IS_FILE (file));
1479 
1480   iface = G_FILE_GET_IFACE (file);
1481   (* iface->query_filesystem_info_async) (file,
1482                                           attributes,
1483                                           io_priority,
1484                                           cancellable,
1485                                           callback,
1486                                           user_data);
1487 }
1488 
1489 /**
1490  * g_file_query_filesystem_info_finish:
1491  * @file: input #GFile
1492  * @res: a #GAsyncResult
1493  * @error: a #GError
1494  *
1495  * Finishes an asynchronous filesystem info query.
1496  * See g_file_query_filesystem_info_async().
1497  *
1498  * Returns: (transfer full): #GFileInfo for given @file
1499  *     or %NULL on error.
1500  *     Free the returned object with g_object_unref().
1501  */
1502 GFileInfo *
g_file_query_filesystem_info_finish(GFile * file,GAsyncResult * res,GError ** error)1503 g_file_query_filesystem_info_finish (GFile         *file,
1504                                      GAsyncResult  *res,
1505                                      GError       **error)
1506 {
1507   GFileIface *iface;
1508 
1509   g_return_val_if_fail (G_IS_FILE (file), NULL);
1510   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
1511 
1512   if (g_async_result_legacy_propagate_error (res, error))
1513     return NULL;
1514 
1515   iface = G_FILE_GET_IFACE (file);
1516   return (* iface->query_filesystem_info_finish) (file, res, error);
1517 }
1518 
1519 /**
1520  * g_file_find_enclosing_mount:
1521  * @file: input #GFile
1522  * @cancellable: (nullable): optional #GCancellable object,
1523  *     %NULL to ignore
1524  * @error: a #GError
1525  *
1526  * Gets a #GMount for the #GFile.
1527  *
1528  * #GMount is returned only for user interesting locations, see
1529  * #GVolumeMonitor. If the #GFileIface for @file does not have a #mount,
1530  * @error will be set to %G_IO_ERROR_NOT_FOUND and %NULL #will be returned.
1531  *
1532  * If @cancellable is not %NULL, then the operation can be cancelled by
1533  * triggering the cancellable object from another thread. If the operation
1534  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
1535  *
1536  * Returns: (transfer full): a #GMount where the @file is located
1537  *     or %NULL on error.
1538  *     Free the returned object with g_object_unref().
1539  */
1540 GMount *
g_file_find_enclosing_mount(GFile * file,GCancellable * cancellable,GError ** error)1541 g_file_find_enclosing_mount (GFile         *file,
1542                              GCancellable  *cancellable,
1543                              GError       **error)
1544 {
1545   GFileIface *iface;
1546 
1547   g_return_val_if_fail (G_IS_FILE (file), NULL);
1548 
1549   if (g_cancellable_set_error_if_cancelled (cancellable, error))
1550     return NULL;
1551 
1552   iface = G_FILE_GET_IFACE (file);
1553   if (iface->find_enclosing_mount == NULL)
1554     {
1555 
1556       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
1557                            /* Translators: This is an error message when
1558                             * trying to find the enclosing (user visible)
1559                             * mount of a file, but none exists.
1560                             */
1561                            _("Containing mount does not exist"));
1562       return NULL;
1563     }
1564 
1565   return (* iface->find_enclosing_mount) (file, cancellable, error);
1566 }
1567 
1568 /**
1569  * g_file_find_enclosing_mount_async:
1570  * @file: a #GFile
1571  * @io_priority: the [I/O priority][io-priority] of the request
1572  * @cancellable: (nullable): optional #GCancellable object,
1573  *     %NULL to ignore
1574  * @callback: (scope async): a #GAsyncReadyCallback to call
1575  *     when the request is satisfied
1576  * @user_data: (closure): the data to pass to callback function
1577  *
1578  * Asynchronously gets the mount for the file.
1579  *
1580  * For more details, see g_file_find_enclosing_mount() which is
1581  * the synchronous version of this call.
1582  *
1583  * When the operation is finished, @callback will be called.
1584  * You can then call g_file_find_enclosing_mount_finish() to
1585  * get the result of the operation.
1586  */
1587 void
g_file_find_enclosing_mount_async(GFile * file,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1588 g_file_find_enclosing_mount_async (GFile              *file,
1589                                    int                   io_priority,
1590                                    GCancellable         *cancellable,
1591                                    GAsyncReadyCallback   callback,
1592                                    gpointer              user_data)
1593 {
1594   GFileIface *iface;
1595 
1596   g_return_if_fail (G_IS_FILE (file));
1597 
1598   iface = G_FILE_GET_IFACE (file);
1599   (* iface->find_enclosing_mount_async) (file,
1600                                          io_priority,
1601                                          cancellable,
1602                                          callback,
1603                                          user_data);
1604 }
1605 
1606 /**
1607  * g_file_find_enclosing_mount_finish:
1608  * @file: a #GFile
1609  * @res: a #GAsyncResult
1610  * @error: a #GError
1611  *
1612  * Finishes an asynchronous find mount request.
1613  * See g_file_find_enclosing_mount_async().
1614  *
1615  * Returns: (transfer full): #GMount for given @file or %NULL on error.
1616  *     Free the returned object with g_object_unref().
1617  */
1618 GMount *
g_file_find_enclosing_mount_finish(GFile * file,GAsyncResult * res,GError ** error)1619 g_file_find_enclosing_mount_finish (GFile         *file,
1620                                     GAsyncResult  *res,
1621                                     GError       **error)
1622 {
1623   GFileIface *iface;
1624 
1625   g_return_val_if_fail (G_IS_FILE (file), NULL);
1626   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
1627 
1628   if (g_async_result_legacy_propagate_error (res, error))
1629     return NULL;
1630 
1631   iface = G_FILE_GET_IFACE (file);
1632   return (* iface->find_enclosing_mount_finish) (file, res, error);
1633 }
1634 
1635 
1636 /**
1637  * g_file_read:
1638  * @file: #GFile to read
1639  * @cancellable: (nullable): a #GCancellable
1640  * @error: a #GError, or %NULL
1641  *
1642  * Opens a file for reading. The result is a #GFileInputStream that
1643  * can be used to read the contents of the file.
1644  *
1645  * If @cancellable is not %NULL, then the operation can be cancelled by
1646  * triggering the cancellable object from another thread. If the operation
1647  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
1648  *
1649  * If the file does not exist, the %G_IO_ERROR_NOT_FOUND error will be
1650  * returned. If the file is a directory, the %G_IO_ERROR_IS_DIRECTORY
1651  * error will be returned. Other errors are possible too, and depend
1652  * on what kind of filesystem the file is on.
1653  *
1654  * Virtual: read_fn
1655  * Returns: (transfer full): #GFileInputStream or %NULL on error.
1656  *     Free the returned object with g_object_unref().
1657  */
1658 GFileInputStream *
g_file_read(GFile * file,GCancellable * cancellable,GError ** error)1659 g_file_read (GFile         *file,
1660              GCancellable  *cancellable,
1661              GError       **error)
1662 {
1663   GFileIface *iface;
1664 
1665   g_return_val_if_fail (G_IS_FILE (file), NULL);
1666 
1667   if (g_cancellable_set_error_if_cancelled (cancellable, error))
1668     return NULL;
1669 
1670   iface = G_FILE_GET_IFACE (file);
1671 
1672   if (iface->read_fn == NULL)
1673     {
1674       g_set_error_literal (error, G_IO_ERROR,
1675                            G_IO_ERROR_NOT_SUPPORTED,
1676                            _("Operation not supported"));
1677       return NULL;
1678     }
1679 
1680   return (* iface->read_fn) (file, cancellable, error);
1681 }
1682 
1683 /**
1684  * g_file_append_to:
1685  * @file: input #GFile
1686  * @flags: a set of #GFileCreateFlags
1687  * @cancellable: (nullable): optional #GCancellable object,
1688  *     %NULL to ignore
1689  * @error: a #GError, or %NULL
1690  *
1691  * Gets an output stream for appending data to the file.
1692  * If the file doesn't already exist it is created.
1693  *
1694  * By default files created are generally readable by everyone,
1695  * but if you pass #G_FILE_CREATE_PRIVATE in @flags the file
1696  * will be made readable only to the current user, to the level that
1697  * is supported on the target filesystem.
1698  *
1699  * If @cancellable is not %NULL, then the operation can be cancelled
1700  * by triggering the cancellable object from another thread. If the
1701  * operation was cancelled, the error %G_IO_ERROR_CANCELLED will be
1702  * returned.
1703  *
1704  * Some file systems don't allow all file names, and may return an
1705  * %G_IO_ERROR_INVALID_FILENAME error. If the file is a directory the
1706  * %G_IO_ERROR_IS_DIRECTORY error will be returned. Other errors are
1707  * possible too, and depend on what kind of filesystem the file is on.
1708  *
1709  * Returns: (transfer full): a #GFileOutputStream, or %NULL on error.
1710  *     Free the returned object with g_object_unref().
1711  */
1712 GFileOutputStream *
g_file_append_to(GFile * file,GFileCreateFlags flags,GCancellable * cancellable,GError ** error)1713 g_file_append_to (GFile             *file,
1714                   GFileCreateFlags   flags,
1715                   GCancellable      *cancellable,
1716                   GError           **error)
1717 {
1718   GFileIface *iface;
1719 
1720   g_return_val_if_fail (G_IS_FILE (file), NULL);
1721 
1722   if (g_cancellable_set_error_if_cancelled (cancellable, error))
1723     return NULL;
1724 
1725   iface = G_FILE_GET_IFACE (file);
1726 
1727   if (iface->append_to == NULL)
1728     {
1729       g_set_error_literal (error, G_IO_ERROR,
1730                            G_IO_ERROR_NOT_SUPPORTED,
1731                            _("Operation not supported"));
1732       return NULL;
1733     }
1734 
1735   return (* iface->append_to) (file, flags, cancellable, error);
1736 }
1737 
1738 /**
1739  * g_file_create:
1740  * @file: input #GFile
1741  * @flags: a set of #GFileCreateFlags
1742  * @cancellable: (nullable): optional #GCancellable object,
1743  *     %NULL to ignore
1744  * @error: a #GError, or %NULL
1745  *
1746  * Creates a new file and returns an output stream for writing to it.
1747  * The file must not already exist.
1748  *
1749  * By default files created are generally readable by everyone,
1750  * but if you pass #G_FILE_CREATE_PRIVATE in @flags the file
1751  * will be made readable only to the current user, to the level
1752  * that is supported on the target filesystem.
1753  *
1754  * If @cancellable is not %NULL, then the operation can be cancelled
1755  * by triggering the cancellable object from another thread. If the
1756  * operation was cancelled, the error %G_IO_ERROR_CANCELLED will be
1757  * returned.
1758  *
1759  * If a file or directory with this name already exists the
1760  * %G_IO_ERROR_EXISTS error will be returned. Some file systems don't
1761  * allow all file names, and may return an %G_IO_ERROR_INVALID_FILENAME
1762  * error, and if the name is to long %G_IO_ERROR_FILENAME_TOO_LONG will
1763  * be returned. Other errors are possible too, and depend on what kind
1764  * of filesystem the file is on.
1765  *
1766  * Returns: (transfer full): a #GFileOutputStream for the newly created
1767  *     file, or %NULL on error.
1768  *     Free the returned object with g_object_unref().
1769  */
1770 GFileOutputStream *
g_file_create(GFile * file,GFileCreateFlags flags,GCancellable * cancellable,GError ** error)1771 g_file_create (GFile             *file,
1772                GFileCreateFlags   flags,
1773                GCancellable      *cancellable,
1774                GError           **error)
1775 {
1776   GFileIface *iface;
1777 
1778   g_return_val_if_fail (G_IS_FILE (file), NULL);
1779 
1780   if (g_cancellable_set_error_if_cancelled (cancellable, error))
1781     return NULL;
1782 
1783   iface = G_FILE_GET_IFACE (file);
1784 
1785   if (iface->create == NULL)
1786     {
1787       g_set_error_literal (error, G_IO_ERROR,
1788                            G_IO_ERROR_NOT_SUPPORTED,
1789                            _("Operation not supported"));
1790       return NULL;
1791     }
1792 
1793   return (* iface->create) (file, flags, cancellable, error);
1794 }
1795 
1796 /**
1797  * g_file_replace:
1798  * @file: input #GFile
1799  * @etag: (nullable): an optional [entity tag][gfile-etag]
1800  *     for the current #GFile, or #NULL to ignore
1801  * @make_backup: %TRUE if a backup should be created
1802  * @flags: a set of #GFileCreateFlags
1803  * @cancellable: (nullable): optional #GCancellable object,
1804  *     %NULL to ignore
1805  * @error: a #GError, or %NULL
1806  *
1807  * Returns an output stream for overwriting the file, possibly
1808  * creating a backup copy of the file first. If the file doesn't exist,
1809  * it will be created.
1810  *
1811  * This will try to replace the file in the safest way possible so
1812  * that any errors during the writing will not affect an already
1813  * existing copy of the file. For instance, for local files it
1814  * may write to a temporary file and then atomically rename over
1815  * the destination when the stream is closed.
1816  *
1817  * By default files created are generally readable by everyone,
1818  * but if you pass #G_FILE_CREATE_PRIVATE in @flags the file
1819  * will be made readable only to the current user, to the level that
1820  * is supported on the target filesystem.
1821  *
1822  * If @cancellable is not %NULL, then the operation can be cancelled
1823  * by triggering the cancellable object from another thread. If the
1824  * operation was cancelled, the error %G_IO_ERROR_CANCELLED will be
1825  * returned.
1826  *
1827  * If you pass in a non-%NULL @etag value and @file already exists, then
1828  * this value is compared to the current entity tag of the file, and if
1829  * they differ an %G_IO_ERROR_WRONG_ETAG error is returned. This
1830  * generally means that the file has been changed since you last read
1831  * it. You can get the new etag from g_file_output_stream_get_etag()
1832  * after you've finished writing and closed the #GFileOutputStream. When
1833  * you load a new file you can use g_file_input_stream_query_info() to
1834  * get the etag of the file.
1835  *
1836  * If @make_backup is %TRUE, this function will attempt to make a
1837  * backup of the current file before overwriting it. If this fails
1838  * a %G_IO_ERROR_CANT_CREATE_BACKUP error will be returned. If you
1839  * want to replace anyway, try again with @make_backup set to %FALSE.
1840  *
1841  * If the file is a directory the %G_IO_ERROR_IS_DIRECTORY error will
1842  * be returned, and if the file is some other form of non-regular file
1843  * then a %G_IO_ERROR_NOT_REGULAR_FILE error will be returned. Some
1844  * file systems don't allow all file names, and may return an
1845  * %G_IO_ERROR_INVALID_FILENAME error, and if the name is to long
1846  * %G_IO_ERROR_FILENAME_TOO_LONG will be returned. Other errors are
1847  * possible too, and depend on what kind of filesystem the file is on.
1848  *
1849  * Returns: (transfer full): a #GFileOutputStream or %NULL on error.
1850  *     Free the returned object with g_object_unref().
1851  */
1852 GFileOutputStream *
g_file_replace(GFile * file,const char * etag,gboolean make_backup,GFileCreateFlags flags,GCancellable * cancellable,GError ** error)1853 g_file_replace (GFile             *file,
1854                 const char        *etag,
1855                 gboolean           make_backup,
1856                 GFileCreateFlags   flags,
1857                 GCancellable      *cancellable,
1858                 GError           **error)
1859 {
1860   GFileIface *iface;
1861 
1862   g_return_val_if_fail (G_IS_FILE (file), NULL);
1863 
1864   if (g_cancellable_set_error_if_cancelled (cancellable, error))
1865     return NULL;
1866 
1867   iface = G_FILE_GET_IFACE (file);
1868 
1869   if (iface->replace == NULL)
1870     {
1871       g_set_error_literal (error, G_IO_ERROR,
1872                            G_IO_ERROR_NOT_SUPPORTED,
1873                            _("Operation not supported"));
1874       return NULL;
1875     }
1876 
1877   /* Handle empty tag string as NULL in consistent way. */
1878   if (etag && *etag == 0)
1879     etag = NULL;
1880 
1881   return (* iface->replace) (file, etag, make_backup, flags, cancellable, error);
1882 }
1883 
1884 /**
1885  * g_file_open_readwrite:
1886  * @file: #GFile to open
1887  * @cancellable: (nullable): a #GCancellable
1888  * @error: a #GError, or %NULL
1889  *
1890  * Opens an existing file for reading and writing. The result is
1891  * a #GFileIOStream that can be used to read and write the contents
1892  * of the file.
1893  *
1894  * If @cancellable is not %NULL, then the operation can be cancelled
1895  * by triggering the cancellable object from another thread. If the
1896  * operation was cancelled, the error %G_IO_ERROR_CANCELLED will be
1897  * returned.
1898  *
1899  * If the file does not exist, the %G_IO_ERROR_NOT_FOUND error will
1900  * be returned. If the file is a directory, the %G_IO_ERROR_IS_DIRECTORY
1901  * error will be returned. Other errors are possible too, and depend on
1902  * what kind of filesystem the file is on. Note that in many non-local
1903  * file cases read and write streams are not supported, so make sure you
1904  * really need to do read and write streaming, rather than just opening
1905  * for reading or writing.
1906  *
1907  * Returns: (transfer full): #GFileIOStream or %NULL on error.
1908  *     Free the returned object with g_object_unref().
1909  *
1910  * Since: 2.22
1911  */
1912 GFileIOStream *
g_file_open_readwrite(GFile * file,GCancellable * cancellable,GError ** error)1913 g_file_open_readwrite (GFile         *file,
1914                        GCancellable  *cancellable,
1915                        GError       **error)
1916 {
1917   GFileIface *iface;
1918 
1919   g_return_val_if_fail (G_IS_FILE (file), NULL);
1920 
1921   if (g_cancellable_set_error_if_cancelled (cancellable, error))
1922     return NULL;
1923 
1924   iface = G_FILE_GET_IFACE (file);
1925 
1926   if (iface->open_readwrite == NULL)
1927     {
1928       g_set_error_literal (error, G_IO_ERROR,
1929                            G_IO_ERROR_NOT_SUPPORTED,
1930                            _("Operation not supported"));
1931       return NULL;
1932     }
1933 
1934   return (* iface->open_readwrite) (file, cancellable, error);
1935 }
1936 
1937 /**
1938  * g_file_create_readwrite:
1939  * @file: a #GFile
1940  * @flags: a set of #GFileCreateFlags
1941  * @cancellable: (nullable): optional #GCancellable object,
1942  *     %NULL to ignore
1943  * @error: return location for a #GError, or %NULL
1944  *
1945  * Creates a new file and returns a stream for reading and
1946  * writing to it. The file must not already exist.
1947  *
1948  * By default files created are generally readable by everyone,
1949  * but if you pass #G_FILE_CREATE_PRIVATE in @flags the file
1950  * will be made readable only to the current user, to the level
1951  * that is supported on the target filesystem.
1952  *
1953  * If @cancellable is not %NULL, then the operation can be cancelled
1954  * by triggering the cancellable object from another thread. If the
1955  * operation was cancelled, the error %G_IO_ERROR_CANCELLED will be
1956  * returned.
1957  *
1958  * If a file or directory with this name already exists, the
1959  * %G_IO_ERROR_EXISTS error will be returned. Some file systems don't
1960  * allow all file names, and may return an %G_IO_ERROR_INVALID_FILENAME
1961  * error, and if the name is too long, %G_IO_ERROR_FILENAME_TOO_LONG
1962  * will be returned. Other errors are possible too, and depend on what
1963  * kind of filesystem the file is on.
1964  *
1965  * Note that in many non-local file cases read and write streams are
1966  * not supported, so make sure you really need to do read and write
1967  * streaming, rather than just opening for reading or writing.
1968  *
1969  * Returns: (transfer full): a #GFileIOStream for the newly created
1970  *     file, or %NULL on error.
1971  *     Free the returned object with g_object_unref().
1972  *
1973  * Since: 2.22
1974  */
1975 GFileIOStream *
g_file_create_readwrite(GFile * file,GFileCreateFlags flags,GCancellable * cancellable,GError ** error)1976 g_file_create_readwrite (GFile             *file,
1977                          GFileCreateFlags   flags,
1978                          GCancellable      *cancellable,
1979                          GError           **error)
1980 {
1981   GFileIface *iface;
1982 
1983   g_return_val_if_fail (G_IS_FILE (file), NULL);
1984 
1985   if (g_cancellable_set_error_if_cancelled (cancellable, error))
1986     return NULL;
1987 
1988   iface = G_FILE_GET_IFACE (file);
1989 
1990   if (iface->create_readwrite == NULL)
1991     {
1992       g_set_error_literal (error, G_IO_ERROR,
1993                            G_IO_ERROR_NOT_SUPPORTED,
1994                            _("Operation not supported"));
1995       return NULL;
1996     }
1997 
1998   return (* iface->create_readwrite) (file, flags, cancellable, error);
1999 }
2000 
2001 /**
2002  * g_file_replace_readwrite:
2003  * @file: a #GFile
2004  * @etag: (nullable): an optional [entity tag][gfile-etag]
2005  *     for the current #GFile, or #NULL to ignore
2006  * @make_backup: %TRUE if a backup should be created
2007  * @flags: a set of #GFileCreateFlags
2008  * @cancellable: (nullable): optional #GCancellable object,
2009  *     %NULL to ignore
2010  * @error: return location for a #GError, or %NULL
2011  *
2012  * Returns an output stream for overwriting the file in readwrite mode,
2013  * possibly creating a backup copy of the file first. If the file doesn't
2014  * exist, it will be created.
2015  *
2016  * For details about the behaviour, see g_file_replace() which does the
2017  * same thing but returns an output stream only.
2018  *
2019  * Note that in many non-local file cases read and write streams are not
2020  * supported, so make sure you really need to do read and write streaming,
2021  * rather than just opening for reading or writing.
2022  *
2023  * Returns: (transfer full): a #GFileIOStream or %NULL on error.
2024  *     Free the returned object with g_object_unref().
2025  *
2026  * Since: 2.22
2027  */
2028 GFileIOStream *
g_file_replace_readwrite(GFile * file,const char * etag,gboolean make_backup,GFileCreateFlags flags,GCancellable * cancellable,GError ** error)2029 g_file_replace_readwrite (GFile             *file,
2030                           const char        *etag,
2031                           gboolean           make_backup,
2032                           GFileCreateFlags   flags,
2033                           GCancellable      *cancellable,
2034                           GError           **error)
2035 {
2036   GFileIface *iface;
2037 
2038   g_return_val_if_fail (G_IS_FILE (file), NULL);
2039 
2040   if (g_cancellable_set_error_if_cancelled (cancellable, error))
2041     return NULL;
2042 
2043   iface = G_FILE_GET_IFACE (file);
2044 
2045   if (iface->replace_readwrite == NULL)
2046     {
2047       g_set_error_literal (error, G_IO_ERROR,
2048                            G_IO_ERROR_NOT_SUPPORTED,
2049                            _("Operation not supported"));
2050       return NULL;
2051     }
2052 
2053   return (* iface->replace_readwrite) (file, etag, make_backup, flags, cancellable, error);
2054 }
2055 
2056 /**
2057  * g_file_read_async:
2058  * @file: input #GFile
2059  * @io_priority: the [I/O priority][io-priority] of the request
2060  * @cancellable: (nullable): optional #GCancellable object,
2061  *     %NULL to ignore
2062  * @callback: (scope async): a #GAsyncReadyCallback to call
2063  *     when the request is satisfied
2064  * @user_data: (closure): the data to pass to callback function
2065  *
2066  * Asynchronously opens @file for reading.
2067  *
2068  * For more details, see g_file_read() which is
2069  * the synchronous version of this call.
2070  *
2071  * When the operation is finished, @callback will be called.
2072  * You can then call g_file_read_finish() to get the result
2073  * of the operation.
2074  */
2075 void
g_file_read_async(GFile * file,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2076 g_file_read_async (GFile               *file,
2077                    int                  io_priority,
2078                    GCancellable        *cancellable,
2079                    GAsyncReadyCallback  callback,
2080                    gpointer             user_data)
2081 {
2082   GFileIface *iface;
2083 
2084   g_return_if_fail (G_IS_FILE (file));
2085 
2086   iface = G_FILE_GET_IFACE (file);
2087   (* iface->read_async) (file,
2088                          io_priority,
2089                          cancellable,
2090                          callback,
2091                          user_data);
2092 }
2093 
2094 /**
2095  * g_file_read_finish:
2096  * @file: input #GFile
2097  * @res: a #GAsyncResult
2098  * @error: a #GError, or %NULL
2099  *
2100  * Finishes an asynchronous file read operation started with
2101  * g_file_read_async().
2102  *
2103  * Returns: (transfer full): a #GFileInputStream or %NULL on error.
2104  *     Free the returned object with g_object_unref().
2105  */
2106 GFileInputStream *
g_file_read_finish(GFile * file,GAsyncResult * res,GError ** error)2107 g_file_read_finish (GFile         *file,
2108                     GAsyncResult  *res,
2109                     GError       **error)
2110 {
2111   GFileIface *iface;
2112 
2113   g_return_val_if_fail (G_IS_FILE (file), NULL);
2114   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2115 
2116   if (g_async_result_legacy_propagate_error (res, error))
2117     return NULL;
2118 
2119   iface = G_FILE_GET_IFACE (file);
2120   return (* iface->read_finish) (file, res, error);
2121 }
2122 
2123 /**
2124  * g_file_append_to_async:
2125  * @file: input #GFile
2126  * @flags: a set of #GFileCreateFlags
2127  * @io_priority: the [I/O priority][io-priority] of the request
2128  * @cancellable: (nullable): optional #GCancellable object,
2129  *     %NULL to ignore
2130  * @callback: (scope async): a #GAsyncReadyCallback to call
2131  *     when the request is satisfied
2132  * @user_data: (closure): the data to pass to callback function
2133  *
2134  * Asynchronously opens @file for appending.
2135  *
2136  * For more details, see g_file_append_to() which is
2137  * the synchronous version of this call.
2138  *
2139  * When the operation is finished, @callback will be called.
2140  * You can then call g_file_append_to_finish() to get the result
2141  * of the operation.
2142  */
2143 void
g_file_append_to_async(GFile * file,GFileCreateFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2144 g_file_append_to_async (GFile               *file,
2145                         GFileCreateFlags     flags,
2146                         int                  io_priority,
2147                         GCancellable        *cancellable,
2148                         GAsyncReadyCallback  callback,
2149                         gpointer             user_data)
2150 {
2151   GFileIface *iface;
2152 
2153   g_return_if_fail (G_IS_FILE (file));
2154 
2155   iface = G_FILE_GET_IFACE (file);
2156   (* iface->append_to_async) (file,
2157                               flags,
2158                               io_priority,
2159                               cancellable,
2160                               callback,
2161                               user_data);
2162 }
2163 
2164 /**
2165  * g_file_append_to_finish:
2166  * @file: input #GFile
2167  * @res: #GAsyncResult
2168  * @error: a #GError, or %NULL
2169  *
2170  * Finishes an asynchronous file append operation started with
2171  * g_file_append_to_async().
2172  *
2173  * Returns: (transfer full): a valid #GFileOutputStream
2174  *     or %NULL on error.
2175  *     Free the returned object with g_object_unref().
2176  */
2177 GFileOutputStream *
g_file_append_to_finish(GFile * file,GAsyncResult * res,GError ** error)2178 g_file_append_to_finish (GFile         *file,
2179                          GAsyncResult  *res,
2180                          GError       **error)
2181 {
2182   GFileIface *iface;
2183 
2184   g_return_val_if_fail (G_IS_FILE (file), NULL);
2185   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2186 
2187   if (g_async_result_legacy_propagate_error (res, error))
2188     return NULL;
2189 
2190   iface = G_FILE_GET_IFACE (file);
2191   return (* iface->append_to_finish) (file, res, error);
2192 }
2193 
2194 /**
2195  * g_file_create_async:
2196  * @file: input #GFile
2197  * @flags: a set of #GFileCreateFlags
2198  * @io_priority: the [I/O priority][io-priority] of the request
2199  * @cancellable: (nullable): optional #GCancellable object,
2200  *     %NULL to ignore
2201  * @callback: (scope async): a #GAsyncReadyCallback to call
2202  *     when the request is satisfied
2203  * @user_data: (closure): the data to pass to callback function
2204  *
2205  * Asynchronously creates a new file and returns an output stream
2206  * for writing to it. The file must not already exist.
2207  *
2208  * For more details, see g_file_create() which is
2209  * the synchronous version of this call.
2210  *
2211  * When the operation is finished, @callback will be called.
2212  * You can then call g_file_create_finish() to get the result
2213  * of the operation.
2214  */
2215 void
g_file_create_async(GFile * file,GFileCreateFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2216 g_file_create_async (GFile               *file,
2217                      GFileCreateFlags     flags,
2218                      int                  io_priority,
2219                      GCancellable        *cancellable,
2220                      GAsyncReadyCallback  callback,
2221                      gpointer             user_data)
2222 {
2223   GFileIface *iface;
2224 
2225   g_return_if_fail (G_IS_FILE (file));
2226 
2227   iface = G_FILE_GET_IFACE (file);
2228   (* iface->create_async) (file,
2229                            flags,
2230                            io_priority,
2231                            cancellable,
2232                            callback,
2233                            user_data);
2234 }
2235 
2236 /**
2237  * g_file_create_finish:
2238  * @file: input #GFile
2239  * @res: a #GAsyncResult
2240  * @error: a #GError, or %NULL
2241  *
2242  * Finishes an asynchronous file create operation started with
2243  * g_file_create_async().
2244  *
2245  * Returns: (transfer full): a #GFileOutputStream or %NULL on error.
2246  *     Free the returned object with g_object_unref().
2247  */
2248 GFileOutputStream *
g_file_create_finish(GFile * file,GAsyncResult * res,GError ** error)2249 g_file_create_finish (GFile         *file,
2250                       GAsyncResult  *res,
2251                       GError       **error)
2252 {
2253   GFileIface *iface;
2254 
2255   g_return_val_if_fail (G_IS_FILE (file), NULL);
2256   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2257 
2258   if (g_async_result_legacy_propagate_error (res, error))
2259     return NULL;
2260 
2261   iface = G_FILE_GET_IFACE (file);
2262   return (* iface->create_finish) (file, res, error);
2263 }
2264 
2265 /**
2266  * g_file_replace_async:
2267  * @file: input #GFile
2268  * @etag: (nullable): an [entity tag][gfile-etag] for the current #GFile,
2269  *     or %NULL to ignore
2270  * @make_backup: %TRUE if a backup should be created
2271  * @flags: a set of #GFileCreateFlags
2272  * @io_priority: the [I/O priority][io-priority] of the request
2273  * @cancellable: (nullable): optional #GCancellable object,
2274  *     %NULL to ignore
2275  * @callback: (scope async): a #GAsyncReadyCallback to call
2276  *     when the request is satisfied
2277  * @user_data: (closure): the data to pass to callback function
2278  *
2279  * Asynchronously overwrites the file, replacing the contents,
2280  * possibly creating a backup copy of the file first.
2281  *
2282  * For more details, see g_file_replace() which is
2283  * the synchronous version of this call.
2284  *
2285  * When the operation is finished, @callback will be called.
2286  * You can then call g_file_replace_finish() to get the result
2287  * of the operation.
2288  */
2289 void
g_file_replace_async(GFile * file,const char * etag,gboolean make_backup,GFileCreateFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2290 g_file_replace_async (GFile               *file,
2291                       const char          *etag,
2292                       gboolean             make_backup,
2293                       GFileCreateFlags     flags,
2294                       int                  io_priority,
2295                       GCancellable        *cancellable,
2296                       GAsyncReadyCallback  callback,
2297                       gpointer             user_data)
2298 {
2299   GFileIface *iface;
2300 
2301   g_return_if_fail (G_IS_FILE (file));
2302 
2303   iface = G_FILE_GET_IFACE (file);
2304   (* iface->replace_async) (file,
2305                             etag,
2306                             make_backup,
2307                             flags,
2308                             io_priority,
2309                             cancellable,
2310                             callback,
2311                             user_data);
2312 }
2313 
2314 /**
2315  * g_file_replace_finish:
2316  * @file: input #GFile
2317  * @res: a #GAsyncResult
2318  * @error: a #GError, or %NULL
2319  *
2320  * Finishes an asynchronous file replace operation started with
2321  * g_file_replace_async().
2322  *
2323  * Returns: (transfer full): a #GFileOutputStream, or %NULL on error.
2324  *     Free the returned object with g_object_unref().
2325  */
2326 GFileOutputStream *
g_file_replace_finish(GFile * file,GAsyncResult * res,GError ** error)2327 g_file_replace_finish (GFile         *file,
2328                        GAsyncResult  *res,
2329                        GError       **error)
2330 {
2331   GFileIface *iface;
2332 
2333   g_return_val_if_fail (G_IS_FILE (file), NULL);
2334   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2335 
2336   if (g_async_result_legacy_propagate_error (res, error))
2337     return NULL;
2338 
2339   iface = G_FILE_GET_IFACE (file);
2340   return (* iface->replace_finish) (file, res, error);
2341 }
2342 
2343 /**
2344  * g_file_open_readwrite_async
2345  * @file: input #GFile
2346  * @io_priority: the [I/O priority][io-priority] of the request
2347  * @cancellable: (nullable): optional #GCancellable object,
2348  *     %NULL to ignore
2349  * @callback: (scope async): a #GAsyncReadyCallback to call
2350  *     when the request is satisfied
2351  * @user_data: (closure): the data to pass to callback function
2352  *
2353  * Asynchronously opens @file for reading and writing.
2354  *
2355  * For more details, see g_file_open_readwrite() which is
2356  * the synchronous version of this call.
2357  *
2358  * When the operation is finished, @callback will be called.
2359  * You can then call g_file_open_readwrite_finish() to get
2360  * the result of the operation.
2361  *
2362  * Since: 2.22
2363  */
2364 void
g_file_open_readwrite_async(GFile * file,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2365 g_file_open_readwrite_async (GFile               *file,
2366                              int                  io_priority,
2367                              GCancellable        *cancellable,
2368                              GAsyncReadyCallback  callback,
2369                              gpointer             user_data)
2370 {
2371   GFileIface *iface;
2372 
2373   g_return_if_fail (G_IS_FILE (file));
2374 
2375   iface = G_FILE_GET_IFACE (file);
2376   (* iface->open_readwrite_async) (file,
2377                                    io_priority,
2378                                    cancellable,
2379                                    callback,
2380                                    user_data);
2381 }
2382 
2383 /**
2384  * g_file_open_readwrite_finish:
2385  * @file: input #GFile
2386  * @res: a #GAsyncResult
2387  * @error: a #GError, or %NULL
2388  *
2389  * Finishes an asynchronous file read operation started with
2390  * g_file_open_readwrite_async().
2391  *
2392  * Returns: (transfer full): a #GFileIOStream or %NULL on error.
2393  *     Free the returned object with g_object_unref().
2394  *
2395  * Since: 2.22
2396  */
2397 GFileIOStream *
g_file_open_readwrite_finish(GFile * file,GAsyncResult * res,GError ** error)2398 g_file_open_readwrite_finish (GFile         *file,
2399                               GAsyncResult  *res,
2400                               GError       **error)
2401 {
2402   GFileIface *iface;
2403 
2404   g_return_val_if_fail (G_IS_FILE (file), NULL);
2405   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2406 
2407   if (g_async_result_legacy_propagate_error (res, error))
2408     return NULL;
2409 
2410   iface = G_FILE_GET_IFACE (file);
2411   return (* iface->open_readwrite_finish) (file, res, error);
2412 }
2413 
2414 /**
2415  * g_file_create_readwrite_async:
2416  * @file: input #GFile
2417  * @flags: a set of #GFileCreateFlags
2418  * @io_priority: the [I/O priority][io-priority] of the request
2419  * @cancellable: (nullable): optional #GCancellable object,
2420  *     %NULL to ignore
2421  * @callback: (scope async): a #GAsyncReadyCallback to call
2422  *     when the request is satisfied
2423  * @user_data: (closure): the data to pass to callback function
2424  *
2425  * Asynchronously creates a new file and returns a stream
2426  * for reading and writing to it. The file must not already exist.
2427  *
2428  * For more details, see g_file_create_readwrite() which is
2429  * the synchronous version of this call.
2430  *
2431  * When the operation is finished, @callback will be called.
2432  * You can then call g_file_create_readwrite_finish() to get
2433  * the result of the operation.
2434  *
2435  * Since: 2.22
2436  */
2437 void
g_file_create_readwrite_async(GFile * file,GFileCreateFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2438 g_file_create_readwrite_async (GFile               *file,
2439                                GFileCreateFlags     flags,
2440                                int                  io_priority,
2441                                GCancellable        *cancellable,
2442                                GAsyncReadyCallback  callback,
2443                                gpointer             user_data)
2444 {
2445   GFileIface *iface;
2446 
2447   g_return_if_fail (G_IS_FILE (file));
2448 
2449   iface = G_FILE_GET_IFACE (file);
2450   (* iface->create_readwrite_async) (file,
2451                                      flags,
2452                                      io_priority,
2453                                      cancellable,
2454                                      callback,
2455                                      user_data);
2456 }
2457 
2458 /**
2459  * g_file_create_readwrite_finish:
2460  * @file: input #GFile
2461  * @res: a #GAsyncResult
2462  * @error: a #GError, or %NULL
2463  *
2464  * Finishes an asynchronous file create operation started with
2465  * g_file_create_readwrite_async().
2466  *
2467  * Returns: (transfer full): a #GFileIOStream or %NULL on error.
2468  *     Free the returned object with g_object_unref().
2469  *
2470  * Since: 2.22
2471  */
2472 GFileIOStream *
g_file_create_readwrite_finish(GFile * file,GAsyncResult * res,GError ** error)2473 g_file_create_readwrite_finish (GFile         *file,
2474                                 GAsyncResult  *res,
2475                                 GError       **error)
2476 {
2477   GFileIface *iface;
2478 
2479   g_return_val_if_fail (G_IS_FILE (file), NULL);
2480   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2481 
2482   if (g_async_result_legacy_propagate_error (res, error))
2483     return NULL;
2484 
2485   iface = G_FILE_GET_IFACE (file);
2486   return (* iface->create_readwrite_finish) (file, res, error);
2487 }
2488 
2489 /**
2490  * g_file_replace_readwrite_async:
2491  * @file: input #GFile
2492  * @etag: (nullable): an [entity tag][gfile-etag] for the current #GFile,
2493  *     or %NULL to ignore
2494  * @make_backup: %TRUE if a backup should be created
2495  * @flags: a set of #GFileCreateFlags
2496  * @io_priority: the [I/O priority][io-priority] of the request
2497  * @cancellable: (nullable): optional #GCancellable object,
2498  *     %NULL to ignore
2499  * @callback: (scope async): a #GAsyncReadyCallback to call
2500  *     when the request is satisfied
2501  * @user_data: (closure): the data to pass to callback function
2502  *
2503  * Asynchronously overwrites the file in read-write mode,
2504  * replacing the contents, possibly creating a backup copy
2505  * of the file first.
2506  *
2507  * For more details, see g_file_replace_readwrite() which is
2508  * the synchronous version of this call.
2509  *
2510  * When the operation is finished, @callback will be called.
2511  * You can then call g_file_replace_readwrite_finish() to get
2512  * the result of the operation.
2513  *
2514  * Since: 2.22
2515  */
2516 void
g_file_replace_readwrite_async(GFile * file,const char * etag,gboolean make_backup,GFileCreateFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2517 g_file_replace_readwrite_async (GFile               *file,
2518                                 const char          *etag,
2519                                 gboolean             make_backup,
2520                                 GFileCreateFlags     flags,
2521                                 int                  io_priority,
2522                                 GCancellable        *cancellable,
2523                                 GAsyncReadyCallback  callback,
2524                                 gpointer             user_data)
2525 {
2526   GFileIface *iface;
2527 
2528   g_return_if_fail (G_IS_FILE (file));
2529 
2530   iface = G_FILE_GET_IFACE (file);
2531   (* iface->replace_readwrite_async) (file,
2532                                       etag,
2533                                       make_backup,
2534                                       flags,
2535                                       io_priority,
2536                                       cancellable,
2537                                       callback,
2538                                       user_data);
2539 }
2540 
2541 /**
2542  * g_file_replace_readwrite_finish:
2543  * @file: input #GFile
2544  * @res: a #GAsyncResult
2545  * @error: a #GError, or %NULL
2546  *
2547  * Finishes an asynchronous file replace operation started with
2548  * g_file_replace_readwrite_async().
2549  *
2550  * Returns: (transfer full): a #GFileIOStream, or %NULL on error.
2551  *     Free the returned object with g_object_unref().
2552  *
2553  * Since: 2.22
2554  */
2555 GFileIOStream *
g_file_replace_readwrite_finish(GFile * file,GAsyncResult * res,GError ** error)2556 g_file_replace_readwrite_finish (GFile         *file,
2557                                  GAsyncResult  *res,
2558                                  GError       **error)
2559 {
2560   GFileIface *iface;
2561 
2562   g_return_val_if_fail (G_IS_FILE (file), NULL);
2563   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2564 
2565   if (g_async_result_legacy_propagate_error (res, error))
2566     return NULL;
2567 
2568   iface = G_FILE_GET_IFACE (file);
2569   return (* iface->replace_readwrite_finish) (file, res, error);
2570 }
2571 
2572 static gboolean
copy_symlink(GFile * destination,GFileCopyFlags flags,GCancellable * cancellable,const char * target,GError ** error)2573 copy_symlink (GFile           *destination,
2574               GFileCopyFlags   flags,
2575               GCancellable    *cancellable,
2576               const char      *target,
2577               GError         **error)
2578 {
2579   GError *my_error;
2580   gboolean tried_delete;
2581   GFileInfo *info;
2582   GFileType file_type;
2583 
2584   tried_delete = FALSE;
2585 
2586  retry:
2587   my_error = NULL;
2588   if (!g_file_make_symbolic_link (destination, target, cancellable, &my_error))
2589     {
2590       /* Maybe it already existed, and we want to overwrite? */
2591       if (!tried_delete && (flags & G_FILE_COPY_OVERWRITE) &&
2592           my_error->domain == G_IO_ERROR && my_error->code == G_IO_ERROR_EXISTS)
2593         {
2594           g_clear_error (&my_error);
2595 
2596           /* Don't overwrite if the destination is a directory */
2597           info = g_file_query_info (destination, G_FILE_ATTRIBUTE_STANDARD_TYPE,
2598                                     G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2599                                     cancellable, &my_error);
2600           if (info != NULL)
2601             {
2602               file_type = g_file_info_get_file_type (info);
2603               g_object_unref (info);
2604 
2605               if (file_type == G_FILE_TYPE_DIRECTORY)
2606                 {
2607                   g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY,
2608                                        _("Can’t copy over directory"));
2609                   return FALSE;
2610                 }
2611             }
2612 
2613           if (!g_file_delete (destination, cancellable, error))
2614             return FALSE;
2615 
2616           tried_delete = TRUE;
2617           goto retry;
2618         }
2619             /* Nah, fail */
2620       g_propagate_error (error, my_error);
2621       return FALSE;
2622     }
2623 
2624   return TRUE;
2625 }
2626 
2627 static GFileInputStream *
open_source_for_copy(GFile * source,GFile * destination,GFileCopyFlags flags,GCancellable * cancellable,GError ** error)2628 open_source_for_copy (GFile           *source,
2629                       GFile           *destination,
2630                       GFileCopyFlags   flags,
2631                       GCancellable    *cancellable,
2632                       GError         **error)
2633 {
2634   GError *my_error;
2635   GFileInputStream *ret;
2636   GFileInfo *info;
2637   GFileType file_type;
2638 
2639   my_error = NULL;
2640   ret = g_file_read (source, cancellable, &my_error);
2641   if (ret != NULL)
2642     return ret;
2643 
2644   /* There was an error opening the source, try to set a good error for it: */
2645   if (my_error->domain == G_IO_ERROR && my_error->code == G_IO_ERROR_IS_DIRECTORY)
2646     {
2647       /* The source is a directory, don't fail with WOULD_RECURSE immediately,
2648        * as that is less useful to the app. Better check for errors on the
2649        * target instead.
2650        */
2651       g_error_free (my_error);
2652       my_error = NULL;
2653 
2654       info = g_file_query_info (destination, G_FILE_ATTRIBUTE_STANDARD_TYPE,
2655                                 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2656                                 cancellable, &my_error);
2657       if (info != NULL &&
2658           g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE))
2659         {
2660           file_type = g_file_info_get_file_type (info);
2661           g_object_unref (info);
2662 
2663           if (flags & G_FILE_COPY_OVERWRITE)
2664             {
2665               if (file_type == G_FILE_TYPE_DIRECTORY)
2666                 {
2667                   g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_MERGE,
2668                                        _("Can’t copy directory over directory"));
2669                   return NULL;
2670                 }
2671               /* continue to would_recurse error */
2672             }
2673           else
2674             {
2675               g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_EXISTS,
2676                                    _("Target file exists"));
2677               return NULL;
2678             }
2679         }
2680       else
2681         {
2682           /* Error getting info from target, return that error
2683            * (except for NOT_FOUND, which is no error here)
2684            */
2685           g_clear_object (&info);
2686           if (my_error != NULL && !g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
2687             {
2688               g_propagate_error (error, my_error);
2689               return NULL;
2690             }
2691           g_clear_error (&my_error);
2692         }
2693 
2694       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE,
2695                            _("Can’t recursively copy directory"));
2696       return NULL;
2697     }
2698 
2699   g_propagate_error (error, my_error);
2700   return NULL;
2701 }
2702 
2703 static gboolean
should_copy(GFileAttributeInfo * info,gboolean copy_all_attributes,gboolean skip_perms)2704 should_copy (GFileAttributeInfo *info,
2705              gboolean            copy_all_attributes,
2706              gboolean            skip_perms)
2707 {
2708   if (skip_perms && strcmp(info->name, "unix::mode") == 0)
2709         return FALSE;
2710 
2711   if (copy_all_attributes)
2712     return info->flags & G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED;
2713   return info->flags & G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE;
2714 }
2715 
2716 /**
2717  * g_file_build_attribute_list_for_copy:
2718  * @file: a #GFile to copy attributes to
2719  * @flags: a set of #GFileCopyFlags
2720  * @cancellable: (nullable): optional #GCancellable object,
2721  *     %NULL to ignore
2722  * @error: a #GError, %NULL to ignore
2723  *
2724  * Prepares the file attribute query string for copying to @file.
2725  *
2726  * This function prepares an attribute query string to be
2727  * passed to g_file_query_info() to get a list of attributes
2728  * normally copied with the file (see g_file_copy_attributes()
2729  * for the detailed description). This function is used by the
2730  * implementation of g_file_copy_attributes() and is useful
2731  * when one needs to query and set the attributes in two
2732  * stages (e.g., for recursive move of a directory).
2733  *
2734  * Returns: an attribute query string for g_file_query_info(),
2735  *     or %NULL if an error occurs.
2736  *
2737  * Since: 2.68
2738  */
2739 char *
g_file_build_attribute_list_for_copy(GFile * file,GFileCopyFlags flags,GCancellable * cancellable,GError ** error)2740 g_file_build_attribute_list_for_copy (GFile                  *file,
2741                                       GFileCopyFlags          flags,
2742                                       GCancellable           *cancellable,
2743                                       GError                **error)
2744 {
2745   char *ret = NULL;
2746   GFileAttributeInfoList *attributes = NULL, *namespaces = NULL;
2747   GString *s = NULL;
2748   gboolean first;
2749   int i;
2750   gboolean copy_all_attributes;
2751   gboolean skip_perms;
2752 
2753   g_return_val_if_fail (G_IS_FILE (file), NULL);
2754   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
2755   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2756 
2757   copy_all_attributes = flags & G_FILE_COPY_ALL_METADATA;
2758   skip_perms = (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) != 0;
2759 
2760   /* Ignore errors here, if the target supports no attributes there is
2761    * nothing to copy.  We still honor the cancellable though.
2762    */
2763   attributes = g_file_query_settable_attributes (file, cancellable, NULL);
2764   if (g_cancellable_set_error_if_cancelled (cancellable, error))
2765     goto out;
2766 
2767   namespaces = g_file_query_writable_namespaces (file, cancellable, NULL);
2768   if (g_cancellable_set_error_if_cancelled (cancellable, error))
2769     goto out;
2770 
2771   if (attributes == NULL && namespaces == NULL)
2772     goto out;
2773 
2774   first = TRUE;
2775   s = g_string_new ("");
2776 
2777   if (attributes)
2778     {
2779       for (i = 0; i < attributes->n_infos; i++)
2780         {
2781           if (should_copy (&attributes->infos[i], copy_all_attributes, skip_perms))
2782             {
2783               if (first)
2784                 first = FALSE;
2785               else
2786                 g_string_append_c (s, ',');
2787 
2788               g_string_append (s, attributes->infos[i].name);
2789             }
2790         }
2791     }
2792 
2793   if (namespaces)
2794     {
2795       for (i = 0; i < namespaces->n_infos; i++)
2796         {
2797           if (should_copy (&namespaces->infos[i], copy_all_attributes, FALSE))
2798             {
2799               if (first)
2800                 first = FALSE;
2801               else
2802                 g_string_append_c (s, ',');
2803 
2804               g_string_append (s, namespaces->infos[i].name);
2805               g_string_append (s, "::*");
2806             }
2807         }
2808     }
2809 
2810   ret = g_string_free (s, FALSE);
2811   s = NULL;
2812  out:
2813   if (s)
2814     g_string_free (s, TRUE);
2815   if (attributes)
2816     g_file_attribute_info_list_unref (attributes);
2817   if (namespaces)
2818     g_file_attribute_info_list_unref (namespaces);
2819 
2820   return ret;
2821 }
2822 
2823 /**
2824  * g_file_copy_attributes:
2825  * @source: a #GFile with attributes
2826  * @destination: a #GFile to copy attributes to
2827  * @flags: a set of #GFileCopyFlags
2828  * @cancellable: (nullable): optional #GCancellable object,
2829  *     %NULL to ignore
2830  * @error: a #GError, %NULL to ignore
2831  *
2832  * Copies the file attributes from @source to @destination.
2833  *
2834  * Normally only a subset of the file attributes are copied,
2835  * those that are copies in a normal file copy operation
2836  * (which for instance does not include e.g. owner). However
2837  * if #G_FILE_COPY_ALL_METADATA is specified in @flags, then
2838  * all the metadata that is possible to copy is copied. This
2839  * is useful when implementing move by copy + delete source.
2840  *
2841  * Returns: %TRUE if the attributes were copied successfully,
2842  *     %FALSE otherwise.
2843  */
2844 gboolean
g_file_copy_attributes(GFile * source,GFile * destination,GFileCopyFlags flags,GCancellable * cancellable,GError ** error)2845 g_file_copy_attributes (GFile           *source,
2846                         GFile           *destination,
2847                         GFileCopyFlags   flags,
2848                         GCancellable    *cancellable,
2849                         GError         **error)
2850 {
2851   char *attrs_to_read;
2852   gboolean res;
2853   GFileInfo *info;
2854   gboolean source_nofollow_symlinks;
2855 
2856   attrs_to_read = g_file_build_attribute_list_for_copy (destination, flags,
2857                                                         cancellable, error);
2858   if (!attrs_to_read)
2859     return FALSE;
2860 
2861   source_nofollow_symlinks = flags & G_FILE_COPY_NOFOLLOW_SYMLINKS;
2862 
2863   /* Ignore errors here, if we can't read some info (e.g. if it doesn't exist)
2864    * we just don't copy it.
2865    */
2866   info = g_file_query_info (source, attrs_to_read,
2867                             source_nofollow_symlinks ? G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS:0,
2868                             cancellable,
2869                             NULL);
2870 
2871   g_free (attrs_to_read);
2872 
2873   res = TRUE;
2874   if  (info)
2875     {
2876       res = g_file_set_attributes_from_info (destination,
2877                                              info,
2878                                              G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2879                                              cancellable,
2880                                              error);
2881       g_object_unref (info);
2882     }
2883 
2884   return res;
2885 }
2886 
2887 /* 256k minus malloc overhead */
2888 #define STREAM_BUFFER_SIZE (1024*256 - 2 *sizeof(gpointer))
2889 
2890 static gboolean
copy_stream_with_progress(GInputStream * in,GOutputStream * out,GFile * source,GCancellable * cancellable,GFileProgressCallback progress_callback,gpointer progress_callback_data,GError ** error)2891 copy_stream_with_progress (GInputStream           *in,
2892                            GOutputStream          *out,
2893                            GFile                  *source,
2894                            GCancellable           *cancellable,
2895                            GFileProgressCallback   progress_callback,
2896                            gpointer                progress_callback_data,
2897                            GError                **error)
2898 {
2899   gssize n_read;
2900   gsize n_written;
2901   goffset current_size;
2902   char *buffer;
2903   gboolean res;
2904   goffset total_size;
2905   GFileInfo *info;
2906 
2907   total_size = -1;
2908   /* avoid performance impact of querying total size when it's not needed */
2909   if (progress_callback)
2910     {
2911       info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (in),
2912                                              G_FILE_ATTRIBUTE_STANDARD_SIZE,
2913                                              cancellable, NULL);
2914       if (info)
2915         {
2916           if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE))
2917             total_size = g_file_info_get_size (info);
2918           g_object_unref (info);
2919         }
2920 
2921       if (total_size == -1)
2922         {
2923           info = g_file_query_info (source,
2924                                     G_FILE_ATTRIBUTE_STANDARD_SIZE,
2925                                     G_FILE_QUERY_INFO_NONE,
2926                                     cancellable, NULL);
2927           if (info)
2928             {
2929               if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE))
2930                 total_size = g_file_info_get_size (info);
2931               g_object_unref (info);
2932             }
2933         }
2934     }
2935 
2936   if (total_size == -1)
2937     total_size = 0;
2938 
2939   buffer = g_malloc0 (STREAM_BUFFER_SIZE);
2940   current_size = 0;
2941   res = TRUE;
2942   while (TRUE)
2943     {
2944       n_read = g_input_stream_read (in, buffer, STREAM_BUFFER_SIZE, cancellable, error);
2945       if (n_read == -1)
2946         {
2947           res = FALSE;
2948           break;
2949         }
2950 
2951       if (n_read == 0)
2952         break;
2953 
2954       current_size += n_read;
2955 
2956       res = g_output_stream_write_all (out, buffer, n_read, &n_written, cancellable, error);
2957       if (!res)
2958         break;
2959 
2960       if (progress_callback)
2961         progress_callback (current_size, total_size, progress_callback_data);
2962     }
2963   g_free (buffer);
2964 
2965   /* Make sure we send full copied size */
2966   if (progress_callback)
2967     progress_callback (current_size, total_size, progress_callback_data);
2968 
2969   return res;
2970 }
2971 
2972 #ifdef HAVE_SPLICE
2973 
2974 static gboolean
do_splice(int fd_in,loff_t * off_in,int fd_out,loff_t * off_out,size_t len,long * bytes_transferd,GError ** error)2975 do_splice (int     fd_in,
2976            loff_t *off_in,
2977            int     fd_out,
2978            loff_t *off_out,
2979            size_t  len,
2980            long   *bytes_transferd,
2981            GError **error)
2982 {
2983   long result;
2984 
2985 retry:
2986   result = splice (fd_in, off_in, fd_out, off_out, len, SPLICE_F_MORE);
2987 
2988   if (result == -1)
2989     {
2990       int errsv = errno;
2991 
2992       if (errsv == EINTR)
2993         goto retry;
2994       else if (errsv == ENOSYS || errsv == EINVAL || errsv == EOPNOTSUPP)
2995         g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
2996                              _("Splice not supported"));
2997       else
2998         g_set_error (error, G_IO_ERROR,
2999                      g_io_error_from_errno (errsv),
3000                      _("Error splicing file: %s"),
3001                      g_strerror (errsv));
3002 
3003       return FALSE;
3004     }
3005 
3006   *bytes_transferd = result;
3007   return TRUE;
3008 }
3009 
3010 static gboolean
splice_stream_with_progress(GInputStream * in,GOutputStream * out,GCancellable * cancellable,GFileProgressCallback progress_callback,gpointer progress_callback_data,GError ** error)3011 splice_stream_with_progress (GInputStream           *in,
3012                              GOutputStream          *out,
3013                              GCancellable           *cancellable,
3014                              GFileProgressCallback   progress_callback,
3015                              gpointer                progress_callback_data,
3016                              GError                **error)
3017 {
3018   int buffer[2] = { -1, -1 };
3019   int buffer_size;
3020   gboolean res;
3021   goffset total_size;
3022   loff_t offset_in;
3023   loff_t offset_out;
3024   int fd_in, fd_out;
3025 
3026   fd_in = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (in));
3027   fd_out = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (out));
3028 
3029   if (!g_unix_open_pipe (buffer, FD_CLOEXEC, error))
3030     return FALSE;
3031 
3032   /* Try a 1MiB buffer for improved throughput. If that fails, use the default
3033    * pipe size. See: https://bugzilla.gnome.org/791457 */
3034   buffer_size = fcntl (buffer[1], F_SETPIPE_SZ, 1024 * 1024);
3035   if (buffer_size <= 0)
3036     {
3037       buffer_size = fcntl (buffer[1], F_GETPIPE_SZ);
3038       if (buffer_size <= 0)
3039         {
3040           /* If #F_GETPIPE_SZ isn’t available, assume we’re on Linux < 2.6.35,
3041            * but ≥ 2.6.11, meaning the pipe capacity is 64KiB. Ignore the
3042            * possibility of running on Linux < 2.6.11 (where the capacity was
3043            * the system page size, typically 4KiB) because it’s ancient.
3044            * See pipe(7). */
3045           buffer_size = 1024 * 64;
3046         }
3047     }
3048 
3049   g_assert (buffer_size > 0);
3050 
3051   total_size = -1;
3052   /* avoid performance impact of querying total size when it's not needed */
3053   if (progress_callback)
3054     {
3055       struct stat sbuf;
3056 
3057       if (fstat (fd_in, &sbuf) == 0)
3058         total_size = sbuf.st_size;
3059     }
3060 
3061   if (total_size == -1)
3062     total_size = 0;
3063 
3064   offset_in = offset_out = 0;
3065   res = FALSE;
3066   while (TRUE)
3067     {
3068       long n_read;
3069       long n_written;
3070 
3071       if (g_cancellable_set_error_if_cancelled (cancellable, error))
3072         break;
3073 
3074       if (!do_splice (fd_in, &offset_in, buffer[1], NULL, buffer_size, &n_read, error))
3075         break;
3076 
3077       if (n_read == 0)
3078         {
3079           res = TRUE;
3080           break;
3081         }
3082 
3083       while (n_read > 0)
3084         {
3085           if (g_cancellable_set_error_if_cancelled (cancellable, error))
3086             goto out;
3087 
3088           if (!do_splice (buffer[0], NULL, fd_out, &offset_out, n_read, &n_written, error))
3089             goto out;
3090 
3091           n_read -= n_written;
3092         }
3093 
3094       if (progress_callback)
3095         progress_callback (offset_in, total_size, progress_callback_data);
3096     }
3097 
3098   /* Make sure we send full copied size */
3099   if (progress_callback)
3100     progress_callback (offset_in, total_size, progress_callback_data);
3101 
3102   if (!g_close (buffer[0], error))
3103     goto out;
3104   buffer[0] = -1;
3105   if (!g_close (buffer[1], error))
3106     goto out;
3107   buffer[1] = -1;
3108  out:
3109   if (buffer[0] != -1)
3110     (void) g_close (buffer[0], NULL);
3111   if (buffer[1] != -1)
3112     (void) g_close (buffer[1], NULL);
3113 
3114   return res;
3115 }
3116 #endif
3117 
3118 #ifdef __linux__
3119 static gboolean
btrfs_reflink_with_progress(GInputStream * in,GOutputStream * out,GFileInfo * info,GCancellable * cancellable,GFileProgressCallback progress_callback,gpointer progress_callback_data,GError ** error)3120 btrfs_reflink_with_progress (GInputStream           *in,
3121                              GOutputStream          *out,
3122                              GFileInfo              *info,
3123                              GCancellable           *cancellable,
3124                              GFileProgressCallback   progress_callback,
3125                              gpointer                progress_callback_data,
3126                              GError                **error)
3127 {
3128   goffset source_size;
3129   int fd_in, fd_out;
3130   int ret, errsv;
3131 
3132   fd_in = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (in));
3133   fd_out = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (out));
3134 
3135   if (progress_callback)
3136     source_size = g_file_info_get_size (info);
3137 
3138   /* Btrfs clone ioctl properties:
3139    *  - Works at the inode level
3140    *  - Doesn't work with directories
3141    *  - Always follows symlinks (source and destination)
3142    *
3143    * By the time we get here, *in and *out are both regular files */
3144   ret = ioctl (fd_out, BTRFS_IOC_CLONE, fd_in);
3145   errsv = errno;
3146 
3147   if (ret < 0)
3148     {
3149       if (errsv == EXDEV)
3150 	g_set_error_literal (error, G_IO_ERROR,
3151 			     G_IO_ERROR_NOT_SUPPORTED,
3152 			     _("Copy (reflink/clone) between mounts is not supported"));
3153       else if (errsv == EINVAL)
3154 	g_set_error_literal (error, G_IO_ERROR,
3155 			     G_IO_ERROR_NOT_SUPPORTED,
3156 			     _("Copy (reflink/clone) is not supported or invalid"));
3157       else
3158 	/* Most probably something odd happened; retry with fallback */
3159 	g_set_error_literal (error, G_IO_ERROR,
3160 			     G_IO_ERROR_NOT_SUPPORTED,
3161 			     _("Copy (reflink/clone) is not supported or didn’t work"));
3162       /* We retry with fallback for all error cases because Btrfs is currently
3163        * unstable, and so we can't trust it to do clone properly.
3164        * In addition, any hard errors here would cause the same failure in the
3165        * fallback manual copy as well. */
3166       return FALSE;
3167     }
3168 
3169   /* Make sure we send full copied size */
3170   if (progress_callback)
3171     progress_callback (source_size, source_size, progress_callback_data);
3172 
3173   return TRUE;
3174 }
3175 #endif
3176 
3177 static gboolean
file_copy_fallback(GFile * source,GFile * destination,GFileCopyFlags flags,GCancellable * cancellable,GFileProgressCallback progress_callback,gpointer progress_callback_data,GError ** error)3178 file_copy_fallback (GFile                  *source,
3179                     GFile                  *destination,
3180                     GFileCopyFlags          flags,
3181                     GCancellable           *cancellable,
3182                     GFileProgressCallback   progress_callback,
3183                     gpointer                progress_callback_data,
3184                     GError                **error)
3185 {
3186   gboolean ret = FALSE;
3187   GFileInputStream *file_in = NULL;
3188   GInputStream *in = NULL;
3189   GOutputStream *out = NULL;
3190   GFileInfo *info = NULL;
3191   const char *target;
3192   char *attrs_to_read;
3193   gboolean do_set_attributes = FALSE;
3194   GFileCreateFlags create_flags;
3195   GError *tmp_error = NULL;
3196 
3197   /* need to know the file type */
3198   info = g_file_query_info (source,
3199                             G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
3200                             G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3201                             cancellable,
3202                             error);
3203   if (!info)
3204     goto out;
3205 
3206   /* Maybe copy the symlink? */
3207   if ((flags & G_FILE_COPY_NOFOLLOW_SYMLINKS) &&
3208       g_file_info_get_file_type (info) == G_FILE_TYPE_SYMBOLIC_LINK)
3209     {
3210       target = g_file_info_get_symlink_target (info);
3211       if (target)
3212         {
3213           if (!copy_symlink (destination, flags, cancellable, target, error))
3214             goto out;
3215 
3216           ret = TRUE;
3217           goto out;
3218         }
3219         /* ... else fall back on a regular file copy */
3220     }
3221   /* Handle "special" files (pipes, device nodes, ...)? */
3222   else if (g_file_info_get_file_type (info) == G_FILE_TYPE_SPECIAL)
3223     {
3224       /* FIXME: could try to recreate device nodes and others? */
3225       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
3226                            _("Can’t copy special file"));
3227       goto out;
3228     }
3229 
3230   /* Everything else should just fall back on a regular copy. */
3231 
3232   file_in = open_source_for_copy (source, destination, flags, cancellable, error);
3233   if (!file_in)
3234     goto out;
3235   in = G_INPUT_STREAM (file_in);
3236 
3237   attrs_to_read = g_file_build_attribute_list_for_copy (destination, flags,
3238                                                         cancellable, error);
3239   if (!attrs_to_read)
3240     goto out;
3241 
3242   /* Ok, ditch the previous lightweight info (on Unix we just
3243    * called lstat()); at this point we gather all the information
3244    * we need about the source from the opened file descriptor.
3245    */
3246   g_object_unref (info);
3247 
3248   info = g_file_input_stream_query_info (file_in, attrs_to_read,
3249                                          cancellable, &tmp_error);
3250   if (!info)
3251     {
3252       /* Not all gvfs backends implement query_info_on_read(), we
3253        * can just fall back to the pathname again.
3254        * https://bugzilla.gnome.org/706254
3255        */
3256       if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
3257         {
3258           g_clear_error (&tmp_error);
3259           info = g_file_query_info (source, attrs_to_read, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3260                                     cancellable, error);
3261         }
3262       else
3263         {
3264           g_free (attrs_to_read);
3265           g_propagate_error (error, tmp_error);
3266           goto out;
3267         }
3268     }
3269   g_free (attrs_to_read);
3270   if (!info)
3271     goto out;
3272 
3273   do_set_attributes = TRUE;
3274 
3275   /* In the local file path, we pass down the source info which
3276    * includes things like unix::mode, to ensure that the target file
3277    * is not created with different permissions from the source file.
3278    *
3279    * If a future API like g_file_replace_with_info() is added, switch
3280    * this code to use that.
3281    *
3282    * Use %G_FILE_CREATE_PRIVATE unless
3283    *  - we were told to create the file with default permissions (i.e. the
3284    *    process’ umask),
3285    *  - or if the source file is on a file system which doesn’t support
3286    *    `unix::mode` (in which case it probably also makes sense to create the
3287    *    destination with default permissions because the source cannot be
3288    *    private),
3289    *  - or if the destination file is a `GLocalFile`, in which case we can
3290    *    directly open() it with the permissions from the source file.
3291    */
3292   create_flags = G_FILE_CREATE_NONE;
3293   if (!(flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) &&
3294       g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE) &&
3295       !G_IS_LOCAL_FILE (destination))
3296     create_flags |= G_FILE_CREATE_PRIVATE;
3297   if (flags & G_FILE_COPY_OVERWRITE)
3298     create_flags |= G_FILE_CREATE_REPLACE_DESTINATION;
3299 
3300   if (G_IS_LOCAL_FILE (destination))
3301     {
3302       if (flags & G_FILE_COPY_OVERWRITE)
3303         out = (GOutputStream*)_g_local_file_output_stream_replace (_g_local_file_get_filename (G_LOCAL_FILE (destination)),
3304                                                                    FALSE, NULL,
3305                                                                    flags & G_FILE_COPY_BACKUP,
3306                                                                    create_flags,
3307                                                                    (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) ? NULL : info,
3308                                                                    cancellable, error);
3309       else
3310         out = (GOutputStream*)_g_local_file_output_stream_create (_g_local_file_get_filename (G_LOCAL_FILE (destination)),
3311                                                                   FALSE, create_flags,
3312                                                                   (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) ? NULL : info,
3313                                                                   cancellable, error);
3314     }
3315   else if (flags & G_FILE_COPY_OVERWRITE)
3316     {
3317       out = (GOutputStream *)g_file_replace (destination,
3318                                              NULL,
3319                                              flags & G_FILE_COPY_BACKUP,
3320                                              create_flags,
3321                                              cancellable, error);
3322     }
3323   else
3324     {
3325       out = (GOutputStream *)g_file_create (destination, create_flags, cancellable, error);
3326     }
3327 
3328   if (!out)
3329     goto out;
3330 
3331 #ifdef __linux__
3332   if (G_IS_FILE_DESCRIPTOR_BASED (in) && G_IS_FILE_DESCRIPTOR_BASED (out))
3333     {
3334       GError *reflink_err = NULL;
3335 
3336       if (!btrfs_reflink_with_progress (in, out, info, cancellable,
3337                                         progress_callback, progress_callback_data,
3338                                         &reflink_err))
3339         {
3340           if (g_error_matches (reflink_err, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
3341             {
3342               g_clear_error (&reflink_err);
3343             }
3344           else
3345             {
3346               g_propagate_error (error, reflink_err);
3347               goto out;
3348             }
3349         }
3350       else
3351         {
3352           ret = TRUE;
3353           goto out;
3354         }
3355     }
3356 #endif
3357 
3358 #ifdef HAVE_SPLICE
3359   if (G_IS_FILE_DESCRIPTOR_BASED (in) && G_IS_FILE_DESCRIPTOR_BASED (out))
3360     {
3361       GError *splice_err = NULL;
3362 
3363       if (!splice_stream_with_progress (in, out, cancellable,
3364                                         progress_callback, progress_callback_data,
3365                                         &splice_err))
3366         {
3367           if (g_error_matches (splice_err, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
3368             {
3369               g_clear_error (&splice_err);
3370             }
3371           else
3372             {
3373               g_propagate_error (error, splice_err);
3374               goto out;
3375             }
3376         }
3377       else
3378         {
3379           ret = TRUE;
3380           goto out;
3381         }
3382     }
3383 
3384 #endif
3385 
3386   /* A plain read/write loop */
3387   if (!copy_stream_with_progress (in, out, source, cancellable,
3388                                   progress_callback, progress_callback_data,
3389                                   error))
3390     goto out;
3391 
3392   ret = TRUE;
3393  out:
3394   if (in)
3395     {
3396       /* Don't care about errors in source here */
3397       (void) g_input_stream_close (in, cancellable, NULL);
3398       g_object_unref (in);
3399     }
3400 
3401   if (out)
3402     {
3403       /* But write errors on close are bad! */
3404       if (!g_output_stream_close (out, cancellable, ret ? error : NULL))
3405         ret = FALSE;
3406       g_object_unref (out);
3407     }
3408 
3409   /* Ignore errors here. Failure to copy metadata is not a hard error */
3410   /* TODO: set these attributes /before/ we do the rename() on Unix */
3411   if (ret && do_set_attributes)
3412     {
3413       g_file_set_attributes_from_info (destination,
3414                                        info,
3415                                        G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3416                                        cancellable,
3417                                        NULL);
3418     }
3419 
3420   g_clear_object (&info);
3421 
3422   return ret;
3423 }
3424 
3425 /**
3426  * g_file_copy:
3427  * @source: input #GFile
3428  * @destination: destination #GFile
3429  * @flags: set of #GFileCopyFlags
3430  * @cancellable: (nullable): optional #GCancellable object,
3431  *     %NULL to ignore
3432  * @progress_callback: (nullable) (scope call): function to callback with
3433  *     progress information, or %NULL if progress information is not needed
3434  * @progress_callback_data: (closure): user data to pass to @progress_callback
3435  * @error: #GError to set on error, or %NULL
3436  *
3437  * Copies the file @source to the location specified by @destination.
3438  * Can not handle recursive copies of directories.
3439  *
3440  * If the flag #G_FILE_COPY_OVERWRITE is specified an already
3441  * existing @destination file is overwritten.
3442  *
3443  * If the flag #G_FILE_COPY_NOFOLLOW_SYMLINKS is specified then symlinks
3444  * will be copied as symlinks, otherwise the target of the
3445  * @source symlink will be copied.
3446  *
3447  * If the flag #G_FILE_COPY_ALL_METADATA is specified then all the metadata
3448  * that is possible to copy is copied, not just the default subset (which,
3449  * for instance, does not include the owner, see #GFileInfo).
3450  *
3451  * If @cancellable is not %NULL, then the operation can be cancelled by
3452  * triggering the cancellable object from another thread. If the operation
3453  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
3454  *
3455  * If @progress_callback is not %NULL, then the operation can be monitored
3456  * by setting this to a #GFileProgressCallback function.
3457  * @progress_callback_data will be passed to this function. It is guaranteed
3458  * that this callback will be called after all data has been transferred with
3459  * the total number of bytes copied during the operation.
3460  *
3461  * If the @source file does not exist, then the %G_IO_ERROR_NOT_FOUND error
3462  * is returned, independent on the status of the @destination.
3463  *
3464  * If #G_FILE_COPY_OVERWRITE is not specified and the target exists, then
3465  * the error %G_IO_ERROR_EXISTS is returned.
3466  *
3467  * If trying to overwrite a file over a directory, the %G_IO_ERROR_IS_DIRECTORY
3468  * error is returned. If trying to overwrite a directory with a directory the
3469  * %G_IO_ERROR_WOULD_MERGE error is returned.
3470  *
3471  * If the source is a directory and the target does not exist, or
3472  * #G_FILE_COPY_OVERWRITE is specified and the target is a file, then the
3473  * %G_IO_ERROR_WOULD_RECURSE error is returned.
3474  *
3475  * If you are interested in copying the #GFile object itself (not the on-disk
3476  * file), see g_file_dup().
3477  *
3478  * Returns: %TRUE on success, %FALSE otherwise.
3479  */
3480 gboolean
g_file_copy(GFile * source,GFile * destination,GFileCopyFlags flags,GCancellable * cancellable,GFileProgressCallback progress_callback,gpointer progress_callback_data,GError ** error)3481 g_file_copy (GFile                  *source,
3482              GFile                  *destination,
3483              GFileCopyFlags          flags,
3484              GCancellable           *cancellable,
3485              GFileProgressCallback   progress_callback,
3486              gpointer                progress_callback_data,
3487              GError                **error)
3488 {
3489   GFileIface *iface;
3490   GError *my_error;
3491   gboolean res;
3492 
3493   g_return_val_if_fail (G_IS_FILE (source), FALSE);
3494   g_return_val_if_fail (G_IS_FILE (destination), FALSE);
3495 
3496   if (g_cancellable_set_error_if_cancelled (cancellable, error))
3497     return FALSE;
3498 
3499   iface = G_FILE_GET_IFACE (destination);
3500   if (iface->copy)
3501     {
3502       my_error = NULL;
3503       res = (* iface->copy) (source, destination,
3504                              flags, cancellable,
3505                              progress_callback, progress_callback_data,
3506                              &my_error);
3507 
3508       if (res)
3509         return TRUE;
3510 
3511       if (my_error->domain != G_IO_ERROR || my_error->code != G_IO_ERROR_NOT_SUPPORTED)
3512         {
3513           g_propagate_error (error, my_error);
3514               return FALSE;
3515         }
3516       else
3517         g_clear_error (&my_error);
3518     }
3519 
3520   /* If the types are different, and the destination method failed
3521    * also try the source method
3522    */
3523   if (G_OBJECT_TYPE (source) != G_OBJECT_TYPE (destination))
3524     {
3525       iface = G_FILE_GET_IFACE (source);
3526 
3527       if (iface->copy)
3528         {
3529           my_error = NULL;
3530           res = (* iface->copy) (source, destination,
3531                                  flags, cancellable,
3532                                  progress_callback, progress_callback_data,
3533                                  &my_error);
3534 
3535           if (res)
3536             return TRUE;
3537 
3538           if (my_error->domain != G_IO_ERROR || my_error->code != G_IO_ERROR_NOT_SUPPORTED)
3539             {
3540               g_propagate_error (error, my_error);
3541               return FALSE;
3542             }
3543           else
3544             g_clear_error (&my_error);
3545         }
3546     }
3547 
3548   return file_copy_fallback (source, destination, flags, cancellable,
3549                              progress_callback, progress_callback_data,
3550                              error);
3551 }
3552 
3553 /**
3554  * g_file_copy_async:
3555  * @source: input #GFile
3556  * @destination: destination #GFile
3557  * @flags: set of #GFileCopyFlags
3558  * @io_priority: the [I/O priority][io-priority] of the request
3559  * @cancellable: (nullable): optional #GCancellable object,
3560  *     %NULL to ignore
3561  * @progress_callback: (nullable) (scope notified): function to callback with progress
3562  *     information, or %NULL if progress information is not needed
3563  * @progress_callback_data: (closure progress_callback) (nullable): user data to pass to @progress_callback
3564  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
3565  * @user_data: (closure callback): the data to pass to callback function
3566  *
3567  * Copies the file @source to the location specified by @destination
3568  * asynchronously. For details of the behaviour, see g_file_copy().
3569  *
3570  * If @progress_callback is not %NULL, then that function that will be called
3571  * just like in g_file_copy(). The callback will run in the default main context
3572  * of the thread calling g_file_copy_async() — the same context as @callback is
3573  * run in.
3574  *
3575  * When the operation is finished, @callback will be called. You can then call
3576  * g_file_copy_finish() to get the result of the operation.
3577  */
3578 void
g_file_copy_async(GFile * source,GFile * destination,GFileCopyFlags flags,int io_priority,GCancellable * cancellable,GFileProgressCallback progress_callback,gpointer progress_callback_data,GAsyncReadyCallback callback,gpointer user_data)3579 g_file_copy_async (GFile                  *source,
3580                    GFile                  *destination,
3581                    GFileCopyFlags          flags,
3582                    int                     io_priority,
3583                    GCancellable           *cancellable,
3584                    GFileProgressCallback   progress_callback,
3585                    gpointer                progress_callback_data,
3586                    GAsyncReadyCallback     callback,
3587                    gpointer                user_data)
3588 {
3589   GFileIface *iface;
3590 
3591   g_return_if_fail (G_IS_FILE (source));
3592   g_return_if_fail (G_IS_FILE (destination));
3593 
3594   iface = G_FILE_GET_IFACE (source);
3595   (* iface->copy_async) (source,
3596                          destination,
3597                          flags,
3598                          io_priority,
3599                          cancellable,
3600                          progress_callback,
3601                          progress_callback_data,
3602                          callback,
3603                          user_data);
3604 }
3605 
3606 /**
3607  * g_file_copy_finish:
3608  * @file: input #GFile
3609  * @res: a #GAsyncResult
3610  * @error: a #GError, or %NULL
3611  *
3612  * Finishes copying the file started with g_file_copy_async().
3613  *
3614  * Returns: a %TRUE on success, %FALSE on error.
3615  */
3616 gboolean
g_file_copy_finish(GFile * file,GAsyncResult * res,GError ** error)3617 g_file_copy_finish (GFile         *file,
3618                     GAsyncResult  *res,
3619                     GError       **error)
3620 {
3621   GFileIface *iface;
3622 
3623   g_return_val_if_fail (G_IS_FILE (file), FALSE);
3624   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
3625 
3626   if (g_async_result_legacy_propagate_error (res, error))
3627     return FALSE;
3628 
3629   iface = G_FILE_GET_IFACE (file);
3630   return (* iface->copy_finish) (file, res, error);
3631 }
3632 
3633 /**
3634  * g_file_move:
3635  * @source: #GFile pointing to the source location
3636  * @destination: #GFile pointing to the destination location
3637  * @flags: set of #GFileCopyFlags
3638  * @cancellable: (nullable): optional #GCancellable object,
3639  *     %NULL to ignore
3640  * @progress_callback: (nullable) (scope call): #GFileProgressCallback
3641  *     function for updates
3642  * @progress_callback_data: (closure): gpointer to user data for
3643  *     the callback function
3644  * @error: #GError for returning error conditions, or %NULL
3645  *
3646  * Tries to move the file or directory @source to the location specified
3647  * by @destination. If native move operations are supported then this is
3648  * used, otherwise a copy + delete fallback is used. The native
3649  * implementation may support moving directories (for instance on moves
3650  * inside the same filesystem), but the fallback code does not.
3651  *
3652  * If the flag #G_FILE_COPY_OVERWRITE is specified an already
3653  * existing @destination file is overwritten.
3654  *
3655  * If @cancellable is not %NULL, then the operation can be cancelled by
3656  * triggering the cancellable object from another thread. If the operation
3657  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
3658  *
3659  * If @progress_callback is not %NULL, then the operation can be monitored
3660  * by setting this to a #GFileProgressCallback function.
3661  * @progress_callback_data will be passed to this function. It is
3662  * guaranteed that this callback will be called after all data has been
3663  * transferred with the total number of bytes copied during the operation.
3664  *
3665  * If the @source file does not exist, then the %G_IO_ERROR_NOT_FOUND
3666  * error is returned, independent on the status of the @destination.
3667  *
3668  * If #G_FILE_COPY_OVERWRITE is not specified and the target exists,
3669  * then the error %G_IO_ERROR_EXISTS is returned.
3670  *
3671  * If trying to overwrite a file over a directory, the %G_IO_ERROR_IS_DIRECTORY
3672  * error is returned. If trying to overwrite a directory with a directory the
3673  * %G_IO_ERROR_WOULD_MERGE error is returned.
3674  *
3675  * If the source is a directory and the target does not exist, or
3676  * #G_FILE_COPY_OVERWRITE is specified and the target is a file, then
3677  * the %G_IO_ERROR_WOULD_RECURSE error may be returned (if the native
3678  * move operation isn't available).
3679  *
3680  * Returns: %TRUE on successful move, %FALSE otherwise.
3681  */
3682 gboolean
g_file_move(GFile * source,GFile * destination,GFileCopyFlags flags,GCancellable * cancellable,GFileProgressCallback progress_callback,gpointer progress_callback_data,GError ** error)3683 g_file_move (GFile                  *source,
3684              GFile                  *destination,
3685              GFileCopyFlags          flags,
3686              GCancellable           *cancellable,
3687              GFileProgressCallback   progress_callback,
3688              gpointer                progress_callback_data,
3689              GError                **error)
3690 {
3691   GFileIface *iface;
3692   GError *my_error;
3693   gboolean res;
3694 
3695   g_return_val_if_fail (G_IS_FILE (source), FALSE);
3696   g_return_val_if_fail (G_IS_FILE (destination), FALSE);
3697 
3698   if (g_cancellable_set_error_if_cancelled (cancellable, error))
3699     return FALSE;
3700 
3701   iface = G_FILE_GET_IFACE (destination);
3702   if (iface->move)
3703     {
3704       my_error = NULL;
3705       res = (* iface->move) (source, destination,
3706                              flags, cancellable,
3707                              progress_callback, progress_callback_data,
3708                              &my_error);
3709 
3710       if (res)
3711         return TRUE;
3712 
3713       if (my_error->domain != G_IO_ERROR || my_error->code != G_IO_ERROR_NOT_SUPPORTED)
3714         {
3715           g_propagate_error (error, my_error);
3716           return FALSE;
3717         }
3718       else
3719         g_clear_error (&my_error);
3720     }
3721 
3722   /* If the types are different, and the destination method failed
3723    * also try the source method
3724    */
3725   if (G_OBJECT_TYPE (source) != G_OBJECT_TYPE (destination))
3726     {
3727       iface = G_FILE_GET_IFACE (source);
3728 
3729       if (iface->move)
3730         {
3731           my_error = NULL;
3732           res = (* iface->move) (source, destination,
3733                                  flags, cancellable,
3734                                  progress_callback, progress_callback_data,
3735                                  &my_error);
3736 
3737           if (res)
3738             return TRUE;
3739 
3740           if (my_error->domain != G_IO_ERROR || my_error->code != G_IO_ERROR_NOT_SUPPORTED)
3741             {
3742               g_propagate_error (error, my_error);
3743               return FALSE;
3744             }
3745           else
3746             g_clear_error (&my_error);
3747         }
3748     }
3749 
3750   if (flags & G_FILE_COPY_NO_FALLBACK_FOR_MOVE)
3751     {
3752       g_set_error_literal (error, G_IO_ERROR,
3753                            G_IO_ERROR_NOT_SUPPORTED,
3754                            _("Operation not supported"));
3755       return FALSE;
3756     }
3757 
3758   flags |= G_FILE_COPY_ALL_METADATA | G_FILE_COPY_NOFOLLOW_SYMLINKS;
3759   if (!g_file_copy (source, destination, flags, cancellable,
3760                     progress_callback, progress_callback_data,
3761                     error))
3762     return FALSE;
3763 
3764   return g_file_delete (source, cancellable, error);
3765 }
3766 
3767 /**
3768  * g_file_make_directory:
3769  * @file: input #GFile
3770  * @cancellable: (nullable): optional #GCancellable object,
3771  *     %NULL to ignore
3772  * @error: a #GError, or %NULL
3773  *
3774  * Creates a directory. Note that this will only create a child directory
3775  * of the immediate parent directory of the path or URI given by the #GFile.
3776  * To recursively create directories, see g_file_make_directory_with_parents().
3777  * This function will fail if the parent directory does not exist, setting
3778  * @error to %G_IO_ERROR_NOT_FOUND. If the file system doesn't support
3779  * creating directories, this function will fail, setting @error to
3780  * %G_IO_ERROR_NOT_SUPPORTED.
3781  *
3782  * For a local #GFile the newly created directory will have the default
3783  * (current) ownership and permissions of the current process.
3784  *
3785  * If @cancellable is not %NULL, then the operation can be cancelled by
3786  * triggering the cancellable object from another thread. If the operation
3787  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
3788  *
3789  * Returns: %TRUE on successful creation, %FALSE otherwise.
3790  */
3791 gboolean
g_file_make_directory(GFile * file,GCancellable * cancellable,GError ** error)3792 g_file_make_directory (GFile         *file,
3793                        GCancellable  *cancellable,
3794                        GError       **error)
3795 {
3796   GFileIface *iface;
3797 
3798   g_return_val_if_fail (G_IS_FILE (file), FALSE);
3799 
3800   if (g_cancellable_set_error_if_cancelled (cancellable, error))
3801     return FALSE;
3802 
3803   iface = G_FILE_GET_IFACE (file);
3804 
3805   if (iface->make_directory == NULL)
3806     {
3807       g_set_error_literal (error, G_IO_ERROR,
3808                            G_IO_ERROR_NOT_SUPPORTED,
3809                            _("Operation not supported"));
3810       return FALSE;
3811     }
3812 
3813   return (* iface->make_directory) (file, cancellable, error);
3814 }
3815 
3816 /**
3817  * g_file_make_directory_async:
3818  * @file: input #GFile
3819  * @io_priority: the [I/O priority][io-priority] of the request
3820  * @cancellable: (nullable): optional #GCancellable object,
3821  *     %NULL to ignore
3822  * @callback: a #GAsyncReadyCallback to call
3823  *     when the request is satisfied
3824  * @user_data: the data to pass to callback function
3825  *
3826  * Asynchronously creates a directory.
3827  *
3828  * Virtual: make_directory_async
3829  * Since: 2.38
3830  */
3831 void
g_file_make_directory_async(GFile * file,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)3832 g_file_make_directory_async (GFile               *file,
3833                              int                  io_priority,
3834                              GCancellable        *cancellable,
3835                              GAsyncReadyCallback  callback,
3836                              gpointer             user_data)
3837 {
3838   GFileIface *iface;
3839 
3840   g_return_if_fail (G_IS_FILE (file));
3841 
3842   iface = G_FILE_GET_IFACE (file);
3843   (* iface->make_directory_async) (file,
3844                                    io_priority,
3845                                    cancellable,
3846                                    callback,
3847                                    user_data);
3848 }
3849 
3850 /**
3851  * g_file_make_directory_finish:
3852  * @file: input #GFile
3853  * @result: a #GAsyncResult
3854  * @error: a #GError, or %NULL
3855  *
3856  * Finishes an asynchronous directory creation, started with
3857  * g_file_make_directory_async().
3858  *
3859  * Virtual: make_directory_finish
3860  * Returns: %TRUE on successful directory creation, %FALSE otherwise.
3861  * Since: 2.38
3862  */
3863 gboolean
g_file_make_directory_finish(GFile * file,GAsyncResult * result,GError ** error)3864 g_file_make_directory_finish (GFile         *file,
3865                               GAsyncResult  *result,
3866                               GError       **error)
3867 {
3868   GFileIface *iface;
3869 
3870   g_return_val_if_fail (G_IS_FILE (file), FALSE);
3871   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
3872 
3873   iface = G_FILE_GET_IFACE (file);
3874   return (* iface->make_directory_finish) (file, result, error);
3875 }
3876 
3877 /**
3878  * g_file_make_directory_with_parents:
3879  * @file: input #GFile
3880  * @cancellable: (nullable): optional #GCancellable object,
3881  *     %NULL to ignore
3882  * @error: a #GError, or %NULL
3883  *
3884  * Creates a directory and any parent directories that may not
3885  * exist similar to 'mkdir -p'. If the file system does not support
3886  * creating directories, this function will fail, setting @error to
3887  * %G_IO_ERROR_NOT_SUPPORTED. If the directory itself already exists,
3888  * this function will fail setting @error to %G_IO_ERROR_EXISTS, unlike
3889  * the similar g_mkdir_with_parents().
3890  *
3891  * For a local #GFile the newly created directories will have the default
3892  * (current) ownership and permissions of the current process.
3893  *
3894  * If @cancellable is not %NULL, then the operation can be cancelled by
3895  * triggering the cancellable object from another thread. If the operation
3896  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
3897  *
3898  * Returns: %TRUE if all directories have been successfully created, %FALSE
3899  * otherwise.
3900  *
3901  * Since: 2.18
3902  */
3903 gboolean
g_file_make_directory_with_parents(GFile * file,GCancellable * cancellable,GError ** error)3904 g_file_make_directory_with_parents (GFile         *file,
3905                                     GCancellable  *cancellable,
3906                                     GError       **error)
3907 {
3908   GFile *work_file = NULL;
3909   GList *list = NULL, *l;
3910   GError *my_error = NULL;
3911 
3912   g_return_val_if_fail (G_IS_FILE (file), FALSE);
3913 
3914   if (g_cancellable_set_error_if_cancelled (cancellable, error))
3915     return FALSE;
3916 
3917   /* Try for the simple case of not having to create any parent
3918    * directories.  If any parent directory needs to be created, this
3919    * call will fail with NOT_FOUND. If that happens, then that value of
3920    * my_error persists into the while loop below.
3921    */
3922   g_file_make_directory (file, cancellable, &my_error);
3923   if (!g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
3924     {
3925       if (my_error)
3926         g_propagate_error (error, my_error);
3927       return my_error == NULL;
3928     }
3929 
3930   work_file = g_object_ref (file);
3931 
3932   /* Creates the parent directories as needed. In case any particular
3933    * creation operation fails for lack of other parent directories
3934    * (NOT_FOUND), the directory is added to a list of directories to
3935    * create later, and the value of my_error is retained until the next
3936    * iteration of the loop.  After the loop my_error should either be
3937    * empty or contain a real failure condition.
3938    */
3939   while (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
3940     {
3941       GFile *parent_file;
3942 
3943       parent_file = g_file_get_parent (work_file);
3944       if (parent_file == NULL)
3945         break;
3946 
3947       g_clear_error (&my_error);
3948       g_file_make_directory (parent_file, cancellable, &my_error);
3949       /* Another process may have created the directory in between the
3950        * G_IO_ERROR_NOT_FOUND and now
3951        */
3952       if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
3953         g_clear_error (&my_error);
3954 
3955       g_object_unref (work_file);
3956       work_file = g_object_ref (parent_file);
3957 
3958       if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
3959         list = g_list_prepend (list, parent_file);  /* Transfer ownership of ref */
3960       else
3961         g_object_unref (parent_file);
3962     }
3963 
3964   /* All directories should be able to be created now, so an error at
3965    * this point means the whole operation must fail -- except an EXISTS
3966    * error, which means that another process already created the
3967    * directory in between the previous failure and now.
3968    */
3969   for (l = list; my_error == NULL && l; l = l->next)
3970     {
3971       g_file_make_directory ((GFile *) l->data, cancellable, &my_error);
3972       if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
3973         g_clear_error (&my_error);
3974     }
3975 
3976   if (work_file)
3977     g_object_unref (work_file);
3978 
3979   /* Clean up */
3980   while (list != NULL)
3981     {
3982       g_object_unref ((GFile *) list->data);
3983       list = g_list_remove (list, list->data);
3984     }
3985 
3986   /* At this point an error in my_error means a that something
3987    * unexpected failed in either of the loops above, so the whole
3988    * operation must fail.
3989    */
3990   if (my_error != NULL)
3991     {
3992       g_propagate_error (error, my_error);
3993       return FALSE;
3994     }
3995 
3996   return g_file_make_directory (file, cancellable, error);
3997 }
3998 
3999 /**
4000  * g_file_make_symbolic_link:
4001  * @file: a #GFile with the name of the symlink to create
4002  * @symlink_value: (type filename): a string with the path for the target
4003  *     of the new symlink
4004  * @cancellable: (nullable): optional #GCancellable object,
4005  *     %NULL to ignore
4006  * @error: a #GError
4007  *
4008  * Creates a symbolic link named @file which contains the string
4009  * @symlink_value.
4010  *
4011  * If @cancellable is not %NULL, then the operation can be cancelled by
4012  * triggering the cancellable object from another thread. If the operation
4013  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4014  *
4015  * Returns: %TRUE on the creation of a new symlink, %FALSE otherwise.
4016  */
4017 gboolean
g_file_make_symbolic_link(GFile * file,const char * symlink_value,GCancellable * cancellable,GError ** error)4018 g_file_make_symbolic_link (GFile         *file,
4019                            const char    *symlink_value,
4020                            GCancellable  *cancellable,
4021                            GError       **error)
4022 {
4023   GFileIface *iface;
4024 
4025   g_return_val_if_fail (G_IS_FILE (file), FALSE);
4026   g_return_val_if_fail (symlink_value != NULL, FALSE);
4027 
4028   if (g_cancellable_set_error_if_cancelled (cancellable, error))
4029     return FALSE;
4030 
4031   if (*symlink_value == '\0')
4032     {
4033       g_set_error_literal (error, G_IO_ERROR,
4034                            G_IO_ERROR_INVALID_ARGUMENT,
4035                            _("Invalid symlink value given"));
4036       return FALSE;
4037     }
4038 
4039   iface = G_FILE_GET_IFACE (file);
4040 
4041   if (iface->make_symbolic_link == NULL)
4042     {
4043       g_set_error_literal (error, G_IO_ERROR,
4044                            G_IO_ERROR_NOT_SUPPORTED,
4045                            _("Symbolic links not supported"));
4046       return FALSE;
4047     }
4048 
4049   return (* iface->make_symbolic_link) (file, symlink_value, cancellable, error);
4050 }
4051 
4052 /**
4053  * g_file_delete:
4054  * @file: input #GFile
4055  * @cancellable: (nullable): optional #GCancellable object,
4056  *     %NULL to ignore
4057  * @error: a #GError, or %NULL
4058  *
4059  * Deletes a file. If the @file is a directory, it will only be
4060  * deleted if it is empty. This has the same semantics as g_unlink().
4061  *
4062  * If @file doesn’t exist, %G_IO_ERROR_NOT_FOUND will be returned. This allows
4063  * for deletion to be implemented avoiding
4064  * [time-of-check to time-of-use races](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use):
4065  * |[
4066  * g_autoptr(GError) local_error = NULL;
4067  * if (!g_file_delete (my_file, my_cancellable, &local_error) &&
4068  *     !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
4069  *   {
4070  *     // deletion failed for some reason other than the file not existing:
4071  *     // so report the error
4072  *     g_warning ("Failed to delete %s: %s",
4073  *                g_file_peek_path (my_file), local_error->message);
4074  *   }
4075  * ]|
4076  *
4077  * If @cancellable is not %NULL, then the operation can be cancelled by
4078  * triggering the cancellable object from another thread. If the operation
4079  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4080  *
4081  * Virtual: delete_file
4082  * Returns: %TRUE if the file was deleted. %FALSE otherwise.
4083  */
4084 gboolean
g_file_delete(GFile * file,GCancellable * cancellable,GError ** error)4085 g_file_delete (GFile         *file,
4086                GCancellable  *cancellable,
4087                GError       **error)
4088 {
4089   GFileIface *iface;
4090 
4091   g_return_val_if_fail (G_IS_FILE (file), FALSE);
4092 
4093   if (g_cancellable_set_error_if_cancelled (cancellable, error))
4094     return FALSE;
4095 
4096   iface = G_FILE_GET_IFACE (file);
4097 
4098   if (iface->delete_file == NULL)
4099     {
4100       g_set_error_literal (error, G_IO_ERROR,
4101                            G_IO_ERROR_NOT_SUPPORTED,
4102                            _("Operation not supported"));
4103       return FALSE;
4104     }
4105 
4106   return (* iface->delete_file) (file, cancellable, error);
4107 }
4108 
4109 /**
4110  * g_file_delete_async:
4111  * @file: input #GFile
4112  * @io_priority: the [I/O priority][io-priority] of the request
4113  * @cancellable: (nullable): optional #GCancellable object,
4114  *     %NULL to ignore
4115  * @callback: a #GAsyncReadyCallback to call
4116  *     when the request is satisfied
4117  * @user_data: the data to pass to callback function
4118  *
4119  * Asynchronously delete a file. If the @file is a directory, it will
4120  * only be deleted if it is empty.  This has the same semantics as
4121  * g_unlink().
4122  *
4123  * Virtual: delete_file_async
4124  * Since: 2.34
4125  */
4126 void
g_file_delete_async(GFile * file,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)4127 g_file_delete_async (GFile               *file,
4128                      int                  io_priority,
4129                      GCancellable        *cancellable,
4130                      GAsyncReadyCallback  callback,
4131                      gpointer             user_data)
4132 {
4133   GFileIface *iface;
4134 
4135   g_return_if_fail (G_IS_FILE (file));
4136 
4137   iface = G_FILE_GET_IFACE (file);
4138   (* iface->delete_file_async) (file,
4139                                 io_priority,
4140                                 cancellable,
4141                                 callback,
4142                                 user_data);
4143 }
4144 
4145 /**
4146  * g_file_delete_finish:
4147  * @file: input #GFile
4148  * @result: a #GAsyncResult
4149  * @error: a #GError, or %NULL
4150  *
4151  * Finishes deleting a file started with g_file_delete_async().
4152  *
4153  * Virtual: delete_file_finish
4154  * Returns: %TRUE if the file was deleted. %FALSE otherwise.
4155  * Since: 2.34
4156  **/
4157 gboolean
g_file_delete_finish(GFile * file,GAsyncResult * result,GError ** error)4158 g_file_delete_finish (GFile         *file,
4159                       GAsyncResult  *result,
4160                       GError       **error)
4161 {
4162   GFileIface *iface;
4163 
4164   g_return_val_if_fail (G_IS_FILE (file), FALSE);
4165   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
4166 
4167   if (g_async_result_legacy_propagate_error (result, error))
4168     return FALSE;
4169 
4170   iface = G_FILE_GET_IFACE (file);
4171   return (* iface->delete_file_finish) (file, result, error);
4172 }
4173 
4174 /**
4175  * g_file_trash:
4176  * @file: #GFile to send to trash
4177  * @cancellable: (nullable): optional #GCancellable object,
4178  *     %NULL to ignore
4179  * @error: a #GError, or %NULL
4180  *
4181  * Sends @file to the "Trashcan", if possible. This is similar to
4182  * deleting it, but the user can recover it before emptying the trashcan.
4183  * Not all file systems support trashing, so this call can return the
4184  * %G_IO_ERROR_NOT_SUPPORTED error. Since GLib 2.66, the `x-gvfs-notrash` unix
4185  * mount option can be used to disable g_file_trash() support for certain
4186  * mounts, the %G_IO_ERROR_NOT_SUPPORTED error will be returned in that case.
4187  *
4188  * If @cancellable is not %NULL, then the operation can be cancelled by
4189  * triggering the cancellable object from another thread. If the operation
4190  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4191  *
4192  * Virtual: trash
4193  * Returns: %TRUE on successful trash, %FALSE otherwise.
4194  */
4195 gboolean
g_file_trash(GFile * file,GCancellable * cancellable,GError ** error)4196 g_file_trash (GFile         *file,
4197               GCancellable  *cancellable,
4198               GError       **error)
4199 {
4200   GFileIface *iface;
4201 
4202   g_return_val_if_fail (G_IS_FILE (file), FALSE);
4203 
4204   if (g_cancellable_set_error_if_cancelled (cancellable, error))
4205     return FALSE;
4206 
4207   iface = G_FILE_GET_IFACE (file);
4208 
4209   if (iface->trash == NULL)
4210     {
4211       g_set_error_literal (error,
4212                            G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
4213                            _("Trash not supported"));
4214       return FALSE;
4215     }
4216 
4217   return (* iface->trash) (file, cancellable, error);
4218 }
4219 
4220 /**
4221  * g_file_trash_async:
4222  * @file: input #GFile
4223  * @io_priority: the [I/O priority][io-priority] of the request
4224  * @cancellable: (nullable): optional #GCancellable object,
4225  *     %NULL to ignore
4226  * @callback: a #GAsyncReadyCallback to call
4227  *     when the request is satisfied
4228  * @user_data: the data to pass to callback function
4229  *
4230  * Asynchronously sends @file to the Trash location, if possible.
4231  *
4232  * Virtual: trash_async
4233  * Since: 2.38
4234  */
4235 void
g_file_trash_async(GFile * file,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)4236 g_file_trash_async (GFile               *file,
4237                     int                  io_priority,
4238                     GCancellable        *cancellable,
4239                     GAsyncReadyCallback  callback,
4240                     gpointer             user_data)
4241 {
4242   GFileIface *iface;
4243 
4244   g_return_if_fail (G_IS_FILE (file));
4245 
4246   iface = G_FILE_GET_IFACE (file);
4247   (* iface->trash_async) (file,
4248                           io_priority,
4249                           cancellable,
4250                           callback,
4251                           user_data);
4252 }
4253 
4254 /**
4255  * g_file_trash_finish:
4256  * @file: input #GFile
4257  * @result: a #GAsyncResult
4258  * @error: a #GError, or %NULL
4259  *
4260  * Finishes an asynchronous file trashing operation, started with
4261  * g_file_trash_async().
4262  *
4263  * Virtual: trash_finish
4264  * Returns: %TRUE on successful trash, %FALSE otherwise.
4265  * Since: 2.38
4266  */
4267 gboolean
g_file_trash_finish(GFile * file,GAsyncResult * result,GError ** error)4268 g_file_trash_finish (GFile         *file,
4269                      GAsyncResult  *result,
4270                      GError       **error)
4271 {
4272   GFileIface *iface;
4273 
4274   g_return_val_if_fail (G_IS_FILE (file), FALSE);
4275   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
4276 
4277   iface = G_FILE_GET_IFACE (file);
4278   return (* iface->trash_finish) (file, result, error);
4279 }
4280 
4281 /**
4282  * g_file_set_display_name:
4283  * @file: input #GFile
4284  * @display_name: a string
4285  * @cancellable: (nullable): optional #GCancellable object,
4286  *     %NULL to ignore
4287  * @error: a #GError, or %NULL
4288  *
4289  * Renames @file to the specified display name.
4290  *
4291  * The display name is converted from UTF-8 to the correct encoding
4292  * for the target filesystem if possible and the @file is renamed to this.
4293  *
4294  * If you want to implement a rename operation in the user interface the
4295  * edit name (#G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME) should be used as the
4296  * initial value in the rename widget, and then the result after editing
4297  * should be passed to g_file_set_display_name().
4298  *
4299  * On success the resulting converted filename is returned.
4300  *
4301  * If @cancellable is not %NULL, then the operation can be cancelled by
4302  * triggering the cancellable object from another thread. If the operation
4303  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4304  *
4305  * Returns: (transfer full): a #GFile specifying what @file was renamed to,
4306  *     or %NULL if there was an error.
4307  *     Free the returned object with g_object_unref().
4308  */
4309 GFile *
g_file_set_display_name(GFile * file,const gchar * display_name,GCancellable * cancellable,GError ** error)4310 g_file_set_display_name (GFile         *file,
4311                          const gchar   *display_name,
4312                          GCancellable  *cancellable,
4313                          GError       **error)
4314 {
4315   GFileIface *iface;
4316 
4317   g_return_val_if_fail (G_IS_FILE (file), NULL);
4318   g_return_val_if_fail (display_name != NULL, NULL);
4319 
4320   if (strchr (display_name, G_DIR_SEPARATOR) != NULL)
4321     {
4322       g_set_error (error,
4323                    G_IO_ERROR,
4324                    G_IO_ERROR_INVALID_ARGUMENT,
4325                    _("File names cannot contain “%c”"), G_DIR_SEPARATOR);
4326       return NULL;
4327     }
4328 
4329   if (g_cancellable_set_error_if_cancelled (cancellable, error))
4330     return NULL;
4331 
4332   iface = G_FILE_GET_IFACE (file);
4333 
4334   return (* iface->set_display_name) (file, display_name, cancellable, error);
4335 }
4336 
4337 /**
4338  * g_file_set_display_name_async:
4339  * @file: input #GFile
4340  * @display_name: a string
4341  * @io_priority: the [I/O priority][io-priority] of the request
4342  * @cancellable: (nullable): optional #GCancellable object,
4343  *     %NULL to ignore
4344  * @callback: (scope async): a #GAsyncReadyCallback to call
4345  *     when the request is satisfied
4346  * @user_data: (closure): the data to pass to callback function
4347  *
4348  * Asynchronously sets the display name for a given #GFile.
4349  *
4350  * For more details, see g_file_set_display_name() which is
4351  * the synchronous version of this call.
4352  *
4353  * When the operation is finished, @callback will be called.
4354  * You can then call g_file_set_display_name_finish() to get
4355  * the result of the operation.
4356  */
4357 void
g_file_set_display_name_async(GFile * file,const gchar * display_name,gint io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)4358 g_file_set_display_name_async (GFile               *file,
4359                                const gchar         *display_name,
4360                                gint                 io_priority,
4361                                GCancellable        *cancellable,
4362                                GAsyncReadyCallback  callback,
4363                                gpointer             user_data)
4364 {
4365   GFileIface *iface;
4366 
4367   g_return_if_fail (G_IS_FILE (file));
4368   g_return_if_fail (display_name != NULL);
4369 
4370   iface = G_FILE_GET_IFACE (file);
4371   (* iface->set_display_name_async) (file,
4372                                      display_name,
4373                                      io_priority,
4374                                      cancellable,
4375                                      callback,
4376                                      user_data);
4377 }
4378 
4379 /**
4380  * g_file_set_display_name_finish:
4381  * @file: input #GFile
4382  * @res: a #GAsyncResult
4383  * @error: a #GError, or %NULL
4384  *
4385  * Finishes setting a display name started with
4386  * g_file_set_display_name_async().
4387  *
4388  * Returns: (transfer full): a #GFile or %NULL on error.
4389  *     Free the returned object with g_object_unref().
4390  */
4391 GFile *
g_file_set_display_name_finish(GFile * file,GAsyncResult * res,GError ** error)4392 g_file_set_display_name_finish (GFile         *file,
4393                                 GAsyncResult  *res,
4394                                 GError       **error)
4395 {
4396   GFileIface *iface;
4397 
4398   g_return_val_if_fail (G_IS_FILE (file), NULL);
4399   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
4400 
4401   if (g_async_result_legacy_propagate_error (res, error))
4402     return NULL;
4403 
4404   iface = G_FILE_GET_IFACE (file);
4405   return (* iface->set_display_name_finish) (file, res, error);
4406 }
4407 
4408 /**
4409  * g_file_query_settable_attributes:
4410  * @file: input #GFile
4411  * @cancellable: (nullable): optional #GCancellable object,
4412  *     %NULL to ignore
4413  * @error: a #GError, or %NULL
4414  *
4415  * Obtain the list of settable attributes for the file.
4416  *
4417  * Returns the type and full attribute name of all the attributes
4418  * that can be set on this file. This doesn't mean setting it will
4419  * always succeed though, you might get an access failure, or some
4420  * specific file may not support a specific attribute.
4421  *
4422  * If @cancellable is not %NULL, then the operation can be cancelled by
4423  * triggering the cancellable object from another thread. If the operation
4424  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4425  *
4426  * Returns: a #GFileAttributeInfoList describing the settable attributes.
4427  *     When you are done with it, release it with
4428  *     g_file_attribute_info_list_unref()
4429  */
4430 GFileAttributeInfoList *
g_file_query_settable_attributes(GFile * file,GCancellable * cancellable,GError ** error)4431 g_file_query_settable_attributes (GFile         *file,
4432                                   GCancellable  *cancellable,
4433                                   GError       **error)
4434 {
4435   GFileIface *iface;
4436   GError *my_error;
4437   GFileAttributeInfoList *list;
4438 
4439   g_return_val_if_fail (G_IS_FILE (file), NULL);
4440 
4441   if (g_cancellable_set_error_if_cancelled (cancellable, error))
4442     return NULL;
4443 
4444   iface = G_FILE_GET_IFACE (file);
4445 
4446   if (iface->query_settable_attributes == NULL)
4447     return g_file_attribute_info_list_new ();
4448 
4449   my_error = NULL;
4450   list = (* iface->query_settable_attributes) (file, cancellable, &my_error);
4451 
4452   if (list == NULL)
4453     {
4454       if (my_error->domain == G_IO_ERROR && my_error->code == G_IO_ERROR_NOT_SUPPORTED)
4455         {
4456           list = g_file_attribute_info_list_new ();
4457           g_error_free (my_error);
4458         }
4459       else
4460         g_propagate_error (error, my_error);
4461     }
4462 
4463   return list;
4464 }
4465 
4466 /**
4467  * g_file_query_writable_namespaces:
4468  * @file: input #GFile
4469  * @cancellable: (nullable): optional #GCancellable object,
4470  *     %NULL to ignore
4471  * @error: a #GError, or %NULL
4472  *
4473  * Obtain the list of attribute namespaces where new attributes
4474  * can be created by a user. An example of this is extended
4475  * attributes (in the "xattr" namespace).
4476  *
4477  * If @cancellable is not %NULL, then the operation can be cancelled by
4478  * triggering the cancellable object from another thread. If the operation
4479  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4480  *
4481  * Returns: a #GFileAttributeInfoList describing the writable namespaces.
4482  *     When you are done with it, release it with
4483  *     g_file_attribute_info_list_unref()
4484  */
4485 GFileAttributeInfoList *
g_file_query_writable_namespaces(GFile * file,GCancellable * cancellable,GError ** error)4486 g_file_query_writable_namespaces (GFile         *file,
4487                                   GCancellable  *cancellable,
4488                                   GError       **error)
4489 {
4490   GFileIface *iface;
4491   GError *my_error;
4492   GFileAttributeInfoList *list;
4493 
4494   g_return_val_if_fail (G_IS_FILE (file), NULL);
4495 
4496   if (g_cancellable_set_error_if_cancelled (cancellable, error))
4497     return NULL;
4498 
4499   iface = G_FILE_GET_IFACE (file);
4500 
4501   if (iface->query_writable_namespaces == NULL)
4502     return g_file_attribute_info_list_new ();
4503 
4504   my_error = NULL;
4505   list = (* iface->query_writable_namespaces) (file, cancellable, &my_error);
4506 
4507   if (list == NULL)
4508     {
4509       g_warn_if_reached();
4510       list = g_file_attribute_info_list_new ();
4511     }
4512 
4513   if (my_error != NULL)
4514     {
4515       if (my_error->domain == G_IO_ERROR && my_error->code == G_IO_ERROR_NOT_SUPPORTED)
4516         {
4517           g_error_free (my_error);
4518         }
4519       else
4520         g_propagate_error (error, my_error);
4521     }
4522 
4523   return list;
4524 }
4525 
4526 /**
4527  * g_file_set_attribute:
4528  * @file: input #GFile
4529  * @attribute: a string containing the attribute's name
4530  * @type: The type of the attribute
4531  * @value_p: (nullable): a pointer to the value (or the pointer
4532  *     itself if the type is a pointer type)
4533  * @flags: a set of #GFileQueryInfoFlags
4534  * @cancellable: (nullable): optional #GCancellable object,
4535  *     %NULL to ignore
4536  * @error: a #GError, or %NULL
4537  *
4538  * Sets an attribute in the file with attribute name @attribute to @value_p.
4539  *
4540  * Some attributes can be unset by setting @type to
4541  * %G_FILE_ATTRIBUTE_TYPE_INVALID and @value_p to %NULL.
4542  *
4543  * If @cancellable is not %NULL, then the operation can be cancelled by
4544  * triggering the cancellable object from another thread. If the operation
4545  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4546  *
4547  * Returns: %TRUE if the attribute was set, %FALSE otherwise.
4548  */
4549 gboolean
g_file_set_attribute(GFile * file,const gchar * attribute,GFileAttributeType type,gpointer value_p,GFileQueryInfoFlags flags,GCancellable * cancellable,GError ** error)4550 g_file_set_attribute (GFile                *file,
4551                       const gchar          *attribute,
4552                       GFileAttributeType    type,
4553                       gpointer              value_p,
4554                       GFileQueryInfoFlags   flags,
4555                       GCancellable         *cancellable,
4556                       GError              **error)
4557 {
4558   GFileIface *iface;
4559 
4560   g_return_val_if_fail (G_IS_FILE (file), FALSE);
4561   g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
4562 
4563   if (g_cancellable_set_error_if_cancelled (cancellable, error))
4564     return FALSE;
4565 
4566   iface = G_FILE_GET_IFACE (file);
4567 
4568   if (iface->set_attribute == NULL)
4569     {
4570       g_set_error_literal (error, G_IO_ERROR,
4571                            G_IO_ERROR_NOT_SUPPORTED,
4572                            _("Operation not supported"));
4573       return FALSE;
4574     }
4575 
4576   return (* iface->set_attribute) (file, attribute, type, value_p, flags, cancellable, error);
4577 }
4578 
4579 /**
4580  * g_file_set_attributes_from_info:
4581  * @file: input #GFile
4582  * @info: a #GFileInfo
4583  * @flags: #GFileQueryInfoFlags
4584  * @cancellable: (nullable): optional #GCancellable object,
4585  *     %NULL to ignore
4586  * @error: a #GError, or %NULL
4587  *
4588  * Tries to set all attributes in the #GFileInfo on the target
4589  * values, not stopping on the first error.
4590  *
4591  * If there is any error during this operation then @error will
4592  * be set to the first error. Error on particular fields are flagged
4593  * by setting the "status" field in the attribute value to
4594  * %G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING, which means you can
4595  * also detect further errors.
4596  *
4597  * If @cancellable is not %NULL, then the operation can be cancelled by
4598  * triggering the cancellable object from another thread. If the operation
4599  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4600  *
4601  * Returns: %FALSE if there was any error, %TRUE otherwise.
4602  */
4603 gboolean
g_file_set_attributes_from_info(GFile * file,GFileInfo * info,GFileQueryInfoFlags flags,GCancellable * cancellable,GError ** error)4604 g_file_set_attributes_from_info (GFile                *file,
4605                                  GFileInfo            *info,
4606                                  GFileQueryInfoFlags   flags,
4607                                  GCancellable         *cancellable,
4608                                  GError              **error)
4609 {
4610   GFileIface *iface;
4611 
4612   g_return_val_if_fail (G_IS_FILE (file), FALSE);
4613   g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
4614 
4615   if (g_cancellable_set_error_if_cancelled (cancellable, error))
4616     return FALSE;
4617 
4618   g_file_info_clear_status (info);
4619 
4620   iface = G_FILE_GET_IFACE (file);
4621 
4622   return (* iface->set_attributes_from_info) (file,
4623                                               info,
4624                                               flags,
4625                                               cancellable,
4626                                               error);
4627 }
4628 
4629 static gboolean
g_file_real_set_attributes_from_info(GFile * file,GFileInfo * info,GFileQueryInfoFlags flags,GCancellable * cancellable,GError ** error)4630 g_file_real_set_attributes_from_info (GFile                *file,
4631                                       GFileInfo            *info,
4632                                       GFileQueryInfoFlags   flags,
4633                                       GCancellable         *cancellable,
4634                                       GError              **error)
4635 {
4636   char **attributes;
4637   int i;
4638   gboolean res;
4639   GFileAttributeValue *value;
4640 
4641   res = TRUE;
4642 
4643   attributes = g_file_info_list_attributes (info, NULL);
4644 
4645   for (i = 0; attributes[i] != NULL; i++)
4646     {
4647       value = _g_file_info_get_attribute_value (info, attributes[i]);
4648 
4649       if (value->status != G_FILE_ATTRIBUTE_STATUS_UNSET)
4650         continue;
4651 
4652       if (!g_file_set_attribute (file, attributes[i],
4653                                  value->type, _g_file_attribute_value_peek_as_pointer (value),
4654                                  flags, cancellable, error))
4655         {
4656           value->status = G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING;
4657           res = FALSE;
4658           /* Don't set error multiple times */
4659           error = NULL;
4660         }
4661       else
4662         value->status = G_FILE_ATTRIBUTE_STATUS_SET;
4663     }
4664 
4665   g_strfreev (attributes);
4666 
4667   return res;
4668 }
4669 
4670 /**
4671  * g_file_set_attributes_async:
4672  * @file: input #GFile
4673  * @info: a #GFileInfo
4674  * @flags: a #GFileQueryInfoFlags
4675  * @io_priority: the [I/O priority][io-priority] of the request
4676  * @cancellable: (nullable): optional #GCancellable object,
4677  *     %NULL to ignore
4678  * @callback: (scope async): a #GAsyncReadyCallback
4679  * @user_data: (closure): a #gpointer
4680  *
4681  * Asynchronously sets the attributes of @file with @info.
4682  *
4683  * For more details, see g_file_set_attributes_from_info(),
4684  * which is the synchronous version of this call.
4685  *
4686  * When the operation is finished, @callback will be called.
4687  * You can then call g_file_set_attributes_finish() to get
4688  * the result of the operation.
4689  */
4690 void
g_file_set_attributes_async(GFile * file,GFileInfo * info,GFileQueryInfoFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)4691 g_file_set_attributes_async (GFile               *file,
4692                              GFileInfo           *info,
4693                              GFileQueryInfoFlags  flags,
4694                              int                  io_priority,
4695                              GCancellable        *cancellable,
4696                              GAsyncReadyCallback  callback,
4697                              gpointer             user_data)
4698 {
4699   GFileIface *iface;
4700 
4701   g_return_if_fail (G_IS_FILE (file));
4702   g_return_if_fail (G_IS_FILE_INFO (info));
4703 
4704   iface = G_FILE_GET_IFACE (file);
4705   (* iface->set_attributes_async) (file,
4706                                    info,
4707                                    flags,
4708                                    io_priority,
4709                                    cancellable,
4710                                    callback,
4711                                    user_data);
4712 }
4713 
4714 /**
4715  * g_file_set_attributes_finish:
4716  * @file: input #GFile
4717  * @result: a #GAsyncResult
4718  * @info: (out) (transfer full): a #GFileInfo
4719  * @error: a #GError, or %NULL
4720  *
4721  * Finishes setting an attribute started in g_file_set_attributes_async().
4722  *
4723  * Returns: %TRUE if the attributes were set correctly, %FALSE otherwise.
4724  */
4725 gboolean
g_file_set_attributes_finish(GFile * file,GAsyncResult * result,GFileInfo ** info,GError ** error)4726 g_file_set_attributes_finish (GFile         *file,
4727                               GAsyncResult  *result,
4728                               GFileInfo    **info,
4729                               GError       **error)
4730 {
4731   GFileIface *iface;
4732 
4733   g_return_val_if_fail (G_IS_FILE (file), FALSE);
4734   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
4735 
4736   /* No standard handling of errors here, as we must set info even
4737    * on errors
4738    */
4739   iface = G_FILE_GET_IFACE (file);
4740   return (* iface->set_attributes_finish) (file, result, info, error);
4741 }
4742 
4743 /**
4744  * g_file_set_attribute_string:
4745  * @file: input #GFile
4746  * @attribute: a string containing the attribute's name
4747  * @value: a string containing the attribute's value
4748  * @flags: #GFileQueryInfoFlags
4749  * @cancellable: (nullable): optional #GCancellable object,
4750  *     %NULL to ignore
4751  * @error: a #GError, or %NULL
4752  *
4753  * Sets @attribute of type %G_FILE_ATTRIBUTE_TYPE_STRING to @value.
4754  * If @attribute is of a different type, this operation will fail.
4755  *
4756  * If @cancellable is not %NULL, then the operation can be cancelled by
4757  * triggering the cancellable object from another thread. If the operation
4758  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4759  *
4760  * Returns: %TRUE if the @attribute was successfully set, %FALSE otherwise.
4761  */
4762 gboolean
g_file_set_attribute_string(GFile * file,const char * attribute,const char * value,GFileQueryInfoFlags flags,GCancellable * cancellable,GError ** error)4763 g_file_set_attribute_string (GFile                *file,
4764                              const char           *attribute,
4765                              const char           *value,
4766                              GFileQueryInfoFlags   flags,
4767                              GCancellable         *cancellable,
4768                              GError              **error)
4769 {
4770   return g_file_set_attribute (file, attribute,
4771                                G_FILE_ATTRIBUTE_TYPE_STRING, (gpointer)value,
4772                                flags, cancellable, error);
4773 }
4774 
4775 /**
4776  * g_file_set_attribute_byte_string:
4777  * @file: input #GFile
4778  * @attribute: a string containing the attribute's name
4779  * @value: a string containing the attribute's new value
4780  * @flags: a #GFileQueryInfoFlags
4781  * @cancellable: (nullable): optional #GCancellable object,
4782  *     %NULL to ignore
4783  * @error: a #GError, or %NULL
4784  *
4785  * Sets @attribute of type %G_FILE_ATTRIBUTE_TYPE_BYTE_STRING to @value.
4786  * If @attribute is of a different type, this operation will fail,
4787  * returning %FALSE.
4788  *
4789  * If @cancellable is not %NULL, then the operation can be cancelled by
4790  * triggering the cancellable object from another thread. If the operation
4791  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4792  *
4793  * Returns: %TRUE if the @attribute was successfully set to @value
4794  *     in the @file, %FALSE otherwise.
4795  */
4796 gboolean
g_file_set_attribute_byte_string(GFile * file,const gchar * attribute,const gchar * value,GFileQueryInfoFlags flags,GCancellable * cancellable,GError ** error)4797 g_file_set_attribute_byte_string  (GFile                *file,
4798                                    const gchar          *attribute,
4799                                    const gchar          *value,
4800                                    GFileQueryInfoFlags   flags,
4801                                    GCancellable         *cancellable,
4802                                    GError              **error)
4803 {
4804   return g_file_set_attribute (file, attribute,
4805                                G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, (gpointer)value,
4806                                flags, cancellable, error);
4807 }
4808 
4809 /**
4810  * g_file_set_attribute_uint32:
4811  * @file: input #GFile
4812  * @attribute: a string containing the attribute's name
4813  * @value: a #guint32 containing the attribute's new value
4814  * @flags: a #GFileQueryInfoFlags
4815  * @cancellable: (nullable): optional #GCancellable object,
4816  *     %NULL to ignore
4817  * @error: a #GError, or %NULL
4818  *
4819  * Sets @attribute of type %G_FILE_ATTRIBUTE_TYPE_UINT32 to @value.
4820  * If @attribute is of a different type, this operation will fail.
4821  *
4822  * If @cancellable is not %NULL, then the operation can be cancelled by
4823  * triggering the cancellable object from another thread. If the operation
4824  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4825  *
4826  * Returns: %TRUE if the @attribute was successfully set to @value
4827  *     in the @file, %FALSE otherwise.
4828  */
4829 gboolean
g_file_set_attribute_uint32(GFile * file,const gchar * attribute,guint32 value,GFileQueryInfoFlags flags,GCancellable * cancellable,GError ** error)4830 g_file_set_attribute_uint32 (GFile                *file,
4831                              const gchar          *attribute,
4832                              guint32               value,
4833                              GFileQueryInfoFlags   flags,
4834                              GCancellable         *cancellable,
4835                              GError              **error)
4836 {
4837   return g_file_set_attribute (file, attribute,
4838                                G_FILE_ATTRIBUTE_TYPE_UINT32, &value,
4839                                flags, cancellable, error);
4840 }
4841 
4842 /**
4843  * g_file_set_attribute_int32:
4844  * @file: input #GFile
4845  * @attribute: a string containing the attribute's name
4846  * @value: a #gint32 containing the attribute's new value
4847  * @flags: a #GFileQueryInfoFlags
4848  * @cancellable: (nullable): optional #GCancellable object,
4849  *     %NULL to ignore
4850  * @error: a #GError, or %NULL
4851  *
4852  * Sets @attribute of type %G_FILE_ATTRIBUTE_TYPE_INT32 to @value.
4853  * If @attribute is of a different type, this operation will fail.
4854  *
4855  * If @cancellable is not %NULL, then the operation can be cancelled by
4856  * triggering the cancellable object from another thread. If the operation
4857  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4858  *
4859  * Returns: %TRUE if the @attribute was successfully set to @value
4860  *     in the @file, %FALSE otherwise.
4861  */
4862 gboolean
g_file_set_attribute_int32(GFile * file,const gchar * attribute,gint32 value,GFileQueryInfoFlags flags,GCancellable * cancellable,GError ** error)4863 g_file_set_attribute_int32 (GFile                *file,
4864                             const gchar          *attribute,
4865                             gint32                value,
4866                             GFileQueryInfoFlags   flags,
4867                             GCancellable         *cancellable,
4868                             GError              **error)
4869 {
4870   return g_file_set_attribute (file, attribute,
4871                                G_FILE_ATTRIBUTE_TYPE_INT32, &value,
4872                                flags, cancellable, error);
4873 }
4874 
4875 /**
4876  * g_file_set_attribute_uint64:
4877  * @file: input #GFile
4878  * @attribute: a string containing the attribute's name
4879  * @value: a #guint64 containing the attribute's new value
4880  * @flags: a #GFileQueryInfoFlags
4881  * @cancellable: (nullable): optional #GCancellable object,
4882  *     %NULL to ignore
4883  * @error: a #GError, or %NULL
4884  *
4885  * Sets @attribute of type %G_FILE_ATTRIBUTE_TYPE_UINT64 to @value.
4886  * If @attribute is of a different type, this operation will fail.
4887  *
4888  * If @cancellable is not %NULL, then the operation can be cancelled by
4889  * triggering the cancellable object from another thread. If the operation
4890  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4891  *
4892  * Returns: %TRUE if the @attribute was successfully set to @value
4893  *     in the @file, %FALSE otherwise.
4894  */
4895 gboolean
g_file_set_attribute_uint64(GFile * file,const gchar * attribute,guint64 value,GFileQueryInfoFlags flags,GCancellable * cancellable,GError ** error)4896 g_file_set_attribute_uint64 (GFile                *file,
4897                              const gchar          *attribute,
4898                              guint64               value,
4899                              GFileQueryInfoFlags   flags,
4900                              GCancellable         *cancellable,
4901                              GError              **error)
4902  {
4903   return g_file_set_attribute (file, attribute,
4904                                G_FILE_ATTRIBUTE_TYPE_UINT64, &value,
4905                                flags, cancellable, error);
4906 }
4907 
4908 /**
4909  * g_file_set_attribute_int64:
4910  * @file: input #GFile
4911  * @attribute: a string containing the attribute's name
4912  * @value: a #guint64 containing the attribute's new value
4913  * @flags: a #GFileQueryInfoFlags
4914  * @cancellable: (nullable): optional #GCancellable object,
4915  *     %NULL to ignore
4916  * @error: a #GError, or %NULL
4917  *
4918  * Sets @attribute of type %G_FILE_ATTRIBUTE_TYPE_INT64 to @value.
4919  * If @attribute is of a different type, this operation will fail.
4920  *
4921  * If @cancellable is not %NULL, then the operation can be cancelled by
4922  * triggering the cancellable object from another thread. If the operation
4923  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4924  *
4925  * Returns: %TRUE if the @attribute was successfully set, %FALSE otherwise.
4926  */
4927 gboolean
g_file_set_attribute_int64(GFile * file,const gchar * attribute,gint64 value,GFileQueryInfoFlags flags,GCancellable * cancellable,GError ** error)4928 g_file_set_attribute_int64 (GFile                *file,
4929                             const gchar          *attribute,
4930                             gint64                value,
4931                             GFileQueryInfoFlags   flags,
4932                             GCancellable         *cancellable,
4933                             GError              **error)
4934 {
4935   return g_file_set_attribute (file, attribute,
4936                                G_FILE_ATTRIBUTE_TYPE_INT64, &value,
4937                                flags, cancellable, error);
4938 }
4939 
4940 /**
4941  * g_file_mount_mountable:
4942  * @file: input #GFile
4943  * @flags: flags affecting the operation
4944  * @mount_operation: (nullable): a #GMountOperation,
4945  *     or %NULL to avoid user interaction
4946  * @cancellable: (nullable): optional #GCancellable object,
4947  *     %NULL to ignore
4948  * @callback: (scope async) (nullable): a #GAsyncReadyCallback to call
4949  *     when the request is satisfied, or %NULL
4950  * @user_data: (closure): the data to pass to callback function
4951  *
4952  * Mounts a file of type G_FILE_TYPE_MOUNTABLE.
4953  * Using @mount_operation, you can request callbacks when, for instance,
4954  * passwords are needed during authentication.
4955  *
4956  * If @cancellable is not %NULL, then the operation can be cancelled by
4957  * triggering the cancellable object from another thread. If the operation
4958  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
4959  *
4960  * When the operation is finished, @callback will be called.
4961  * You can then call g_file_mount_mountable_finish() to get
4962  * the result of the operation.
4963  */
4964 void
g_file_mount_mountable(GFile * file,GMountMountFlags flags,GMountOperation * mount_operation,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)4965 g_file_mount_mountable (GFile               *file,
4966                         GMountMountFlags     flags,
4967                         GMountOperation     *mount_operation,
4968                         GCancellable        *cancellable,
4969                         GAsyncReadyCallback  callback,
4970                         gpointer             user_data)
4971 {
4972   GFileIface *iface;
4973 
4974   g_return_if_fail (G_IS_FILE (file));
4975 
4976   iface = G_FILE_GET_IFACE (file);
4977 
4978   if (iface->mount_mountable == NULL)
4979     {
4980       g_task_report_new_error (file, callback, user_data,
4981                                g_file_mount_mountable,
4982                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
4983                                _("Operation not supported"));
4984       return;
4985     }
4986 
4987   (* iface->mount_mountable) (file,
4988                               flags,
4989                               mount_operation,
4990                               cancellable,
4991                               callback,
4992                               user_data);
4993 }
4994 
4995 /**
4996  * g_file_mount_mountable_finish:
4997  * @file: input #GFile
4998  * @result: a #GAsyncResult
4999  * @error: a #GError, or %NULL
5000  *
5001  * Finishes a mount operation. See g_file_mount_mountable() for details.
5002  *
5003  * Finish an asynchronous mount operation that was started
5004  * with g_file_mount_mountable().
5005  *
5006  * Returns: (transfer full): a #GFile or %NULL on error.
5007  *     Free the returned object with g_object_unref().
5008  */
5009 GFile *
g_file_mount_mountable_finish(GFile * file,GAsyncResult * result,GError ** error)5010 g_file_mount_mountable_finish (GFile         *file,
5011                                GAsyncResult  *result,
5012                                GError       **error)
5013 {
5014   GFileIface *iface;
5015 
5016   g_return_val_if_fail (G_IS_FILE (file), NULL);
5017   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
5018 
5019   if (g_async_result_legacy_propagate_error (result, error))
5020     return NULL;
5021   else if (g_async_result_is_tagged (result, g_file_mount_mountable))
5022     return g_task_propagate_pointer (G_TASK (result), error);
5023 
5024   iface = G_FILE_GET_IFACE (file);
5025   return (* iface->mount_mountable_finish) (file, result, error);
5026 }
5027 
5028 /**
5029  * g_file_unmount_mountable:
5030  * @file: input #GFile
5031  * @flags: flags affecting the operation
5032  * @cancellable: (nullable): optional #GCancellable object,
5033  *     %NULL to ignore
5034  * @callback: (scope async) (nullable): a #GAsyncReadyCallback to call
5035  *     when the request is satisfied, or %NULL
5036  * @user_data: (closure): the data to pass to callback function
5037  *
5038  * Unmounts a file of type G_FILE_TYPE_MOUNTABLE.
5039  *
5040  * If @cancellable is not %NULL, then the operation can be cancelled by
5041  * triggering the cancellable object from another thread. If the operation
5042  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
5043  *
5044  * When the operation is finished, @callback will be called.
5045  * You can then call g_file_unmount_mountable_finish() to get
5046  * the result of the operation.
5047  *
5048  * Deprecated: 2.22: Use g_file_unmount_mountable_with_operation() instead.
5049  */
5050 void
g_file_unmount_mountable(GFile * file,GMountUnmountFlags flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)5051 g_file_unmount_mountable (GFile               *file,
5052                           GMountUnmountFlags   flags,
5053                           GCancellable        *cancellable,
5054                           GAsyncReadyCallback  callback,
5055                           gpointer             user_data)
5056 {
5057   GFileIface *iface;
5058 
5059   g_return_if_fail (G_IS_FILE (file));
5060 
5061   iface = G_FILE_GET_IFACE (file);
5062 
5063   if (iface->unmount_mountable == NULL)
5064     {
5065       g_task_report_new_error (file, callback, user_data,
5066                                g_file_unmount_mountable_with_operation,
5067                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
5068                                _("Operation not supported"));
5069       return;
5070     }
5071 
5072   (* iface->unmount_mountable) (file,
5073                                 flags,
5074                                 cancellable,
5075                                 callback,
5076                                 user_data);
5077 }
5078 
5079 /**
5080  * g_file_unmount_mountable_finish:
5081  * @file: input #GFile
5082  * @result: a #GAsyncResult
5083  * @error: a #GError, or %NULL
5084  *
5085  * Finishes an unmount operation, see g_file_unmount_mountable() for details.
5086  *
5087  * Finish an asynchronous unmount operation that was started
5088  * with g_file_unmount_mountable().
5089  *
5090  * Returns: %TRUE if the operation finished successfully.
5091  *     %FALSE otherwise.
5092  *
5093  * Deprecated: 2.22: Use g_file_unmount_mountable_with_operation_finish()
5094  *     instead.
5095  */
5096 gboolean
g_file_unmount_mountable_finish(GFile * file,GAsyncResult * result,GError ** error)5097 g_file_unmount_mountable_finish (GFile         *file,
5098                                  GAsyncResult  *result,
5099                                  GError       **error)
5100 {
5101   GFileIface *iface;
5102 
5103   g_return_val_if_fail (G_IS_FILE (file), FALSE);
5104   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
5105 
5106   if (g_async_result_legacy_propagate_error (result, error))
5107     return FALSE;
5108   else if (g_async_result_is_tagged (result, g_file_unmount_mountable_with_operation))
5109     return g_task_propagate_boolean (G_TASK (result), error);
5110 
5111   iface = G_FILE_GET_IFACE (file);
5112   return (* iface->unmount_mountable_finish) (file, result, error);
5113 }
5114 
5115 /**
5116  * g_file_unmount_mountable_with_operation:
5117  * @file: input #GFile
5118  * @flags: flags affecting the operation
5119  * @mount_operation: (nullable): a #GMountOperation,
5120  *     or %NULL to avoid user interaction
5121  * @cancellable: (nullable): optional #GCancellable object,
5122  *     %NULL to ignore
5123  * @callback: (scope async) (nullable): a #GAsyncReadyCallback to call
5124  *     when the request is satisfied, or %NULL
5125  * @user_data: (closure): the data to pass to callback function
5126  *
5127  * Unmounts a file of type #G_FILE_TYPE_MOUNTABLE.
5128  *
5129  * If @cancellable is not %NULL, then the operation can be cancelled by
5130  * triggering the cancellable object from another thread. If the operation
5131  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
5132  *
5133  * When the operation is finished, @callback will be called.
5134  * You can then call g_file_unmount_mountable_finish() to get
5135  * the result of the operation.
5136  *
5137  * Since: 2.22
5138  */
5139 void
g_file_unmount_mountable_with_operation(GFile * file,GMountUnmountFlags flags,GMountOperation * mount_operation,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)5140 g_file_unmount_mountable_with_operation (GFile               *file,
5141                                          GMountUnmountFlags   flags,
5142                                          GMountOperation     *mount_operation,
5143                                          GCancellable        *cancellable,
5144                                          GAsyncReadyCallback  callback,
5145                                          gpointer             user_data)
5146 {
5147   GFileIface *iface;
5148 
5149   g_return_if_fail (G_IS_FILE (file));
5150 
5151   iface = G_FILE_GET_IFACE (file);
5152 
5153   if (iface->unmount_mountable == NULL && iface->unmount_mountable_with_operation == NULL)
5154     {
5155       g_task_report_new_error (file, callback, user_data,
5156                                g_file_unmount_mountable_with_operation,
5157                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
5158                                _("Operation not supported"));
5159       return;
5160     }
5161 
5162   if (iface->unmount_mountable_with_operation != NULL)
5163     (* iface->unmount_mountable_with_operation) (file,
5164                                                  flags,
5165                                                  mount_operation,
5166                                                  cancellable,
5167                                                  callback,
5168                                                  user_data);
5169   else
5170     (* iface->unmount_mountable) (file,
5171                                   flags,
5172                                   cancellable,
5173                                   callback,
5174                                   user_data);
5175 }
5176 
5177 /**
5178  * g_file_unmount_mountable_with_operation_finish:
5179  * @file: input #GFile
5180  * @result: a #GAsyncResult
5181  * @error: a #GError, or %NULL
5182  *
5183  * Finishes an unmount operation,
5184  * see g_file_unmount_mountable_with_operation() for details.
5185  *
5186  * Finish an asynchronous unmount operation that was started
5187  * with g_file_unmount_mountable_with_operation().
5188  *
5189  * Returns: %TRUE if the operation finished successfully.
5190  *     %FALSE otherwise.
5191  *
5192  * Since: 2.22
5193  */
5194 gboolean
g_file_unmount_mountable_with_operation_finish(GFile * file,GAsyncResult * result,GError ** error)5195 g_file_unmount_mountable_with_operation_finish (GFile         *file,
5196                                                 GAsyncResult  *result,
5197                                                 GError       **error)
5198 {
5199   GFileIface *iface;
5200 
5201   g_return_val_if_fail (G_IS_FILE (file), FALSE);
5202   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
5203 
5204   if (g_async_result_legacy_propagate_error (result, error))
5205     return FALSE;
5206   else if (g_async_result_is_tagged (result, g_file_unmount_mountable_with_operation))
5207     return g_task_propagate_boolean (G_TASK (result), error);
5208 
5209   iface = G_FILE_GET_IFACE (file);
5210   if (iface->unmount_mountable_with_operation_finish != NULL)
5211     return (* iface->unmount_mountable_with_operation_finish) (file, result, error);
5212   else
5213     return (* iface->unmount_mountable_finish) (file, result, error);
5214 }
5215 
5216 /**
5217  * g_file_eject_mountable:
5218  * @file: input #GFile
5219  * @flags: flags affecting the operation
5220  * @cancellable: (nullable): optional #GCancellable object,
5221  *     %NULL to ignore
5222  * @callback: (scope async) (nullable): a #GAsyncReadyCallback to call
5223  *     when the request is satisfied, or %NULL
5224  * @user_data: (closure): the data to pass to callback function
5225  *
5226  * Starts an asynchronous eject on a mountable.
5227  * When this operation has completed, @callback will be called with
5228  * @user_user data, and the operation can be finalized with
5229  * g_file_eject_mountable_finish().
5230  *
5231  * If @cancellable is not %NULL, then the operation can be cancelled by
5232  * triggering the cancellable object from another thread. If the operation
5233  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
5234  *
5235  * Deprecated: 2.22: Use g_file_eject_mountable_with_operation() instead.
5236  */
5237 void
g_file_eject_mountable(GFile * file,GMountUnmountFlags flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)5238 g_file_eject_mountable (GFile               *file,
5239                         GMountUnmountFlags   flags,
5240                         GCancellable        *cancellable,
5241                         GAsyncReadyCallback  callback,
5242                         gpointer             user_data)
5243 {
5244   GFileIface *iface;
5245 
5246   g_return_if_fail (G_IS_FILE (file));
5247 
5248   iface = G_FILE_GET_IFACE (file);
5249 
5250   if (iface->eject_mountable == NULL)
5251     {
5252       g_task_report_new_error (file, callback, user_data,
5253                                g_file_eject_mountable_with_operation,
5254                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
5255                                _("Operation not supported"));
5256       return;
5257     }
5258 
5259   (* iface->eject_mountable) (file,
5260                               flags,
5261                               cancellable,
5262                               callback,
5263                               user_data);
5264 }
5265 
5266 /**
5267  * g_file_eject_mountable_finish:
5268  * @file: input #GFile
5269  * @result: a #GAsyncResult
5270  * @error: a #GError, or %NULL
5271  *
5272  * Finishes an asynchronous eject operation started by
5273  * g_file_eject_mountable().
5274  *
5275  * Returns: %TRUE if the @file was ejected successfully.
5276  *     %FALSE otherwise.
5277  *
5278  * Deprecated: 2.22: Use g_file_eject_mountable_with_operation_finish()
5279  *     instead.
5280  */
5281 gboolean
g_file_eject_mountable_finish(GFile * file,GAsyncResult * result,GError ** error)5282 g_file_eject_mountable_finish (GFile         *file,
5283                                GAsyncResult  *result,
5284                                GError       **error)
5285 {
5286   GFileIface *iface;
5287 
5288   g_return_val_if_fail (G_IS_FILE (file), FALSE);
5289   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
5290 
5291   if (g_async_result_legacy_propagate_error (result, error))
5292     return FALSE;
5293   else if (g_async_result_is_tagged (result, g_file_eject_mountable_with_operation))
5294     return g_task_propagate_boolean (G_TASK (result), error);
5295 
5296   iface = G_FILE_GET_IFACE (file);
5297   return (* iface->eject_mountable_finish) (file, result, error);
5298 }
5299 
5300 /**
5301  * g_file_eject_mountable_with_operation:
5302  * @file: input #GFile
5303  * @flags: flags affecting the operation
5304  * @mount_operation: (nullable): a #GMountOperation,
5305  *     or %NULL to avoid user interaction
5306  * @cancellable: (nullable): optional #GCancellable object,
5307  *     %NULL to ignore
5308  * @callback: (scope async) (nullable): a #GAsyncReadyCallback to call
5309  *     when the request is satisfied, or %NULL
5310  * @user_data: (closure): the data to pass to callback function
5311  *
5312  * Starts an asynchronous eject on a mountable.
5313  * When this operation has completed, @callback will be called with
5314  * @user_user data, and the operation can be finalized with
5315  * g_file_eject_mountable_with_operation_finish().
5316  *
5317  * If @cancellable is not %NULL, then the operation can be cancelled by
5318  * triggering the cancellable object from another thread. If the operation
5319  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
5320  *
5321  * Since: 2.22
5322  */
5323 void
g_file_eject_mountable_with_operation(GFile * file,GMountUnmountFlags flags,GMountOperation * mount_operation,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)5324 g_file_eject_mountable_with_operation (GFile               *file,
5325                                        GMountUnmountFlags   flags,
5326                                        GMountOperation     *mount_operation,
5327                                        GCancellable        *cancellable,
5328                                        GAsyncReadyCallback  callback,
5329                                        gpointer             user_data)
5330 {
5331   GFileIface *iface;
5332 
5333   g_return_if_fail (G_IS_FILE (file));
5334 
5335   iface = G_FILE_GET_IFACE (file);
5336 
5337   if (iface->eject_mountable == NULL && iface->eject_mountable_with_operation == NULL)
5338     {
5339       g_task_report_new_error (file, callback, user_data,
5340                                g_file_eject_mountable_with_operation,
5341                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
5342                                _("Operation not supported"));
5343       return;
5344     }
5345 
5346   if (iface->eject_mountable_with_operation != NULL)
5347     (* iface->eject_mountable_with_operation) (file,
5348                                                flags,
5349                                                mount_operation,
5350                                                cancellable,
5351                                                callback,
5352                                                user_data);
5353   else
5354     (* iface->eject_mountable) (file,
5355                                 flags,
5356                                 cancellable,
5357                                 callback,
5358                                 user_data);
5359 }
5360 
5361 /**
5362  * g_file_eject_mountable_with_operation_finish:
5363  * @file: input #GFile
5364  * @result: a #GAsyncResult
5365  * @error: a #GError, or %NULL
5366  *
5367  * Finishes an asynchronous eject operation started by
5368  * g_file_eject_mountable_with_operation().
5369  *
5370  * Returns: %TRUE if the @file was ejected successfully.
5371  *     %FALSE otherwise.
5372  *
5373  * Since: 2.22
5374  */
5375 gboolean
g_file_eject_mountable_with_operation_finish(GFile * file,GAsyncResult * result,GError ** error)5376 g_file_eject_mountable_with_operation_finish (GFile         *file,
5377                                               GAsyncResult  *result,
5378                                               GError       **error)
5379 {
5380   GFileIface *iface;
5381 
5382   g_return_val_if_fail (G_IS_FILE (file), FALSE);
5383   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
5384 
5385   if (g_async_result_legacy_propagate_error (result, error))
5386     return FALSE;
5387   else if (g_async_result_is_tagged (result, g_file_eject_mountable_with_operation))
5388     return g_task_propagate_boolean (G_TASK (result), error);
5389 
5390   iface = G_FILE_GET_IFACE (file);
5391   if (iface->eject_mountable_with_operation_finish != NULL)
5392     return (* iface->eject_mountable_with_operation_finish) (file, result, error);
5393   else
5394     return (* iface->eject_mountable_finish) (file, result, error);
5395 }
5396 
5397 /**
5398  * g_file_monitor_directory:
5399  * @file: input #GFile
5400  * @flags: a set of #GFileMonitorFlags
5401  * @cancellable: (nullable): optional #GCancellable object,
5402  *     %NULL to ignore
5403  * @error: a #GError, or %NULL
5404  *
5405  * Obtains a directory monitor for the given file.
5406  * This may fail if directory monitoring is not supported.
5407  *
5408  * If @cancellable is not %NULL, then the operation can be cancelled by
5409  * triggering the cancellable object from another thread. If the operation
5410  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
5411  *
5412  * It does not make sense for @flags to contain
5413  * %G_FILE_MONITOR_WATCH_HARD_LINKS, since hard links can not be made to
5414  * directories.  It is not possible to monitor all the files in a
5415  * directory for changes made via hard links; if you want to do this then
5416  * you must register individual watches with g_file_monitor().
5417  *
5418  * Virtual: monitor_dir
5419  * Returns: (transfer full): a #GFileMonitor for the given @file,
5420  *     or %NULL on error.
5421  *     Free the returned object with g_object_unref().
5422  */
5423 GFileMonitor *
g_file_monitor_directory(GFile * file,GFileMonitorFlags flags,GCancellable * cancellable,GError ** error)5424 g_file_monitor_directory (GFile              *file,
5425                           GFileMonitorFlags   flags,
5426                           GCancellable       *cancellable,
5427                           GError            **error)
5428 {
5429   GFileIface *iface;
5430 
5431   g_return_val_if_fail (G_IS_FILE (file), NULL);
5432   g_return_val_if_fail (~flags & G_FILE_MONITOR_WATCH_HARD_LINKS, NULL);
5433 
5434   if (g_cancellable_set_error_if_cancelled (cancellable, error))
5435     return NULL;
5436 
5437   iface = G_FILE_GET_IFACE (file);
5438 
5439   if (iface->monitor_dir == NULL)
5440     {
5441       g_set_error_literal (error, G_IO_ERROR,
5442                            G_IO_ERROR_NOT_SUPPORTED,
5443                            _("Operation not supported"));
5444       return NULL;
5445     }
5446 
5447   return (* iface->monitor_dir) (file, flags, cancellable, error);
5448 }
5449 
5450 /**
5451  * g_file_monitor_file:
5452  * @file: input #GFile
5453  * @flags: a set of #GFileMonitorFlags
5454  * @cancellable: (nullable): optional #GCancellable object,
5455  *     %NULL to ignore
5456  * @error: a #GError, or %NULL
5457  *
5458  * Obtains a file monitor for the given file. If no file notification
5459  * mechanism exists, then regular polling of the file is used.
5460  *
5461  * If @cancellable is not %NULL, then the operation can be cancelled by
5462  * triggering the cancellable object from another thread. If the operation
5463  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
5464  *
5465  * If @flags contains %G_FILE_MONITOR_WATCH_HARD_LINKS then the monitor
5466  * will also attempt to report changes made to the file via another
5467  * filename (ie, a hard link). Without this flag, you can only rely on
5468  * changes made through the filename contained in @file to be
5469  * reported. Using this flag may result in an increase in resource
5470  * usage, and may not have any effect depending on the #GFileMonitor
5471  * backend and/or filesystem type.
5472  *
5473  * Returns: (transfer full): a #GFileMonitor for the given @file,
5474  *     or %NULL on error.
5475  *     Free the returned object with g_object_unref().
5476  */
5477 GFileMonitor *
g_file_monitor_file(GFile * file,GFileMonitorFlags flags,GCancellable * cancellable,GError ** error)5478 g_file_monitor_file (GFile              *file,
5479                      GFileMonitorFlags   flags,
5480                      GCancellable       *cancellable,
5481                      GError            **error)
5482 {
5483   GFileIface *iface;
5484   GFileMonitor *monitor;
5485 
5486   g_return_val_if_fail (G_IS_FILE (file), NULL);
5487 
5488   if (g_cancellable_set_error_if_cancelled (cancellable, error))
5489     return NULL;
5490 
5491   iface = G_FILE_GET_IFACE (file);
5492 
5493   monitor = NULL;
5494 
5495   if (iface->monitor_file)
5496     monitor = (* iface->monitor_file) (file, flags, cancellable, NULL);
5497 
5498   /* Fallback to polling */
5499   if (monitor == NULL)
5500     monitor = _g_poll_file_monitor_new (file);
5501 
5502   return monitor;
5503 }
5504 
5505 /**
5506  * g_file_monitor:
5507  * @file: input #GFile
5508  * @flags: a set of #GFileMonitorFlags
5509  * @cancellable: (nullable): optional #GCancellable object,
5510  *     %NULL to ignore
5511  * @error: a #GError, or %NULL
5512  *
5513  * Obtains a file or directory monitor for the given file,
5514  * depending on the type of the file.
5515  *
5516  * If @cancellable is not %NULL, then the operation can be cancelled by
5517  * triggering the cancellable object from another thread. If the operation
5518  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
5519  *
5520  * Returns: (transfer full): a #GFileMonitor for the given @file,
5521  *     or %NULL on error.
5522  *     Free the returned object with g_object_unref().
5523  *
5524  * Since: 2.18
5525  */
5526 GFileMonitor *
g_file_monitor(GFile * file,GFileMonitorFlags flags,GCancellable * cancellable,GError ** error)5527 g_file_monitor (GFile              *file,
5528                 GFileMonitorFlags   flags,
5529                 GCancellable       *cancellable,
5530                 GError            **error)
5531 {
5532   if (g_file_query_file_type (file, 0, cancellable) == G_FILE_TYPE_DIRECTORY)
5533     return g_file_monitor_directory (file,
5534                                      flags & ~G_FILE_MONITOR_WATCH_HARD_LINKS,
5535                                      cancellable, error);
5536   else
5537     return g_file_monitor_file (file, flags, cancellable, error);
5538 }
5539 
5540 /********************************************
5541  *   Default implementation of async ops    *
5542  ********************************************/
5543 
5544 typedef struct {
5545   char *attributes;
5546   GFileQueryInfoFlags flags;
5547 } QueryInfoAsyncData;
5548 
5549 static void
query_info_data_free(QueryInfoAsyncData * data)5550 query_info_data_free (QueryInfoAsyncData *data)
5551 {
5552   g_free (data->attributes);
5553   g_free (data);
5554 }
5555 
5556 static void
query_info_async_thread(GTask * task,gpointer object,gpointer task_data,GCancellable * cancellable)5557 query_info_async_thread (GTask         *task,
5558                          gpointer       object,
5559                          gpointer       task_data,
5560                          GCancellable  *cancellable)
5561 {
5562   QueryInfoAsyncData *data = task_data;
5563   GFileInfo *info;
5564   GError *error = NULL;
5565 
5566   info = g_file_query_info (G_FILE (object), data->attributes, data->flags, cancellable, &error);
5567   if (info)
5568     g_task_return_pointer (task, info, g_object_unref);
5569   else
5570     g_task_return_error (task, error);
5571 }
5572 
5573 static void
g_file_real_query_info_async(GFile * file,const char * attributes,GFileQueryInfoFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)5574 g_file_real_query_info_async (GFile               *file,
5575                               const char          *attributes,
5576                               GFileQueryInfoFlags  flags,
5577                               int                  io_priority,
5578                               GCancellable        *cancellable,
5579                               GAsyncReadyCallback  callback,
5580                               gpointer             user_data)
5581 {
5582   GTask *task;
5583   QueryInfoAsyncData *data;
5584 
5585   data = g_new0 (QueryInfoAsyncData, 1);
5586   data->attributes = g_strdup (attributes);
5587   data->flags = flags;
5588 
5589   task = g_task_new (file, cancellable, callback, user_data);
5590   g_task_set_source_tag (task, g_file_real_query_info_async);
5591   g_task_set_task_data (task, data, (GDestroyNotify)query_info_data_free);
5592   g_task_set_priority (task, io_priority);
5593   g_task_run_in_thread (task, query_info_async_thread);
5594   g_object_unref (task);
5595 }
5596 
5597 static GFileInfo *
g_file_real_query_info_finish(GFile * file,GAsyncResult * res,GError ** error)5598 g_file_real_query_info_finish (GFile         *file,
5599                                GAsyncResult  *res,
5600                                GError       **error)
5601 {
5602   g_return_val_if_fail (g_task_is_valid (res, file), NULL);
5603 
5604   return g_task_propagate_pointer (G_TASK (res), error);
5605 }
5606 
5607 static void
query_filesystem_info_async_thread(GTask * task,gpointer object,gpointer task_data,GCancellable * cancellable)5608 query_filesystem_info_async_thread (GTask         *task,
5609                                     gpointer       object,
5610                                     gpointer       task_data,
5611                                     GCancellable  *cancellable)
5612 {
5613   const char *attributes = task_data;
5614   GFileInfo *info;
5615   GError *error = NULL;
5616 
5617   info = g_file_query_filesystem_info (G_FILE (object), attributes, cancellable, &error);
5618   if (info)
5619     g_task_return_pointer (task, info, g_object_unref);
5620   else
5621     g_task_return_error (task, error);
5622 }
5623 
5624 static void
g_file_real_query_filesystem_info_async(GFile * file,const char * attributes,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)5625 g_file_real_query_filesystem_info_async (GFile               *file,
5626                                          const char          *attributes,
5627                                          int                  io_priority,
5628                                          GCancellable        *cancellable,
5629                                          GAsyncReadyCallback  callback,
5630                                          gpointer             user_data)
5631 {
5632   GTask *task;
5633 
5634   task = g_task_new (file, cancellable, callback, user_data);
5635   g_task_set_source_tag (task, g_file_real_query_filesystem_info_async);
5636   g_task_set_task_data (task, g_strdup (attributes), g_free);
5637   g_task_set_priority (task, io_priority);
5638   g_task_run_in_thread (task, query_filesystem_info_async_thread);
5639   g_object_unref (task);
5640 }
5641 
5642 static GFileInfo *
g_file_real_query_filesystem_info_finish(GFile * file,GAsyncResult * res,GError ** error)5643 g_file_real_query_filesystem_info_finish (GFile         *file,
5644                                           GAsyncResult  *res,
5645                                           GError       **error)
5646 {
5647   g_return_val_if_fail (g_task_is_valid (res, file), NULL);
5648 
5649   return g_task_propagate_pointer (G_TASK (res), error);
5650 }
5651 
5652 static void
enumerate_children_async_thread(GTask * task,gpointer object,gpointer task_data,GCancellable * cancellable)5653 enumerate_children_async_thread (GTask         *task,
5654                                  gpointer       object,
5655                                  gpointer       task_data,
5656                                  GCancellable  *cancellable)
5657 {
5658   QueryInfoAsyncData *data = task_data;
5659   GFileEnumerator *enumerator;
5660   GError *error = NULL;
5661 
5662   enumerator = g_file_enumerate_children (G_FILE (object), data->attributes, data->flags, cancellable, &error);
5663   if (error)
5664     g_task_return_error (task, error);
5665   else
5666     g_task_return_pointer (task, enumerator, g_object_unref);
5667 }
5668 
5669 static void
g_file_real_enumerate_children_async(GFile * file,const char * attributes,GFileQueryInfoFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)5670 g_file_real_enumerate_children_async (GFile               *file,
5671                                       const char          *attributes,
5672                                       GFileQueryInfoFlags  flags,
5673                                       int                  io_priority,
5674                                       GCancellable        *cancellable,
5675                                       GAsyncReadyCallback  callback,
5676                                       gpointer             user_data)
5677 {
5678   GTask *task;
5679   QueryInfoAsyncData *data;
5680 
5681   data = g_new0 (QueryInfoAsyncData, 1);
5682   data->attributes = g_strdup (attributes);
5683   data->flags = flags;
5684 
5685   task = g_task_new (file, cancellable, callback, user_data);
5686   g_task_set_source_tag (task, g_file_real_enumerate_children_async);
5687   g_task_set_task_data (task, data, (GDestroyNotify)query_info_data_free);
5688   g_task_set_priority (task, io_priority);
5689   g_task_run_in_thread (task, enumerate_children_async_thread);
5690   g_object_unref (task);
5691 }
5692 
5693 static GFileEnumerator *
g_file_real_enumerate_children_finish(GFile * file,GAsyncResult * res,GError ** error)5694 g_file_real_enumerate_children_finish (GFile         *file,
5695                                        GAsyncResult  *res,
5696                                        GError       **error)
5697 {
5698   g_return_val_if_fail (g_task_is_valid (res, file), NULL);
5699 
5700   return g_task_propagate_pointer (G_TASK (res), error);
5701 }
5702 
5703 static void
open_read_async_thread(GTask * task,gpointer object,gpointer task_data,GCancellable * cancellable)5704 open_read_async_thread (GTask         *task,
5705                         gpointer       object,
5706                         gpointer       task_data,
5707                         GCancellable  *cancellable)
5708 {
5709   GFileInputStream *stream;
5710   GError *error = NULL;
5711 
5712   stream = g_file_read (G_FILE (object), cancellable, &error);
5713   if (stream)
5714     g_task_return_pointer (task, stream, g_object_unref);
5715   else
5716     g_task_return_error (task, error);
5717 }
5718 
5719 static void
g_file_real_read_async(GFile * file,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)5720 g_file_real_read_async (GFile               *file,
5721                         int                  io_priority,
5722                         GCancellable        *cancellable,
5723                         GAsyncReadyCallback  callback,
5724                         gpointer             user_data)
5725 {
5726   GTask *task;
5727 
5728   task = g_task_new (file, cancellable, callback, user_data);
5729   g_task_set_source_tag (task, g_file_real_read_async);
5730   g_task_set_priority (task, io_priority);
5731   g_task_run_in_thread (task, open_read_async_thread);
5732   g_object_unref (task);
5733 }
5734 
5735 static GFileInputStream *
g_file_real_read_finish(GFile * file,GAsyncResult * res,GError ** error)5736 g_file_real_read_finish (GFile         *file,
5737                          GAsyncResult  *res,
5738                          GError       **error)
5739 {
5740   g_return_val_if_fail (g_task_is_valid (res, file), NULL);
5741 
5742   return g_task_propagate_pointer (G_TASK (res), error);
5743 }
5744 
5745 static void
append_to_async_thread(GTask * task,gpointer source_object,gpointer task_data,GCancellable * cancellable)5746 append_to_async_thread (GTask         *task,
5747                         gpointer       source_object,
5748                         gpointer       task_data,
5749                         GCancellable  *cancellable)
5750 {
5751   GFileCreateFlags *data = task_data;
5752   GFileOutputStream *stream;
5753   GError *error = NULL;
5754 
5755   stream = g_file_append_to (G_FILE (source_object), *data, cancellable, &error);
5756   if (stream)
5757     g_task_return_pointer (task, stream, g_object_unref);
5758   else
5759     g_task_return_error (task, error);
5760 }
5761 
5762 static void
g_file_real_append_to_async(GFile * file,GFileCreateFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)5763 g_file_real_append_to_async (GFile               *file,
5764                              GFileCreateFlags     flags,
5765                              int                  io_priority,
5766                              GCancellable        *cancellable,
5767                              GAsyncReadyCallback  callback,
5768                              gpointer             user_data)
5769 {
5770   GFileCreateFlags *data;
5771   GTask *task;
5772 
5773   data = g_new0 (GFileCreateFlags, 1);
5774   *data = flags;
5775 
5776   task = g_task_new (file, cancellable, callback, user_data);
5777   g_task_set_source_tag (task, g_file_real_append_to_async);
5778   g_task_set_task_data (task, data, g_free);
5779   g_task_set_priority (task, io_priority);
5780 
5781   g_task_run_in_thread (task, append_to_async_thread);
5782   g_object_unref (task);
5783 }
5784 
5785 static GFileOutputStream *
g_file_real_append_to_finish(GFile * file,GAsyncResult * res,GError ** error)5786 g_file_real_append_to_finish (GFile         *file,
5787                               GAsyncResult  *res,
5788                               GError       **error)
5789 {
5790   g_return_val_if_fail (g_task_is_valid (res, file), NULL);
5791 
5792   return g_task_propagate_pointer (G_TASK (res), error);
5793 }
5794 
5795 static void
create_async_thread(GTask * task,gpointer source_object,gpointer task_data,GCancellable * cancellable)5796 create_async_thread (GTask         *task,
5797                      gpointer       source_object,
5798                      gpointer       task_data,
5799                      GCancellable  *cancellable)
5800 {
5801   GFileCreateFlags *data = task_data;
5802   GFileOutputStream *stream;
5803   GError *error = NULL;
5804 
5805   stream = g_file_create (G_FILE (source_object), *data, cancellable, &error);
5806   if (stream)
5807     g_task_return_pointer (task, stream, g_object_unref);
5808   else
5809     g_task_return_error (task, error);
5810 }
5811 
5812 static void
g_file_real_create_async(GFile * file,GFileCreateFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)5813 g_file_real_create_async (GFile               *file,
5814                           GFileCreateFlags     flags,
5815                           int                  io_priority,
5816                           GCancellable        *cancellable,
5817                           GAsyncReadyCallback  callback,
5818                           gpointer             user_data)
5819 {
5820   GFileCreateFlags *data;
5821   GTask *task;
5822 
5823   data = g_new0 (GFileCreateFlags, 1);
5824   *data = flags;
5825 
5826   task = g_task_new (file, cancellable, callback, user_data);
5827   g_task_set_source_tag (task, g_file_real_create_async);
5828   g_task_set_task_data (task, data, g_free);
5829   g_task_set_priority (task, io_priority);
5830 
5831   g_task_run_in_thread (task, create_async_thread);
5832   g_object_unref (task);
5833 }
5834 
5835 static GFileOutputStream *
g_file_real_create_finish(GFile * file,GAsyncResult * res,GError ** error)5836 g_file_real_create_finish (GFile         *file,
5837                            GAsyncResult  *res,
5838                            GError       **error)
5839 {
5840   g_return_val_if_fail (g_task_is_valid (res, file), NULL);
5841 
5842   return g_task_propagate_pointer (G_TASK (res), error);
5843 }
5844 
5845 typedef struct {
5846   GFileOutputStream *stream;
5847   char *etag;
5848   gboolean make_backup;
5849   GFileCreateFlags flags;
5850 } ReplaceAsyncData;
5851 
5852 static void
replace_async_data_free(ReplaceAsyncData * data)5853 replace_async_data_free (ReplaceAsyncData *data)
5854 {
5855   if (data->stream)
5856     g_object_unref (data->stream);
5857   g_free (data->etag);
5858   g_free (data);
5859 }
5860 
5861 static void
replace_async_thread(GTask * task,gpointer source_object,gpointer task_data,GCancellable * cancellable)5862 replace_async_thread (GTask         *task,
5863                       gpointer       source_object,
5864                       gpointer       task_data,
5865                       GCancellable  *cancellable)
5866 {
5867   GFileOutputStream *stream;
5868   ReplaceAsyncData *data = task_data;
5869   GError *error = NULL;
5870 
5871   stream = g_file_replace (G_FILE (source_object),
5872                            data->etag,
5873                            data->make_backup,
5874                            data->flags,
5875                            cancellable,
5876                            &error);
5877 
5878   if (stream)
5879     g_task_return_pointer (task, stream, g_object_unref);
5880   else
5881     g_task_return_error (task, error);
5882 }
5883 
5884 static void
g_file_real_replace_async(GFile * file,const char * etag,gboolean make_backup,GFileCreateFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)5885 g_file_real_replace_async (GFile               *file,
5886                            const char          *etag,
5887                            gboolean             make_backup,
5888                            GFileCreateFlags     flags,
5889                            int                  io_priority,
5890                            GCancellable        *cancellable,
5891                            GAsyncReadyCallback  callback,
5892                            gpointer             user_data)
5893 {
5894   GTask *task;
5895   ReplaceAsyncData *data;
5896 
5897   data = g_new0 (ReplaceAsyncData, 1);
5898   data->etag = g_strdup (etag);
5899   data->make_backup = make_backup;
5900   data->flags = flags;
5901 
5902   task = g_task_new (file, cancellable, callback, user_data);
5903   g_task_set_source_tag (task, g_file_real_replace_async);
5904   g_task_set_task_data (task, data, (GDestroyNotify)replace_async_data_free);
5905   g_task_set_priority (task, io_priority);
5906 
5907   g_task_run_in_thread (task, replace_async_thread);
5908   g_object_unref (task);
5909 }
5910 
5911 static GFileOutputStream *
g_file_real_replace_finish(GFile * file,GAsyncResult * res,GError ** error)5912 g_file_real_replace_finish (GFile         *file,
5913                             GAsyncResult  *res,
5914                             GError       **error)
5915 {
5916   g_return_val_if_fail (g_task_is_valid (res, file), NULL);
5917 
5918   return g_task_propagate_pointer (G_TASK (res), error);
5919 }
5920 
5921 static void
delete_async_thread(GTask * task,gpointer object,gpointer task_data,GCancellable * cancellable)5922 delete_async_thread (GTask        *task,
5923                      gpointer      object,
5924                      gpointer      task_data,
5925                      GCancellable *cancellable)
5926 {
5927   GError *error = NULL;
5928 
5929   if (g_file_delete (G_FILE (object), cancellable, &error))
5930     g_task_return_boolean (task, TRUE);
5931   else
5932     g_task_return_error (task, error);
5933 }
5934 
5935 static void
g_file_real_delete_async(GFile * file,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)5936 g_file_real_delete_async (GFile               *file,
5937                           int                  io_priority,
5938                           GCancellable        *cancellable,
5939                           GAsyncReadyCallback  callback,
5940                           gpointer             user_data)
5941 {
5942   GTask *task;
5943 
5944   task = g_task_new (file, cancellable, callback, user_data);
5945   g_task_set_source_tag (task, g_file_real_delete_async);
5946   g_task_set_priority (task, io_priority);
5947   g_task_run_in_thread (task, delete_async_thread);
5948   g_object_unref (task);
5949 }
5950 
5951 static gboolean
g_file_real_delete_finish(GFile * file,GAsyncResult * res,GError ** error)5952 g_file_real_delete_finish (GFile         *file,
5953                            GAsyncResult  *res,
5954                            GError       **error)
5955 {
5956   g_return_val_if_fail (g_task_is_valid (res, file), FALSE);
5957 
5958   return g_task_propagate_boolean (G_TASK (res), error);
5959 }
5960 
5961 static void
trash_async_thread(GTask * task,gpointer object,gpointer task_data,GCancellable * cancellable)5962 trash_async_thread (GTask        *task,
5963                     gpointer      object,
5964                     gpointer      task_data,
5965                     GCancellable *cancellable)
5966 {
5967   GError *error = NULL;
5968 
5969   if (g_file_trash (G_FILE (object), cancellable, &error))
5970     g_task_return_boolean (task, TRUE);
5971   else
5972     g_task_return_error (task, error);
5973 }
5974 
5975 static void
g_file_real_trash_async(GFile * file,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)5976 g_file_real_trash_async (GFile               *file,
5977                          int                  io_priority,
5978                          GCancellable        *cancellable,
5979                          GAsyncReadyCallback  callback,
5980                          gpointer             user_data)
5981 {
5982   GTask *task;
5983 
5984   task = g_task_new (file, cancellable, callback, user_data);
5985   g_task_set_source_tag (task, g_file_real_trash_async);
5986   g_task_set_priority (task, io_priority);
5987   g_task_run_in_thread (task, trash_async_thread);
5988   g_object_unref (task);
5989 }
5990 
5991 static gboolean
g_file_real_trash_finish(GFile * file,GAsyncResult * res,GError ** error)5992 g_file_real_trash_finish (GFile         *file,
5993                           GAsyncResult  *res,
5994                           GError       **error)
5995 {
5996   g_return_val_if_fail (g_task_is_valid (res, file), FALSE);
5997 
5998   return g_task_propagate_boolean (G_TASK (res), error);
5999 }
6000 
6001 static void
make_directory_async_thread(GTask * task,gpointer object,gpointer task_data,GCancellable * cancellable)6002 make_directory_async_thread (GTask        *task,
6003                              gpointer      object,
6004                              gpointer      task_data,
6005                              GCancellable *cancellable)
6006 {
6007   GError *error = NULL;
6008 
6009   if (g_file_make_directory (G_FILE (object), cancellable, &error))
6010     g_task_return_boolean (task, TRUE);
6011   else
6012     g_task_return_error (task, error);
6013 }
6014 
6015 static void
g_file_real_make_directory_async(GFile * file,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)6016 g_file_real_make_directory_async (GFile               *file,
6017                                   int                  io_priority,
6018                                   GCancellable        *cancellable,
6019                                   GAsyncReadyCallback  callback,
6020                                   gpointer             user_data)
6021 {
6022   GTask *task;
6023 
6024   task = g_task_new (file, cancellable, callback, user_data);
6025   g_task_set_source_tag (task, g_file_real_make_directory_async);
6026   g_task_set_priority (task, io_priority);
6027   g_task_run_in_thread (task, make_directory_async_thread);
6028   g_object_unref (task);
6029 }
6030 
6031 static gboolean
g_file_real_make_directory_finish(GFile * file,GAsyncResult * res,GError ** error)6032 g_file_real_make_directory_finish (GFile         *file,
6033                                    GAsyncResult  *res,
6034                                    GError       **error)
6035 {
6036   g_return_val_if_fail (g_task_is_valid (res, file), FALSE);
6037 
6038   return g_task_propagate_boolean (G_TASK (res), error);
6039 }
6040 
6041 static void
open_readwrite_async_thread(GTask * task,gpointer object,gpointer task_data,GCancellable * cancellable)6042 open_readwrite_async_thread (GTask        *task,
6043                              gpointer      object,
6044                              gpointer      task_data,
6045                              GCancellable *cancellable)
6046 {
6047   GFileIOStream *stream;
6048   GError *error = NULL;
6049 
6050   stream = g_file_open_readwrite (G_FILE (object), cancellable, &error);
6051 
6052   if (stream == NULL)
6053     g_task_return_error (task, error);
6054   else
6055     g_task_return_pointer (task, stream, g_object_unref);
6056 }
6057 
6058 static void
g_file_real_open_readwrite_async(GFile * file,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)6059 g_file_real_open_readwrite_async (GFile               *file,
6060                                   int                  io_priority,
6061                                   GCancellable        *cancellable,
6062                                   GAsyncReadyCallback  callback,
6063                                   gpointer             user_data)
6064 {
6065   GTask *task;
6066 
6067   task = g_task_new (file, cancellable, callback, user_data);
6068   g_task_set_source_tag (task, g_file_real_open_readwrite_async);
6069   g_task_set_priority (task, io_priority);
6070 
6071   g_task_run_in_thread (task, open_readwrite_async_thread);
6072   g_object_unref (task);
6073 }
6074 
6075 static GFileIOStream *
g_file_real_open_readwrite_finish(GFile * file,GAsyncResult * res,GError ** error)6076 g_file_real_open_readwrite_finish (GFile         *file,
6077                                    GAsyncResult  *res,
6078                                    GError       **error)
6079 {
6080   g_return_val_if_fail (g_task_is_valid (res, file), NULL);
6081 
6082   return g_task_propagate_pointer (G_TASK (res), error);
6083 }
6084 
6085 static void
create_readwrite_async_thread(GTask * task,gpointer object,gpointer task_data,GCancellable * cancellable)6086 create_readwrite_async_thread (GTask        *task,
6087                                gpointer      object,
6088                                gpointer      task_data,
6089                                GCancellable *cancellable)
6090 {
6091   GFileCreateFlags *data = task_data;
6092   GFileIOStream *stream;
6093   GError *error = NULL;
6094 
6095   stream = g_file_create_readwrite (G_FILE (object), *data, cancellable, &error);
6096 
6097   if (stream == NULL)
6098     g_task_return_error (task, error);
6099   else
6100     g_task_return_pointer (task, stream, g_object_unref);
6101 }
6102 
6103 static void
g_file_real_create_readwrite_async(GFile * file,GFileCreateFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)6104 g_file_real_create_readwrite_async (GFile               *file,
6105                                     GFileCreateFlags     flags,
6106                                     int                  io_priority,
6107                                     GCancellable        *cancellable,
6108                                     GAsyncReadyCallback  callback,
6109                                     gpointer             user_data)
6110 {
6111   GFileCreateFlags *data;
6112   GTask *task;
6113 
6114   data = g_new0 (GFileCreateFlags, 1);
6115   *data = flags;
6116 
6117   task = g_task_new (file, cancellable, callback, user_data);
6118   g_task_set_source_tag (task, g_file_real_create_readwrite_async);
6119   g_task_set_task_data (task, data, g_free);
6120   g_task_set_priority (task, io_priority);
6121 
6122   g_task_run_in_thread (task, create_readwrite_async_thread);
6123   g_object_unref (task);
6124 }
6125 
6126 static GFileIOStream *
g_file_real_create_readwrite_finish(GFile * file,GAsyncResult * res,GError ** error)6127 g_file_real_create_readwrite_finish (GFile         *file,
6128                                      GAsyncResult  *res,
6129                                      GError       **error)
6130 {
6131   g_return_val_if_fail (g_task_is_valid (res, file), NULL);
6132 
6133   return g_task_propagate_pointer (G_TASK (res), error);
6134 }
6135 
6136 typedef struct {
6137   char *etag;
6138   gboolean make_backup;
6139   GFileCreateFlags flags;
6140 } ReplaceRWAsyncData;
6141 
6142 static void
replace_rw_async_data_free(ReplaceRWAsyncData * data)6143 replace_rw_async_data_free (ReplaceRWAsyncData *data)
6144 {
6145   g_free (data->etag);
6146   g_free (data);
6147 }
6148 
6149 static void
replace_readwrite_async_thread(GTask * task,gpointer object,gpointer task_data,GCancellable * cancellable)6150 replace_readwrite_async_thread (GTask        *task,
6151                                 gpointer      object,
6152                                 gpointer      task_data,
6153                                 GCancellable *cancellable)
6154 {
6155   GFileIOStream *stream;
6156   GError *error = NULL;
6157   ReplaceRWAsyncData *data = task_data;
6158 
6159   stream = g_file_replace_readwrite (G_FILE (object),
6160                                      data->etag,
6161                                      data->make_backup,
6162                                      data->flags,
6163                                      cancellable,
6164                                      &error);
6165 
6166   if (stream == NULL)
6167     g_task_return_error (task, error);
6168   else
6169     g_task_return_pointer (task, stream, g_object_unref);
6170 }
6171 
6172 static void
g_file_real_replace_readwrite_async(GFile * file,const char * etag,gboolean make_backup,GFileCreateFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)6173 g_file_real_replace_readwrite_async (GFile               *file,
6174                                      const char          *etag,
6175                                      gboolean             make_backup,
6176                                      GFileCreateFlags     flags,
6177                                      int                  io_priority,
6178                                      GCancellable        *cancellable,
6179                                      GAsyncReadyCallback  callback,
6180                                      gpointer             user_data)
6181 {
6182   GTask *task;
6183   ReplaceRWAsyncData *data;
6184 
6185   data = g_new0 (ReplaceRWAsyncData, 1);
6186   data->etag = g_strdup (etag);
6187   data->make_backup = make_backup;
6188   data->flags = flags;
6189 
6190   task = g_task_new (file, cancellable, callback, user_data);
6191   g_task_set_source_tag (task, g_file_real_replace_readwrite_async);
6192   g_task_set_task_data (task, data, (GDestroyNotify)replace_rw_async_data_free);
6193   g_task_set_priority (task, io_priority);
6194 
6195   g_task_run_in_thread (task, replace_readwrite_async_thread);
6196   g_object_unref (task);
6197 }
6198 
6199 static GFileIOStream *
g_file_real_replace_readwrite_finish(GFile * file,GAsyncResult * res,GError ** error)6200 g_file_real_replace_readwrite_finish (GFile         *file,
6201                                       GAsyncResult  *res,
6202                                       GError       **error)
6203 {
6204   g_return_val_if_fail (g_task_is_valid (res, file), NULL);
6205 
6206   return g_task_propagate_pointer (G_TASK (res), error);
6207 }
6208 
6209 static void
set_display_name_async_thread(GTask * task,gpointer object,gpointer task_data,GCancellable * cancellable)6210 set_display_name_async_thread (GTask        *task,
6211                                gpointer      object,
6212                                gpointer      task_data,
6213                                GCancellable *cancellable)
6214 {
6215   GError *error = NULL;
6216   char *name = task_data;
6217   GFile *file;
6218 
6219   file = g_file_set_display_name (G_FILE (object), name, cancellable, &error);
6220 
6221   if (file == NULL)
6222     g_task_return_error (task, error);
6223   else
6224     g_task_return_pointer (task, file, g_object_unref);
6225 }
6226 
6227 static void
g_file_real_set_display_name_async(GFile * file,const char * display_name,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)6228 g_file_real_set_display_name_async (GFile               *file,
6229                                     const char          *display_name,
6230                                     int                  io_priority,
6231                                     GCancellable        *cancellable,
6232                                     GAsyncReadyCallback  callback,
6233                                     gpointer             user_data)
6234 {
6235   GTask *task;
6236 
6237   task = g_task_new (file, cancellable, callback, user_data);
6238   g_task_set_source_tag (task, g_file_real_set_display_name_async);
6239   g_task_set_task_data (task, g_strdup (display_name), g_free);
6240   g_task_set_priority (task, io_priority);
6241 
6242   g_task_run_in_thread (task, set_display_name_async_thread);
6243   g_object_unref (task);
6244 }
6245 
6246 static GFile *
g_file_real_set_display_name_finish(GFile * file,GAsyncResult * res,GError ** error)6247 g_file_real_set_display_name_finish (GFile         *file,
6248                                      GAsyncResult  *res,
6249                                      GError       **error)
6250 {
6251   g_return_val_if_fail (g_task_is_valid (res, file), NULL);
6252 
6253   return g_task_propagate_pointer (G_TASK (res), error);
6254 }
6255 
6256 typedef struct {
6257   GFileQueryInfoFlags flags;
6258   GFileInfo *info;
6259   gboolean res;
6260   GError *error;
6261 } SetInfoAsyncData;
6262 
6263 static void
set_info_data_free(SetInfoAsyncData * data)6264 set_info_data_free (SetInfoAsyncData *data)
6265 {
6266   if (data->info)
6267     g_object_unref (data->info);
6268   if (data->error)
6269     g_error_free (data->error);
6270   g_free (data);
6271 }
6272 
6273 static void
set_info_async_thread(GTask * task,gpointer object,gpointer task_data,GCancellable * cancellable)6274 set_info_async_thread (GTask        *task,
6275                        gpointer      object,
6276                        gpointer      task_data,
6277                        GCancellable *cancellable)
6278 {
6279   SetInfoAsyncData *data = task_data;
6280 
6281   data->error = NULL;
6282   data->res = g_file_set_attributes_from_info (G_FILE (object),
6283                                                data->info,
6284                                                data->flags,
6285                                                cancellable,
6286                                                &data->error);
6287 }
6288 
6289 static void
g_file_real_set_attributes_async(GFile * file,GFileInfo * info,GFileQueryInfoFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)6290 g_file_real_set_attributes_async (GFile               *file,
6291                                   GFileInfo           *info,
6292                                   GFileQueryInfoFlags  flags,
6293                                   int                  io_priority,
6294                                   GCancellable        *cancellable,
6295                                   GAsyncReadyCallback  callback,
6296                                   gpointer             user_data)
6297 {
6298   GTask *task;
6299   SetInfoAsyncData *data;
6300 
6301   data = g_new0 (SetInfoAsyncData, 1);
6302   data->info = g_file_info_dup (info);
6303   data->flags = flags;
6304 
6305   task = g_task_new (file, cancellable, callback, user_data);
6306   g_task_set_source_tag (task, g_file_real_set_attributes_async);
6307   g_task_set_task_data (task, data, (GDestroyNotify)set_info_data_free);
6308   g_task_set_priority (task, io_priority);
6309 
6310   g_task_run_in_thread (task, set_info_async_thread);
6311   g_object_unref (task);
6312 }
6313 
6314 static gboolean
g_file_real_set_attributes_finish(GFile * file,GAsyncResult * res,GFileInfo ** info,GError ** error)6315 g_file_real_set_attributes_finish (GFile         *file,
6316                                    GAsyncResult  *res,
6317                                    GFileInfo    **info,
6318                                    GError       **error)
6319 {
6320   SetInfoAsyncData *data;
6321 
6322   g_return_val_if_fail (g_task_is_valid (res, file), FALSE);
6323 
6324   data = g_task_get_task_data (G_TASK (res));
6325 
6326   if (info)
6327     *info = g_object_ref (data->info);
6328 
6329   if (error != NULL && data->error)
6330     *error = g_error_copy (data->error);
6331 
6332   return data->res;
6333 }
6334 
6335 static void
find_enclosing_mount_async_thread(GTask * task,gpointer object,gpointer task_data,GCancellable * cancellable)6336 find_enclosing_mount_async_thread (GTask        *task,
6337                                    gpointer      object,
6338                                    gpointer      task_data,
6339                                    GCancellable *cancellable)
6340 {
6341   GError *error = NULL;
6342   GMount *mount;
6343 
6344   mount = g_file_find_enclosing_mount (G_FILE (object), cancellable, &error);
6345 
6346   if (mount == NULL)
6347     g_task_return_error (task, error);
6348   else
6349     g_task_return_pointer (task, mount, g_object_unref);
6350 }
6351 
6352 static void
g_file_real_find_enclosing_mount_async(GFile * file,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)6353 g_file_real_find_enclosing_mount_async (GFile               *file,
6354                                         int                  io_priority,
6355                                         GCancellable        *cancellable,
6356                                         GAsyncReadyCallback  callback,
6357                                         gpointer             user_data)
6358 {
6359   GTask *task;
6360 
6361   task = g_task_new (file, cancellable, callback, user_data);
6362   g_task_set_source_tag (task, g_file_real_find_enclosing_mount_async);
6363   g_task_set_priority (task, io_priority);
6364 
6365   g_task_run_in_thread (task, find_enclosing_mount_async_thread);
6366   g_object_unref (task);
6367 }
6368 
6369 static GMount *
g_file_real_find_enclosing_mount_finish(GFile * file,GAsyncResult * res,GError ** error)6370 g_file_real_find_enclosing_mount_finish (GFile         *file,
6371                                          GAsyncResult  *res,
6372                                          GError       **error)
6373 {
6374   g_return_val_if_fail (g_task_is_valid (res, file), NULL);
6375 
6376   return g_task_propagate_pointer (G_TASK (res), error);
6377 }
6378 
6379 
6380 typedef struct {
6381   GFile *source;
6382   GFile *destination;
6383   GFileCopyFlags flags;
6384   GFileProgressCallback progress_cb;
6385   gpointer progress_cb_data;
6386 } CopyAsyncData;
6387 
6388 static void
copy_async_data_free(CopyAsyncData * data)6389 copy_async_data_free (CopyAsyncData *data)
6390 {
6391   g_object_unref (data->source);
6392   g_object_unref (data->destination);
6393   g_slice_free (CopyAsyncData, data);
6394 }
6395 
6396 typedef struct {
6397   CopyAsyncData *data;
6398   goffset current_num_bytes;
6399   goffset total_num_bytes;
6400 } ProgressData;
6401 
6402 static gboolean
copy_async_progress_in_main(gpointer user_data)6403 copy_async_progress_in_main (gpointer user_data)
6404 {
6405   ProgressData *progress = user_data;
6406   CopyAsyncData *data = progress->data;
6407 
6408   data->progress_cb (progress->current_num_bytes,
6409                      progress->total_num_bytes,
6410                      data->progress_cb_data);
6411 
6412   return FALSE;
6413 }
6414 
6415 static void
copy_async_progress_callback(goffset current_num_bytes,goffset total_num_bytes,gpointer user_data)6416 copy_async_progress_callback (goffset  current_num_bytes,
6417                               goffset  total_num_bytes,
6418                               gpointer user_data)
6419 {
6420   GTask *task = user_data;
6421   CopyAsyncData *data = g_task_get_task_data (task);
6422   ProgressData *progress;
6423 
6424   progress = g_new (ProgressData, 1);
6425   progress->data = data;
6426   progress->current_num_bytes = current_num_bytes;
6427   progress->total_num_bytes = total_num_bytes;
6428 
6429   g_main_context_invoke_full (g_task_get_context (task),
6430                               g_task_get_priority (task),
6431                               copy_async_progress_in_main,
6432                               progress,
6433                               g_free);
6434 }
6435 
6436 static void
copy_async_thread(GTask * task,gpointer source,gpointer task_data,GCancellable * cancellable)6437 copy_async_thread (GTask        *task,
6438                    gpointer      source,
6439                    gpointer      task_data,
6440                    GCancellable *cancellable)
6441 {
6442   CopyAsyncData *data = task_data;
6443   gboolean result;
6444   GError *error = NULL;
6445 
6446   result = g_file_copy (data->source,
6447                         data->destination,
6448                         data->flags,
6449                         cancellable,
6450                         (data->progress_cb != NULL) ? copy_async_progress_callback : NULL,
6451                         task,
6452                         &error);
6453   if (result)
6454     g_task_return_boolean (task, TRUE);
6455   else
6456     g_task_return_error (task, error);
6457 }
6458 
6459 static void
g_file_real_copy_async(GFile * source,GFile * destination,GFileCopyFlags flags,int io_priority,GCancellable * cancellable,GFileProgressCallback progress_callback,gpointer progress_callback_data,GAsyncReadyCallback callback,gpointer user_data)6460 g_file_real_copy_async (GFile                  *source,
6461                         GFile                  *destination,
6462                         GFileCopyFlags          flags,
6463                         int                     io_priority,
6464                         GCancellable           *cancellable,
6465                         GFileProgressCallback   progress_callback,
6466                         gpointer                progress_callback_data,
6467                         GAsyncReadyCallback     callback,
6468                         gpointer                user_data)
6469 {
6470   GTask *task;
6471   CopyAsyncData *data;
6472 
6473   data = g_slice_new (CopyAsyncData);
6474   data->source = g_object_ref (source);
6475   data->destination = g_object_ref (destination);
6476   data->flags = flags;
6477   data->progress_cb = progress_callback;
6478   data->progress_cb_data = progress_callback_data;
6479 
6480   task = g_task_new (source, cancellable, callback, user_data);
6481   g_task_set_source_tag (task, g_file_real_copy_async);
6482   g_task_set_task_data (task, data, (GDestroyNotify)copy_async_data_free);
6483   g_task_set_priority (task, io_priority);
6484   g_task_run_in_thread (task, copy_async_thread);
6485   g_object_unref (task);
6486 }
6487 
6488 static gboolean
g_file_real_copy_finish(GFile * file,GAsyncResult * res,GError ** error)6489 g_file_real_copy_finish (GFile        *file,
6490                          GAsyncResult *res,
6491                          GError      **error)
6492 {
6493   g_return_val_if_fail (g_task_is_valid (res, file), FALSE);
6494 
6495   return g_task_propagate_boolean (G_TASK (res), error);
6496 }
6497 
6498 
6499 /********************************************
6500  *   Default VFS operations                 *
6501  ********************************************/
6502 
6503 /**
6504  * g_file_new_for_path:
6505  * @path: (type filename): a string containing a relative or absolute path.
6506  *     The string must be encoded in the glib filename encoding.
6507  *
6508  * Constructs a #GFile for a given path. This operation never
6509  * fails, but the returned object might not support any I/O
6510  * operation if @path is malformed.
6511  *
6512  * Returns: (transfer full): a new #GFile for the given @path.
6513  *   Free the returned object with g_object_unref().
6514  */
6515 GFile *
g_file_new_for_path(const char * path)6516 g_file_new_for_path (const char *path)
6517 {
6518   g_return_val_if_fail (path != NULL, NULL);
6519 
6520   return g_vfs_get_file_for_path (g_vfs_get_default (), path);
6521 }
6522 
6523 /**
6524  * g_file_new_for_uri:
6525  * @uri: a UTF-8 string containing a URI
6526  *
6527  * Constructs a #GFile for a given URI. This operation never
6528  * fails, but the returned object might not support any I/O
6529  * operation if @uri is malformed or if the uri type is
6530  * not supported.
6531  *
6532  * Returns: (transfer full): a new #GFile for the given @uri.
6533  *     Free the returned object with g_object_unref().
6534  */
6535 GFile *
g_file_new_for_uri(const char * uri)6536 g_file_new_for_uri (const char *uri)
6537 {
6538   g_return_val_if_fail (uri != NULL, NULL);
6539 
6540   return g_vfs_get_file_for_uri (g_vfs_get_default (), uri);
6541 }
6542 
6543 /**
6544  * g_file_new_tmp:
6545  * @tmpl: (type filename) (nullable): Template for the file
6546  *   name, as in g_file_open_tmp(), or %NULL for a default template
6547  * @iostream: (out): on return, a #GFileIOStream for the created file
6548  * @error: a #GError, or %NULL
6549  *
6550  * Opens a file in the preferred directory for temporary files (as
6551  * returned by g_get_tmp_dir()) and returns a #GFile and
6552  * #GFileIOStream pointing to it.
6553  *
6554  * @tmpl should be a string in the GLib file name encoding
6555  * containing a sequence of six 'X' characters, and containing no
6556  * directory components. If it is %NULL, a default template is used.
6557  *
6558  * Unlike the other #GFile constructors, this will return %NULL if
6559  * a temporary file could not be created.
6560  *
6561  * Returns: (transfer full): a new #GFile.
6562  *     Free the returned object with g_object_unref().
6563  *
6564  * Since: 2.32
6565  */
6566 GFile *
g_file_new_tmp(const char * tmpl,GFileIOStream ** iostream,GError ** error)6567 g_file_new_tmp (const char     *tmpl,
6568                 GFileIOStream **iostream,
6569                 GError        **error)
6570 {
6571   gint fd;
6572   gchar *path;
6573   GFile *file;
6574   GFileOutputStream *output;
6575 
6576   g_return_val_if_fail (iostream != NULL, NULL);
6577 
6578   fd = g_file_open_tmp (tmpl, &path, error);
6579   if (fd == -1)
6580     return NULL;
6581 
6582   file = g_file_new_for_path (path);
6583 
6584   output = _g_local_file_output_stream_new (fd);
6585   *iostream = _g_local_file_io_stream_new (G_LOCAL_FILE_OUTPUT_STREAM (output));
6586 
6587   g_object_unref (output);
6588   g_free (path);
6589 
6590   return file;
6591 }
6592 
6593 /**
6594  * g_file_parse_name:
6595  * @parse_name: a file name or path to be parsed
6596  *
6597  * Constructs a #GFile with the given @parse_name (i.e. something
6598  * given by g_file_get_parse_name()). This operation never fails,
6599  * but the returned object might not support any I/O operation if
6600  * the @parse_name cannot be parsed.
6601  *
6602  * Returns: (transfer full): a new #GFile.
6603  */
6604 GFile *
g_file_parse_name(const char * parse_name)6605 g_file_parse_name (const char *parse_name)
6606 {
6607   g_return_val_if_fail (parse_name != NULL, NULL);
6608 
6609   return g_vfs_parse_name (g_vfs_get_default (), parse_name);
6610 }
6611 
6612 /**
6613  * g_file_new_build_filename:
6614  * @first_element: (type filename): the first element in the path
6615  * @...: remaining elements in path, terminated by %NULL
6616  *
6617  * Constructs a #GFile from a series of elements using the correct
6618  * separator for filenames.
6619  *
6620  * Using this function is equivalent to calling g_build_filename(),
6621  * followed by g_file_new_for_path() on the result.
6622  *
6623  * Returns: (transfer full): a new #GFile
6624  *
6625  * Since: 2.56
6626  */
6627 GFile *
g_file_new_build_filename(const gchar * first_element,...)6628 g_file_new_build_filename (const gchar *first_element,
6629                            ...)
6630 {
6631   gchar *str;
6632   GFile *file;
6633   va_list args;
6634 
6635   g_return_val_if_fail (first_element != NULL, NULL);
6636 
6637   va_start (args, first_element);
6638   str = g_build_filename_valist (first_element, &args);
6639   va_end (args);
6640 
6641   file = g_file_new_for_path (str);
6642   g_free (str);
6643 
6644   return file;
6645 }
6646 
6647 static gboolean
is_valid_scheme_character(char c)6648 is_valid_scheme_character (char c)
6649 {
6650   return g_ascii_isalnum (c) || c == '+' || c == '-' || c == '.';
6651 }
6652 
6653 /* Following RFC 2396, valid schemes are built like:
6654  *       scheme        = alpha *( alpha | digit | "+" | "-" | "." )
6655  */
6656 static gboolean
has_valid_scheme(const char * uri)6657 has_valid_scheme (const char *uri)
6658 {
6659   const char *p;
6660 
6661   p = uri;
6662 
6663   if (!g_ascii_isalpha (*p))
6664     return FALSE;
6665 
6666   do {
6667     p++;
6668   } while (is_valid_scheme_character (*p));
6669 
6670   return *p == ':';
6671 }
6672 
6673 static GFile *
new_for_cmdline_arg(const gchar * arg,const gchar * cwd)6674 new_for_cmdline_arg (const gchar *arg,
6675                      const gchar *cwd)
6676 {
6677   GFile *file;
6678   char *filename;
6679 
6680   if (g_path_is_absolute (arg))
6681     return g_file_new_for_path (arg);
6682 
6683   if (has_valid_scheme (arg))
6684     return g_file_new_for_uri (arg);
6685 
6686   if (cwd == NULL)
6687     {
6688       char *current_dir;
6689 
6690       current_dir = g_get_current_dir ();
6691       filename = g_build_filename (current_dir, arg, NULL);
6692       g_free (current_dir);
6693     }
6694   else
6695     filename = g_build_filename (cwd, arg, NULL);
6696 
6697   file = g_file_new_for_path (filename);
6698   g_free (filename);
6699 
6700   return file;
6701 }
6702 
6703 /**
6704  * g_file_new_for_commandline_arg:
6705  * @arg: (type filename): a command line string
6706  *
6707  * Creates a #GFile with the given argument from the command line.
6708  * The value of @arg can be either a URI, an absolute path or a
6709  * relative path resolved relative to the current working directory.
6710  * This operation never fails, but the returned object might not
6711  * support any I/O operation if @arg points to a malformed path.
6712  *
6713  * Note that on Windows, this function expects its argument to be in
6714  * UTF-8 -- not the system code page.  This means that you
6715  * should not use this function with string from argv as it is passed
6716  * to main().  g_win32_get_command_line() will return a UTF-8 version of
6717  * the commandline.  #GApplication also uses UTF-8 but
6718  * g_application_command_line_create_file_for_arg() may be more useful
6719  * for you there.  It is also always possible to use this function with
6720  * #GOptionContext arguments of type %G_OPTION_ARG_FILENAME.
6721  *
6722  * Returns: (transfer full): a new #GFile.
6723  *    Free the returned object with g_object_unref().
6724  */
6725 GFile *
g_file_new_for_commandline_arg(const char * arg)6726 g_file_new_for_commandline_arg (const char *arg)
6727 {
6728   g_return_val_if_fail (arg != NULL, NULL);
6729 
6730   return new_for_cmdline_arg (arg, NULL);
6731 }
6732 
6733 /**
6734  * g_file_new_for_commandline_arg_and_cwd:
6735  * @arg: (type filename): a command line string
6736  * @cwd: (type filename): the current working directory of the commandline
6737  *
6738  * Creates a #GFile with the given argument from the command line.
6739  *
6740  * This function is similar to g_file_new_for_commandline_arg() except
6741  * that it allows for passing the current working directory as an
6742  * argument instead of using the current working directory of the
6743  * process.
6744  *
6745  * This is useful if the commandline argument was given in a context
6746  * other than the invocation of the current process.
6747  *
6748  * See also g_application_command_line_create_file_for_arg().
6749  *
6750  * Returns: (transfer full): a new #GFile
6751  *
6752  * Since: 2.36
6753  **/
6754 GFile *
g_file_new_for_commandline_arg_and_cwd(const gchar * arg,const gchar * cwd)6755 g_file_new_for_commandline_arg_and_cwd (const gchar *arg,
6756                                         const gchar *cwd)
6757 {
6758   g_return_val_if_fail (arg != NULL, NULL);
6759   g_return_val_if_fail (cwd != NULL, NULL);
6760 
6761   return new_for_cmdline_arg (arg, cwd);
6762 }
6763 
6764 /**
6765  * g_file_mount_enclosing_volume:
6766  * @location: input #GFile
6767  * @flags: flags affecting the operation
6768  * @mount_operation: (nullable): a #GMountOperation
6769  *     or %NULL to avoid user interaction
6770  * @cancellable: (nullable): optional #GCancellable object,
6771  *     %NULL to ignore
6772  * @callback: (nullable): a #GAsyncReadyCallback to call
6773  *     when the request is satisfied, or %NULL
6774  * @user_data: the data to pass to callback function
6775  *
6776  * Starts a @mount_operation, mounting the volume that contains
6777  * the file @location.
6778  *
6779  * When this operation has completed, @callback will be called with
6780  * @user_user data, and the operation can be finalized with
6781  * g_file_mount_enclosing_volume_finish().
6782  *
6783  * If @cancellable is not %NULL, then the operation can be cancelled by
6784  * triggering the cancellable object from another thread. If the operation
6785  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
6786  */
6787 void
g_file_mount_enclosing_volume(GFile * location,GMountMountFlags flags,GMountOperation * mount_operation,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)6788 g_file_mount_enclosing_volume (GFile               *location,
6789                                GMountMountFlags     flags,
6790                                GMountOperation     *mount_operation,
6791                                GCancellable        *cancellable,
6792                                GAsyncReadyCallback  callback,
6793                                gpointer             user_data)
6794 {
6795   GFileIface *iface;
6796 
6797   g_return_if_fail (G_IS_FILE (location));
6798 
6799   iface = G_FILE_GET_IFACE (location);
6800 
6801   if (iface->mount_enclosing_volume == NULL)
6802     {
6803       g_task_report_new_error (location, callback, user_data,
6804                                g_file_mount_enclosing_volume,
6805                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
6806                                _("volume doesn’t implement mount"));
6807       return;
6808     }
6809 
6810   (* iface->mount_enclosing_volume) (location, flags, mount_operation, cancellable, callback, user_data);
6811 
6812 }
6813 
6814 /**
6815  * g_file_mount_enclosing_volume_finish:
6816  * @location: input #GFile
6817  * @result: a #GAsyncResult
6818  * @error: a #GError, or %NULL
6819  *
6820  * Finishes a mount operation started by g_file_mount_enclosing_volume().
6821  *
6822  * Returns: %TRUE if successful. If an error has occurred,
6823  *     this function will return %FALSE and set @error
6824  *     appropriately if present.
6825  */
6826 gboolean
g_file_mount_enclosing_volume_finish(GFile * location,GAsyncResult * result,GError ** error)6827 g_file_mount_enclosing_volume_finish (GFile         *location,
6828                                       GAsyncResult  *result,
6829                                       GError       **error)
6830 {
6831   GFileIface *iface;
6832 
6833   g_return_val_if_fail (G_IS_FILE (location), FALSE);
6834   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
6835 
6836   if (g_async_result_legacy_propagate_error (result, error))
6837     return FALSE;
6838   else if (g_async_result_is_tagged (result, g_file_mount_enclosing_volume))
6839     return g_task_propagate_boolean (G_TASK (result), error);
6840 
6841   iface = G_FILE_GET_IFACE (location);
6842 
6843   return (* iface->mount_enclosing_volume_finish) (location, result, error);
6844 }
6845 
6846 /********************************************
6847  *   Utility functions                      *
6848  ********************************************/
6849 
6850 /**
6851  * g_file_query_default_handler:
6852  * @file: a #GFile to open
6853  * @cancellable: optional #GCancellable object, %NULL to ignore
6854  * @error: a #GError, or %NULL
6855  *
6856  * Returns the #GAppInfo that is registered as the default
6857  * application to handle the file specified by @file.
6858  *
6859  * If @cancellable is not %NULL, then the operation can be cancelled by
6860  * triggering the cancellable object from another thread. If the operation
6861  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
6862  *
6863  * Returns: (transfer full): a #GAppInfo if the handle was found,
6864  *     %NULL if there were errors.
6865  *     When you are done with it, release it with g_object_unref()
6866  */
6867 GAppInfo *
g_file_query_default_handler(GFile * file,GCancellable * cancellable,GError ** error)6868 g_file_query_default_handler (GFile         *file,
6869                               GCancellable  *cancellable,
6870                               GError       **error)
6871 {
6872   char *uri_scheme;
6873   const char *content_type;
6874   GAppInfo *appinfo;
6875   GFileInfo *info;
6876   char *path;
6877 
6878   uri_scheme = g_file_get_uri_scheme (file);
6879   if (uri_scheme && uri_scheme[0] != '\0')
6880     {
6881       appinfo = g_app_info_get_default_for_uri_scheme (uri_scheme);
6882       g_free (uri_scheme);
6883 
6884       if (appinfo != NULL)
6885         return appinfo;
6886     }
6887   else
6888     g_free (uri_scheme);
6889 
6890   info = g_file_query_info (file,
6891                             G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
6892                             G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE,
6893                             0,
6894                             cancellable,
6895                             error);
6896   if (info == NULL)
6897     return NULL;
6898 
6899   appinfo = NULL;
6900 
6901   content_type = g_file_info_get_content_type (info);
6902   if (content_type == NULL)
6903     content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
6904   if (content_type)
6905     {
6906       /* Don't use is_native(), as we want to support fuse paths if available */
6907       path = g_file_get_path (file);
6908       appinfo = g_app_info_get_default_for_type (content_type,
6909                                                  path == NULL);
6910       g_free (path);
6911     }
6912 
6913   g_object_unref (info);
6914 
6915   if (appinfo != NULL)
6916     return appinfo;
6917 
6918   g_set_error_literal (error, G_IO_ERROR,
6919                        G_IO_ERROR_NOT_SUPPORTED,
6920                        _("No application is registered as handling this file"));
6921   return NULL;
6922 }
6923 
6924 static void
query_default_handler_query_info_cb(GObject * object,GAsyncResult * result,gpointer user_data)6925 query_default_handler_query_info_cb (GObject      *object,
6926                                      GAsyncResult *result,
6927                                      gpointer      user_data)
6928 {
6929   GFile *file = G_FILE (object);
6930   GTask *task = G_TASK (user_data);
6931   GError *error = NULL;
6932   GFileInfo *info;
6933   const char *content_type;
6934   GAppInfo *appinfo = NULL;
6935 
6936   info = g_file_query_info_finish (file, result, &error);
6937   if (info == NULL)
6938     {
6939       g_task_return_error (task, g_steal_pointer (&error));
6940       g_object_unref (task);
6941       return;
6942     }
6943 
6944   content_type = g_file_info_get_content_type (info);
6945   if (content_type == NULL)
6946     content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
6947   if (content_type)
6948     {
6949       char *path;
6950 
6951       /* Don't use is_native(), as we want to support fuse paths if available */
6952       path = g_file_get_path (file);
6953 
6954       /* FIXME: The following still uses blocking calls. */
6955       appinfo = g_app_info_get_default_for_type (content_type,
6956                                                  path == NULL);
6957       g_free (path);
6958     }
6959 
6960   g_object_unref (info);
6961 
6962   if (appinfo != NULL)
6963     g_task_return_pointer (task, g_steal_pointer (&appinfo), g_object_unref);
6964   else
6965     g_task_return_new_error (task,
6966                              G_IO_ERROR,
6967                              G_IO_ERROR_NOT_SUPPORTED,
6968                              _("No application is registered as handling this file"));
6969   g_object_unref (task);
6970 }
6971 
6972 /**
6973  * g_file_query_default_handler_async:
6974  * @file: a #GFile to open
6975  * @io_priority: the [I/O priority][io-priority] of the request
6976  * @cancellable: optional #GCancellable object, %NULL to ignore
6977  * @callback: (nullable): a #GAsyncReadyCallback to call when the request is done
6978  * @user_data: (nullable): data to pass to @callback
6979  *
6980  * Async version of g_file_query_default_handler().
6981  *
6982  * Since: 2.60
6983  */
6984 void
g_file_query_default_handler_async(GFile * file,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)6985 g_file_query_default_handler_async (GFile              *file,
6986                                     int                 io_priority,
6987                                     GCancellable       *cancellable,
6988                                     GAsyncReadyCallback callback,
6989                                     gpointer            user_data)
6990 {
6991   GTask *task;
6992   char *uri_scheme;
6993 
6994   task = g_task_new (file, cancellable, callback, user_data);
6995   g_task_set_source_tag (task, g_file_query_default_handler_async);
6996 
6997   uri_scheme = g_file_get_uri_scheme (file);
6998   if (uri_scheme && uri_scheme[0] != '\0')
6999     {
7000       GAppInfo *appinfo;
7001 
7002       /* FIXME: The following still uses blocking calls. */
7003       appinfo = g_app_info_get_default_for_uri_scheme (uri_scheme);
7004       g_free (uri_scheme);
7005 
7006       if (appinfo != NULL)
7007         {
7008           g_task_return_pointer (task, g_steal_pointer (&appinfo), g_object_unref);
7009           g_object_unref (task);
7010           return;
7011         }
7012     }
7013   else
7014     g_free (uri_scheme);
7015 
7016   g_file_query_info_async (file,
7017                            G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
7018                            G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE,
7019                            0,
7020                            io_priority,
7021                            cancellable,
7022                            query_default_handler_query_info_cb,
7023                            g_steal_pointer (&task));
7024 }
7025 
7026 /**
7027  * g_file_query_default_handler_finish:
7028  * @file: a #GFile to open
7029  * @result: a #GAsyncResult
7030  * @error: (nullable): a #GError
7031  *
7032  * Finishes a g_file_query_default_handler_async() operation.
7033  *
7034  * Returns: (transfer full): a #GAppInfo if the handle was found,
7035  *     %NULL if there were errors.
7036  *     When you are done with it, release it with g_object_unref()
7037  *
7038  * Since: 2.60
7039  */
7040 GAppInfo *
g_file_query_default_handler_finish(GFile * file,GAsyncResult * result,GError ** error)7041 g_file_query_default_handler_finish (GFile        *file,
7042                                      GAsyncResult *result,
7043                                      GError      **error)
7044 {
7045   g_return_val_if_fail (G_IS_FILE (file), NULL);
7046   g_return_val_if_fail (g_task_is_valid (result, file), NULL);
7047 
7048   return g_task_propagate_pointer (G_TASK (result), error);
7049 }
7050 
7051 #define GET_CONTENT_BLOCK_SIZE 8192
7052 
7053 /**
7054  * g_file_load_contents:
7055  * @file: input #GFile
7056  * @cancellable: optional #GCancellable object, %NULL to ignore
7057  * @contents: (out) (transfer full) (element-type guint8) (array length=length): a location to place the contents of the file
7058  * @length: (out) (optional): a location to place the length of the contents of the file,
7059  *    or %NULL if the length is not needed
7060  * @etag_out: (out) (optional) (nullable): a location to place the current entity tag for the file,
7061  *    or %NULL if the entity tag is not needed
7062  * @error: a #GError, or %NULL
7063  *
7064  * Loads the content of the file into memory. The data is always
7065  * zero-terminated, but this is not included in the resultant @length.
7066  * The returned @contents should be freed with g_free() when no longer
7067  * needed.
7068  *
7069  * If @cancellable is not %NULL, then the operation can be cancelled by
7070  * triggering the cancellable object from another thread. If the operation
7071  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
7072  *
7073  * Returns: %TRUE if the @file's contents were successfully loaded.
7074  *     %FALSE if there were errors.
7075  */
7076 gboolean
g_file_load_contents(GFile * file,GCancellable * cancellable,char ** contents,gsize * length,char ** etag_out,GError ** error)7077 g_file_load_contents (GFile         *file,
7078                       GCancellable  *cancellable,
7079                       char         **contents,
7080                       gsize         *length,
7081                       char         **etag_out,
7082                       GError       **error)
7083 {
7084   GFileInputStream *in;
7085   GByteArray *content;
7086   gsize pos;
7087   gssize res;
7088   GFileInfo *info;
7089 
7090   g_return_val_if_fail (G_IS_FILE (file), FALSE);
7091   g_return_val_if_fail (contents != NULL, FALSE);
7092 
7093   in = g_file_read (file, cancellable, error);
7094   if (in == NULL)
7095     return FALSE;
7096 
7097   content = g_byte_array_new ();
7098   pos = 0;
7099 
7100   g_byte_array_set_size (content, pos + GET_CONTENT_BLOCK_SIZE + 1);
7101   while ((res = g_input_stream_read (G_INPUT_STREAM (in),
7102                                      content->data + pos,
7103                                      GET_CONTENT_BLOCK_SIZE,
7104                                      cancellable, error)) > 0)
7105     {
7106       pos += res;
7107       g_byte_array_set_size (content, pos + GET_CONTENT_BLOCK_SIZE + 1);
7108     }
7109 
7110   if (etag_out)
7111     {
7112       *etag_out = NULL;
7113 
7114       info = g_file_input_stream_query_info (in,
7115                                              G_FILE_ATTRIBUTE_ETAG_VALUE,
7116                                              cancellable,
7117                                              NULL);
7118       if (info)
7119         {
7120           *etag_out = g_strdup (g_file_info_get_etag (info));
7121           g_object_unref (info);
7122         }
7123     }
7124 
7125   /* Ignore errors on close */
7126   g_input_stream_close (G_INPUT_STREAM (in), cancellable, NULL);
7127   g_object_unref (in);
7128 
7129   if (res < 0)
7130     {
7131       /* error is set already */
7132       g_byte_array_free (content, TRUE);
7133       return FALSE;
7134     }
7135 
7136   if (length)
7137     *length = pos;
7138 
7139   /* Zero terminate (we got an extra byte allocated for this */
7140   content->data[pos] = 0;
7141 
7142   *contents = (char *)g_byte_array_free (content, FALSE);
7143 
7144   return TRUE;
7145 }
7146 
7147 typedef struct {
7148   GTask *task;
7149   GFileReadMoreCallback read_more_callback;
7150   GByteArray *content;
7151   gsize pos;
7152   char *etag;
7153 } LoadContentsData;
7154 
7155 
7156 static void
load_contents_data_free(LoadContentsData * data)7157 load_contents_data_free (LoadContentsData *data)
7158 {
7159   if (data->content)
7160     g_byte_array_free (data->content, TRUE);
7161   g_free (data->etag);
7162   g_free (data);
7163 }
7164 
7165 static void
load_contents_close_callback(GObject * obj,GAsyncResult * close_res,gpointer user_data)7166 load_contents_close_callback (GObject      *obj,
7167                               GAsyncResult *close_res,
7168                               gpointer      user_data)
7169 {
7170   GInputStream *stream = G_INPUT_STREAM (obj);
7171   LoadContentsData *data = user_data;
7172 
7173   /* Ignore errors here, we're only reading anyway */
7174   g_input_stream_close_finish (stream, close_res, NULL);
7175   g_object_unref (stream);
7176 
7177   g_task_return_boolean (data->task, TRUE);
7178   g_object_unref (data->task);
7179 }
7180 
7181 static void
load_contents_fstat_callback(GObject * obj,GAsyncResult * stat_res,gpointer user_data)7182 load_contents_fstat_callback (GObject      *obj,
7183                               GAsyncResult *stat_res,
7184                               gpointer      user_data)
7185 {
7186   GInputStream *stream = G_INPUT_STREAM (obj);
7187   LoadContentsData *data = user_data;
7188   GFileInfo *info;
7189 
7190   info = g_file_input_stream_query_info_finish (G_FILE_INPUT_STREAM (stream),
7191                                                 stat_res, NULL);
7192   if (info)
7193     {
7194       data->etag = g_strdup (g_file_info_get_etag (info));
7195       g_object_unref (info);
7196     }
7197 
7198   g_input_stream_close_async (stream, 0,
7199                               g_task_get_cancellable (data->task),
7200                               load_contents_close_callback, data);
7201 }
7202 
7203 static void
load_contents_read_callback(GObject * obj,GAsyncResult * read_res,gpointer user_data)7204 load_contents_read_callback (GObject      *obj,
7205                              GAsyncResult *read_res,
7206                              gpointer      user_data)
7207 {
7208   GInputStream *stream = G_INPUT_STREAM (obj);
7209   LoadContentsData *data = user_data;
7210   GError *error = NULL;
7211   gssize read_size;
7212 
7213   read_size = g_input_stream_read_finish (stream, read_res, &error);
7214 
7215   if (read_size < 0)
7216     {
7217       g_task_return_error (data->task, error);
7218       g_object_unref (data->task);
7219 
7220       /* Close the file ignoring any error */
7221       g_input_stream_close_async (stream, 0, NULL, NULL, NULL);
7222       g_object_unref (stream);
7223     }
7224   else if (read_size == 0)
7225     {
7226       g_file_input_stream_query_info_async (G_FILE_INPUT_STREAM (stream),
7227                                             G_FILE_ATTRIBUTE_ETAG_VALUE,
7228                                             0,
7229                                             g_task_get_cancellable (data->task),
7230                                             load_contents_fstat_callback,
7231                                             data);
7232     }
7233   else if (read_size > 0)
7234     {
7235       data->pos += read_size;
7236 
7237       g_byte_array_set_size (data->content,
7238                              data->pos + GET_CONTENT_BLOCK_SIZE);
7239 
7240 
7241       if (data->read_more_callback &&
7242           !data->read_more_callback ((char *)data->content->data, data->pos,
7243                                      g_async_result_get_user_data (G_ASYNC_RESULT (data->task))))
7244         g_file_input_stream_query_info_async (G_FILE_INPUT_STREAM (stream),
7245                                               G_FILE_ATTRIBUTE_ETAG_VALUE,
7246                                               0,
7247                                               g_task_get_cancellable (data->task),
7248                                               load_contents_fstat_callback,
7249                                               data);
7250       else
7251         g_input_stream_read_async (stream,
7252                                    data->content->data + data->pos,
7253                                    GET_CONTENT_BLOCK_SIZE,
7254                                    0,
7255                                    g_task_get_cancellable (data->task),
7256                                    load_contents_read_callback,
7257                                    data);
7258     }
7259 }
7260 
7261 static void
load_contents_open_callback(GObject * obj,GAsyncResult * open_res,gpointer user_data)7262 load_contents_open_callback (GObject      *obj,
7263                              GAsyncResult *open_res,
7264                              gpointer      user_data)
7265 {
7266   GFile *file = G_FILE (obj);
7267   GFileInputStream *stream;
7268   LoadContentsData *data = user_data;
7269   GError *error = NULL;
7270 
7271   stream = g_file_read_finish (file, open_res, &error);
7272 
7273   if (stream)
7274     {
7275       g_byte_array_set_size (data->content,
7276                              data->pos + GET_CONTENT_BLOCK_SIZE);
7277       g_input_stream_read_async (G_INPUT_STREAM (stream),
7278                                  data->content->data + data->pos,
7279                                  GET_CONTENT_BLOCK_SIZE,
7280                                  0,
7281                                  g_task_get_cancellable (data->task),
7282                                  load_contents_read_callback,
7283                                  data);
7284     }
7285   else
7286     {
7287       g_task_return_error (data->task, error);
7288       g_object_unref (data->task);
7289     }
7290 }
7291 
7292 /**
7293  * g_file_load_partial_contents_async: (skip)
7294  * @file: input #GFile
7295  * @cancellable: optional #GCancellable object, %NULL to ignore
7296  * @read_more_callback: (scope call) (closure user_data): a
7297  *     #GFileReadMoreCallback to receive partial data
7298  *     and to specify whether further data should be read
7299  * @callback: (scope async) (closure user_data): a #GAsyncReadyCallback to call
7300  *     when the request is satisfied
7301  * @user_data: the data to pass to the callback functions
7302  *
7303  * Reads the partial contents of a file. A #GFileReadMoreCallback should
7304  * be used to stop reading from the file when appropriate, else this
7305  * function will behave exactly as g_file_load_contents_async(). This
7306  * operation can be finished by g_file_load_partial_contents_finish().
7307  *
7308  * Users of this function should be aware that @user_data is passed to
7309  * both the @read_more_callback and the @callback.
7310  *
7311  * If @cancellable is not %NULL, then the operation can be cancelled by
7312  * triggering the cancellable object from another thread. If the operation
7313  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
7314  */
7315 void
g_file_load_partial_contents_async(GFile * file,GCancellable * cancellable,GFileReadMoreCallback read_more_callback,GAsyncReadyCallback callback,gpointer user_data)7316 g_file_load_partial_contents_async (GFile                 *file,
7317                                     GCancellable          *cancellable,
7318                                     GFileReadMoreCallback  read_more_callback,
7319                                     GAsyncReadyCallback    callback,
7320                                     gpointer               user_data)
7321 {
7322   LoadContentsData *data;
7323 
7324   g_return_if_fail (G_IS_FILE (file));
7325 
7326   data = g_new0 (LoadContentsData, 1);
7327   data->read_more_callback = read_more_callback;
7328   data->content = g_byte_array_new ();
7329 
7330   data->task = g_task_new (file, cancellable, callback, user_data);
7331   g_task_set_source_tag (data->task, g_file_load_partial_contents_async);
7332   g_task_set_task_data (data->task, data, (GDestroyNotify)load_contents_data_free);
7333 
7334   g_file_read_async (file,
7335                      0,
7336                      g_task_get_cancellable (data->task),
7337                      load_contents_open_callback,
7338                      data);
7339 }
7340 
7341 /**
7342  * g_file_load_partial_contents_finish:
7343  * @file: input #GFile
7344  * @res: a #GAsyncResult
7345  * @contents: (out) (transfer full) (element-type guint8) (array length=length): a location to place the contents of the file
7346  * @length: (out) (optional): a location to place the length of the contents of the file,
7347  *     or %NULL if the length is not needed
7348  * @etag_out: (out) (optional) (nullable): a location to place the current entity tag for the file,
7349  *     or %NULL if the entity tag is not needed
7350  * @error: a #GError, or %NULL
7351  *
7352  * Finishes an asynchronous partial load operation that was started
7353  * with g_file_load_partial_contents_async(). The data is always
7354  * zero-terminated, but this is not included in the resultant @length.
7355  * The returned @contents should be freed with g_free() when no longer
7356  * needed.
7357  *
7358  * Returns: %TRUE if the load was successful. If %FALSE and @error is
7359  *     present, it will be set appropriately.
7360  */
7361 gboolean
g_file_load_partial_contents_finish(GFile * file,GAsyncResult * res,char ** contents,gsize * length,char ** etag_out,GError ** error)7362 g_file_load_partial_contents_finish (GFile         *file,
7363                                      GAsyncResult  *res,
7364                                      char         **contents,
7365                                      gsize         *length,
7366                                      char         **etag_out,
7367                                      GError       **error)
7368 {
7369   GTask *task;
7370   LoadContentsData *data;
7371 
7372   g_return_val_if_fail (G_IS_FILE (file), FALSE);
7373   g_return_val_if_fail (g_task_is_valid (res, file), FALSE);
7374   g_return_val_if_fail (contents != NULL, FALSE);
7375 
7376   task = G_TASK (res);
7377 
7378   if (!g_task_propagate_boolean (task, error))
7379     {
7380       if (length)
7381         *length = 0;
7382       return FALSE;
7383     }
7384 
7385   data = g_task_get_task_data (task);
7386 
7387   if (length)
7388     *length = data->pos;
7389 
7390   if (etag_out)
7391     {
7392       *etag_out = data->etag;
7393       data->etag = NULL;
7394     }
7395 
7396   /* Zero terminate */
7397   g_byte_array_set_size (data->content, data->pos + 1);
7398   data->content->data[data->pos] = 0;
7399 
7400   *contents = (char *)g_byte_array_free (data->content, FALSE);
7401   data->content = NULL;
7402 
7403   return TRUE;
7404 }
7405 
7406 /**
7407  * g_file_load_contents_async:
7408  * @file: input #GFile
7409  * @cancellable: optional #GCancellable object, %NULL to ignore
7410  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
7411  * @user_data: the data to pass to callback function
7412  *
7413  * Starts an asynchronous load of the @file's contents.
7414  *
7415  * For more details, see g_file_load_contents() which is
7416  * the synchronous version of this call.
7417  *
7418  * When the load operation has completed, @callback will be called
7419  * with @user data. To finish the operation, call
7420  * g_file_load_contents_finish() with the #GAsyncResult returned by
7421  * the @callback.
7422  *
7423  * If @cancellable is not %NULL, then the operation can be cancelled by
7424  * triggering the cancellable object from another thread. If the operation
7425  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
7426  */
7427 void
g_file_load_contents_async(GFile * file,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)7428 g_file_load_contents_async (GFile               *file,
7429                            GCancellable        *cancellable,
7430                            GAsyncReadyCallback  callback,
7431                            gpointer             user_data)
7432 {
7433   g_file_load_partial_contents_async (file,
7434                                       cancellable,
7435                                       NULL,
7436                                       callback, user_data);
7437 }
7438 
7439 /**
7440  * g_file_load_contents_finish:
7441  * @file: input #GFile
7442  * @res: a #GAsyncResult
7443  * @contents: (out) (transfer full) (element-type guint8) (array length=length): a location to place the contents of the file
7444  * @length: (out) (optional): a location to place the length of the contents of the file,
7445  *     or %NULL if the length is not needed
7446  * @etag_out: (out) (optional) (nullable): a location to place the current entity tag for the file,
7447  *     or %NULL if the entity tag is not needed
7448  * @error: a #GError, or %NULL
7449  *
7450  * Finishes an asynchronous load of the @file's contents.
7451  * The contents are placed in @contents, and @length is set to the
7452  * size of the @contents string. The @contents should be freed with
7453  * g_free() when no longer needed. If @etag_out is present, it will be
7454  * set to the new entity tag for the @file.
7455  *
7456  * Returns: %TRUE if the load was successful. If %FALSE and @error is
7457  *     present, it will be set appropriately.
7458  */
7459 gboolean
g_file_load_contents_finish(GFile * file,GAsyncResult * res,char ** contents,gsize * length,char ** etag_out,GError ** error)7460 g_file_load_contents_finish (GFile         *file,
7461                              GAsyncResult  *res,
7462                              char         **contents,
7463                              gsize         *length,
7464                              char         **etag_out,
7465                              GError       **error)
7466 {
7467   return g_file_load_partial_contents_finish (file,
7468                                               res,
7469                                               contents,
7470                                               length,
7471                                               etag_out,
7472                                               error);
7473 }
7474 
7475 /**
7476  * g_file_replace_contents:
7477  * @file: input #GFile
7478  * @contents: (element-type guint8) (array length=length): a string containing the new contents for @file
7479  * @length: the length of @contents in bytes
7480  * @etag: (nullable): the old [entity-tag][gfile-etag] for the document,
7481  *     or %NULL
7482  * @make_backup: %TRUE if a backup should be created
7483  * @flags: a set of #GFileCreateFlags
7484  * @new_etag: (out) (optional) (nullable): a location to a new [entity tag][gfile-etag]
7485  *      for the document. This should be freed with g_free() when no longer
7486  *      needed, or %NULL
7487  * @cancellable: optional #GCancellable object, %NULL to ignore
7488  * @error: a #GError, or %NULL
7489  *
7490  * Replaces the contents of @file with @contents of @length bytes.
7491  *
7492  * If @etag is specified (not %NULL), any existing file must have that etag,
7493  * or the error %G_IO_ERROR_WRONG_ETAG will be returned.
7494  *
7495  * If @make_backup is %TRUE, this function will attempt to make a backup
7496  * of @file. Internally, it uses g_file_replace(), so will try to replace the
7497  * file contents in the safest way possible. For example, atomic renames are
7498  * used when replacing local files’ contents.
7499  *
7500  * If @cancellable is not %NULL, then the operation can be cancelled by
7501  * triggering the cancellable object from another thread. If the operation
7502  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
7503  *
7504  * The returned @new_etag can be used to verify that the file hasn't
7505  * changed the next time it is saved over.
7506  *
7507  * Returns: %TRUE if successful. If an error has occurred, this function
7508  *     will return %FALSE and set @error appropriately if present.
7509  */
7510 gboolean
g_file_replace_contents(GFile * file,const char * contents,gsize length,const char * etag,gboolean make_backup,GFileCreateFlags flags,char ** new_etag,GCancellable * cancellable,GError ** error)7511 g_file_replace_contents (GFile             *file,
7512                          const char        *contents,
7513                          gsize              length,
7514                          const char        *etag,
7515                          gboolean           make_backup,
7516                          GFileCreateFlags   flags,
7517                          char             **new_etag,
7518                          GCancellable      *cancellable,
7519                          GError           **error)
7520 {
7521   GFileOutputStream *out;
7522   gsize pos, remainder;
7523   gssize res;
7524   gboolean ret;
7525 
7526   g_return_val_if_fail (G_IS_FILE (file), FALSE);
7527   g_return_val_if_fail (contents != NULL, FALSE);
7528 
7529   out = g_file_replace (file, etag, make_backup, flags, cancellable, error);
7530   if (out == NULL)
7531     return FALSE;
7532 
7533   pos = 0;
7534   remainder = length;
7535   while (remainder > 0 &&
7536          (res = g_output_stream_write (G_OUTPUT_STREAM (out),
7537                                        contents + pos,
7538                                        MIN (remainder, GET_CONTENT_BLOCK_SIZE),
7539                                        cancellable,
7540                                        error)) > 0)
7541     {
7542       pos += res;
7543       remainder -= res;
7544     }
7545 
7546   if (remainder > 0 && res < 0)
7547     {
7548       /* Ignore errors on close */
7549       g_output_stream_close (G_OUTPUT_STREAM (out), cancellable, NULL);
7550       g_object_unref (out);
7551 
7552       /* error is set already */
7553       return FALSE;
7554     }
7555 
7556   ret = g_output_stream_close (G_OUTPUT_STREAM (out), cancellable, error);
7557 
7558   if (new_etag)
7559     *new_etag = g_file_output_stream_get_etag (out);
7560 
7561   g_object_unref (out);
7562 
7563   return ret;
7564 }
7565 
7566 typedef struct {
7567   GTask *task;
7568   GBytes *content;
7569   gsize pos;
7570   char *etag;
7571   gboolean failed;
7572 } ReplaceContentsData;
7573 
7574 static void
replace_contents_data_free(ReplaceContentsData * data)7575 replace_contents_data_free (ReplaceContentsData *data)
7576 {
7577   g_bytes_unref (data->content);
7578   g_free (data->etag);
7579   g_free (data);
7580 }
7581 
7582 static void
replace_contents_close_callback(GObject * obj,GAsyncResult * close_res,gpointer user_data)7583 replace_contents_close_callback (GObject      *obj,
7584                                  GAsyncResult *close_res,
7585                                  gpointer      user_data)
7586 {
7587   GOutputStream *stream = G_OUTPUT_STREAM (obj);
7588   ReplaceContentsData *data = user_data;
7589 
7590   /* Ignore errors here, we're only reading anyway */
7591   g_output_stream_close_finish (stream, close_res, NULL);
7592 
7593   if (!data->failed)
7594     {
7595       data->etag = g_file_output_stream_get_etag (G_FILE_OUTPUT_STREAM (stream));
7596       g_task_return_boolean (data->task, TRUE);
7597     }
7598   g_object_unref (data->task);
7599 }
7600 
7601 static void
replace_contents_write_callback(GObject * obj,GAsyncResult * read_res,gpointer user_data)7602 replace_contents_write_callback (GObject      *obj,
7603                                  GAsyncResult *read_res,
7604                                  gpointer      user_data)
7605 {
7606   GOutputStream *stream = G_OUTPUT_STREAM (obj);
7607   ReplaceContentsData *data = user_data;
7608   GError *error = NULL;
7609   gssize write_size;
7610 
7611   write_size = g_output_stream_write_finish (stream, read_res, &error);
7612 
7613   if (write_size <= 0)
7614     {
7615       /* Error or EOF, close the file */
7616       if (write_size < 0)
7617         {
7618           data->failed = TRUE;
7619           g_task_return_error (data->task, error);
7620         }
7621       g_output_stream_close_async (stream, 0,
7622                                    g_task_get_cancellable (data->task),
7623                                    replace_contents_close_callback, data);
7624     }
7625   else if (write_size > 0)
7626     {
7627       const gchar *content;
7628       gsize length;
7629 
7630       content = g_bytes_get_data (data->content, &length);
7631       data->pos += write_size;
7632 
7633       if (data->pos >= length)
7634         g_output_stream_close_async (stream, 0,
7635                                      g_task_get_cancellable (data->task),
7636                                      replace_contents_close_callback, data);
7637       else
7638         g_output_stream_write_async (stream,
7639                                      content + data->pos,
7640                                      length - data->pos,
7641                                      0,
7642                                      g_task_get_cancellable (data->task),
7643                                      replace_contents_write_callback,
7644                                      data);
7645     }
7646 }
7647 
7648 static void
replace_contents_open_callback(GObject * obj,GAsyncResult * open_res,gpointer user_data)7649 replace_contents_open_callback (GObject      *obj,
7650                                 GAsyncResult *open_res,
7651                                 gpointer      user_data)
7652 {
7653   GFile *file = G_FILE (obj);
7654   GFileOutputStream *stream;
7655   ReplaceContentsData *data = user_data;
7656   GError *error = NULL;
7657 
7658   stream = g_file_replace_finish (file, open_res, &error);
7659 
7660   if (stream)
7661     {
7662       const gchar *content;
7663       gsize length;
7664 
7665       content = g_bytes_get_data (data->content, &length);
7666       g_output_stream_write_async (G_OUTPUT_STREAM (stream),
7667                                    content + data->pos,
7668                                    length - data->pos,
7669                                    0,
7670                                    g_task_get_cancellable (data->task),
7671                                    replace_contents_write_callback,
7672                                    data);
7673       g_object_unref (stream);  /* ownership is transferred to the write_async() call above */
7674     }
7675   else
7676     {
7677       g_task_return_error (data->task, error);
7678       g_object_unref (data->task);
7679     }
7680 }
7681 
7682 /**
7683  * g_file_replace_contents_async:
7684  * @file: input #GFile
7685  * @contents: (element-type guint8) (array length=length): string of contents to replace the file with
7686  * @length: the length of @contents in bytes
7687  * @etag: (nullable): a new [entity tag][gfile-etag] for the @file, or %NULL
7688  * @make_backup: %TRUE if a backup should be created
7689  * @flags: a set of #GFileCreateFlags
7690  * @cancellable: optional #GCancellable object, %NULL to ignore
7691  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
7692  * @user_data: the data to pass to callback function
7693  *
7694  * Starts an asynchronous replacement of @file with the given
7695  * @contents of @length bytes. @etag will replace the document's
7696  * current entity tag.
7697  *
7698  * When this operation has completed, @callback will be called with
7699  * @user_user data, and the operation can be finalized with
7700  * g_file_replace_contents_finish().
7701  *
7702  * If @cancellable is not %NULL, then the operation can be cancelled by
7703  * triggering the cancellable object from another thread. If the operation
7704  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
7705  *
7706  * If @make_backup is %TRUE, this function will attempt to
7707  * make a backup of @file.
7708  *
7709  * Note that no copy of @contents will be made, so it must stay valid
7710  * until @callback is called. See g_file_replace_contents_bytes_async()
7711  * for a #GBytes version that will automatically hold a reference to the
7712  * contents (without copying) for the duration of the call.
7713  */
7714 void
g_file_replace_contents_async(GFile * file,const char * contents,gsize length,const char * etag,gboolean make_backup,GFileCreateFlags flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)7715 g_file_replace_contents_async  (GFile               *file,
7716                                 const char          *contents,
7717                                 gsize                length,
7718                                 const char          *etag,
7719                                 gboolean             make_backup,
7720                                 GFileCreateFlags     flags,
7721                                 GCancellable        *cancellable,
7722                                 GAsyncReadyCallback  callback,
7723                                 gpointer             user_data)
7724 {
7725   GBytes *bytes;
7726 
7727   bytes = g_bytes_new_static (contents, length);
7728   g_file_replace_contents_bytes_async (file, bytes, etag, make_backup, flags,
7729       cancellable, callback, user_data);
7730   g_bytes_unref (bytes);
7731 }
7732 
7733 /**
7734  * g_file_replace_contents_bytes_async:
7735  * @file: input #GFile
7736  * @contents: a #GBytes
7737  * @etag: (nullable): a new [entity tag][gfile-etag] for the @file, or %NULL
7738  * @make_backup: %TRUE if a backup should be created
7739  * @flags: a set of #GFileCreateFlags
7740  * @cancellable: optional #GCancellable object, %NULL to ignore
7741  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
7742  * @user_data: the data to pass to callback function
7743  *
7744  * Same as g_file_replace_contents_async() but takes a #GBytes input instead.
7745  * This function will keep a ref on @contents until the operation is done.
7746  * Unlike g_file_replace_contents_async() this allows forgetting about the
7747  * content without waiting for the callback.
7748  *
7749  * When this operation has completed, @callback will be called with
7750  * @user_user data, and the operation can be finalized with
7751  * g_file_replace_contents_finish().
7752  *
7753  * Since: 2.40
7754  */
7755 void
g_file_replace_contents_bytes_async(GFile * file,GBytes * contents,const char * etag,gboolean make_backup,GFileCreateFlags flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)7756 g_file_replace_contents_bytes_async  (GFile               *file,
7757                                       GBytes              *contents,
7758                                       const char          *etag,
7759                                       gboolean             make_backup,
7760                                       GFileCreateFlags     flags,
7761                                       GCancellable        *cancellable,
7762                                       GAsyncReadyCallback  callback,
7763                                       gpointer             user_data)
7764 {
7765   ReplaceContentsData *data;
7766 
7767   g_return_if_fail (G_IS_FILE (file));
7768   g_return_if_fail (contents != NULL);
7769 
7770   data = g_new0 (ReplaceContentsData, 1);
7771 
7772   data->content = g_bytes_ref (contents);
7773 
7774   data->task = g_task_new (file, cancellable, callback, user_data);
7775   g_task_set_source_tag (data->task, g_file_replace_contents_bytes_async);
7776   g_task_set_task_data (data->task, data, (GDestroyNotify)replace_contents_data_free);
7777 
7778   g_file_replace_async (file,
7779                         etag,
7780                         make_backup,
7781                         flags,
7782                         0,
7783                         g_task_get_cancellable (data->task),
7784                         replace_contents_open_callback,
7785                         data);
7786 }
7787 
7788 /**
7789  * g_file_replace_contents_finish:
7790  * @file: input #GFile
7791  * @res: a #GAsyncResult
7792  * @new_etag: (out) (optional) (nullable): a location of a new [entity tag][gfile-etag]
7793  *     for the document. This should be freed with g_free() when it is no
7794  *     longer needed, or %NULL
7795  * @error: a #GError, or %NULL
7796  *
7797  * Finishes an asynchronous replace of the given @file. See
7798  * g_file_replace_contents_async(). Sets @new_etag to the new entity
7799  * tag for the document, if present.
7800  *
7801  * Returns: %TRUE on success, %FALSE on failure.
7802  */
7803 gboolean
g_file_replace_contents_finish(GFile * file,GAsyncResult * res,char ** new_etag,GError ** error)7804 g_file_replace_contents_finish (GFile         *file,
7805                                 GAsyncResult  *res,
7806                                 char         **new_etag,
7807                                 GError       **error)
7808 {
7809   GTask *task;
7810   ReplaceContentsData *data;
7811 
7812   g_return_val_if_fail (G_IS_FILE (file), FALSE);
7813   g_return_val_if_fail (g_task_is_valid (res, file), FALSE);
7814 
7815   task = G_TASK (res);
7816 
7817   if (!g_task_propagate_boolean (task, error))
7818     return FALSE;
7819 
7820   data = g_task_get_task_data (task);
7821 
7822   if (new_etag)
7823     {
7824       *new_etag = data->etag;
7825       data->etag = NULL; /* Take ownership */
7826     }
7827 
7828   return TRUE;
7829 }
7830 
7831 gboolean
g_file_real_measure_disk_usage(GFile * file,GFileMeasureFlags flags,GCancellable * cancellable,GFileMeasureProgressCallback progress_callback,gpointer progress_data,guint64 * disk_usage,guint64 * num_dirs,guint64 * num_files,GError ** error)7832 g_file_real_measure_disk_usage (GFile                         *file,
7833                                 GFileMeasureFlags              flags,
7834                                 GCancellable                  *cancellable,
7835                                 GFileMeasureProgressCallback   progress_callback,
7836                                 gpointer                       progress_data,
7837                                 guint64                       *disk_usage,
7838                                 guint64                       *num_dirs,
7839                                 guint64                       *num_files,
7840                                 GError                       **error)
7841 {
7842   g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
7843                        "Operation not supported for the current backend.");
7844   return FALSE;
7845 }
7846 
7847 typedef struct
7848 {
7849   GFileMeasureFlags             flags;
7850   GFileMeasureProgressCallback  progress_callback;
7851   gpointer                      progress_data;
7852 } MeasureTaskData;
7853 
7854 typedef struct
7855 {
7856   guint64 disk_usage;
7857   guint64 num_dirs;
7858   guint64 num_files;
7859 } MeasureResult;
7860 
7861 typedef struct
7862 {
7863   GFileMeasureProgressCallback callback;
7864   gpointer                     user_data;
7865   gboolean                     reporting;
7866   guint64                      current_size;
7867   guint64                      num_dirs;
7868   guint64                      num_files;
7869 } MeasureProgress;
7870 
7871 static gboolean
measure_disk_usage_invoke_progress(gpointer user_data)7872 measure_disk_usage_invoke_progress (gpointer user_data)
7873 {
7874   MeasureProgress *progress = user_data;
7875 
7876   (* progress->callback) (progress->reporting,
7877                           progress->current_size, progress->num_dirs, progress->num_files,
7878                           progress->user_data);
7879 
7880   return FALSE;
7881 }
7882 
7883 static void
measure_disk_usage_progress(gboolean reporting,guint64 current_size,guint64 num_dirs,guint64 num_files,gpointer user_data)7884 measure_disk_usage_progress (gboolean reporting,
7885                              guint64  current_size,
7886                              guint64  num_dirs,
7887                              guint64  num_files,
7888                              gpointer user_data)
7889 {
7890   MeasureProgress progress;
7891   GTask *task = user_data;
7892   MeasureTaskData *data;
7893 
7894   data = g_task_get_task_data (task);
7895 
7896   progress.callback = data->progress_callback;
7897   progress.user_data = data->progress_data;
7898   progress.reporting = reporting;
7899   progress.current_size = current_size;
7900   progress.num_dirs = num_dirs;
7901   progress.num_files = num_files;
7902 
7903   g_main_context_invoke_full (g_task_get_context (task),
7904                               g_task_get_priority (task),
7905                               measure_disk_usage_invoke_progress,
7906                               g_memdup2 (&progress, sizeof progress),
7907                               g_free);
7908 }
7909 
7910 static void
measure_disk_usage_thread(GTask * task,gpointer source_object,gpointer task_data,GCancellable * cancellable)7911 measure_disk_usage_thread (GTask        *task,
7912                            gpointer      source_object,
7913                            gpointer      task_data,
7914                            GCancellable *cancellable)
7915 {
7916   MeasureTaskData *data = task_data;
7917   GError *error = NULL;
7918   MeasureResult result = { 0, };
7919 
7920   if (g_file_measure_disk_usage (source_object, data->flags, cancellable,
7921                                  data->progress_callback ? measure_disk_usage_progress : NULL, task,
7922                                  &result.disk_usage, &result.num_dirs, &result.num_files,
7923                                  &error))
7924     g_task_return_pointer (task, g_memdup2 (&result, sizeof result), g_free);
7925   else
7926     g_task_return_error (task, error);
7927 }
7928 
7929 static void
g_file_real_measure_disk_usage_async(GFile * file,GFileMeasureFlags flags,gint io_priority,GCancellable * cancellable,GFileMeasureProgressCallback progress_callback,gpointer progress_data,GAsyncReadyCallback callback,gpointer user_data)7930 g_file_real_measure_disk_usage_async (GFile                        *file,
7931                                       GFileMeasureFlags             flags,
7932                                       gint                          io_priority,
7933                                       GCancellable                 *cancellable,
7934                                       GFileMeasureProgressCallback  progress_callback,
7935                                       gpointer                      progress_data,
7936                                       GAsyncReadyCallback           callback,
7937                                       gpointer                      user_data)
7938 {
7939   MeasureTaskData data;
7940   GTask *task;
7941 
7942   data.flags = flags;
7943   data.progress_callback = progress_callback;
7944   data.progress_data = progress_data;
7945 
7946   task = g_task_new (file, cancellable, callback, user_data);
7947   g_task_set_source_tag (task, g_file_real_measure_disk_usage_async);
7948   g_task_set_task_data (task, g_memdup2 (&data, sizeof data), g_free);
7949   g_task_set_priority (task, io_priority);
7950 
7951   g_task_run_in_thread (task, measure_disk_usage_thread);
7952   g_object_unref (task);
7953 }
7954 
7955 static gboolean
g_file_real_measure_disk_usage_finish(GFile * file,GAsyncResult * result,guint64 * disk_usage,guint64 * num_dirs,guint64 * num_files,GError ** error)7956 g_file_real_measure_disk_usage_finish (GFile         *file,
7957                                        GAsyncResult  *result,
7958                                        guint64       *disk_usage,
7959                                        guint64       *num_dirs,
7960                                        guint64       *num_files,
7961                                        GError       **error)
7962 {
7963   MeasureResult *measure_result;
7964 
7965   g_return_val_if_fail (g_task_is_valid (result, file), FALSE);
7966 
7967   measure_result = g_task_propagate_pointer (G_TASK (result), error);
7968 
7969   if (measure_result == NULL)
7970     return FALSE;
7971 
7972   if (disk_usage)
7973     *disk_usage = measure_result->disk_usage;
7974 
7975   if (num_dirs)
7976     *num_dirs = measure_result->num_dirs;
7977 
7978   if (num_files)
7979     *num_files = measure_result->num_files;
7980 
7981   g_free (measure_result);
7982 
7983   return TRUE;
7984 }
7985 
7986 /**
7987  * g_file_measure_disk_usage:
7988  * @file: a #GFile
7989  * @flags: #GFileMeasureFlags
7990  * @cancellable: (nullable): optional #GCancellable
7991  * @progress_callback: (nullable): a #GFileMeasureProgressCallback
7992  * @progress_data: user_data for @progress_callback
7993  * @disk_usage: (out) (optional): the number of bytes of disk space used
7994  * @num_dirs: (out) (optional): the number of directories encountered
7995  * @num_files: (out) (optional): the number of non-directories encountered
7996  * @error: (nullable): %NULL, or a pointer to a %NULL #GError pointer
7997  *
7998  * Recursively measures the disk usage of @file.
7999  *
8000  * This is essentially an analog of the 'du' command, but it also
8001  * reports the number of directories and non-directory files encountered
8002  * (including things like symbolic links).
8003  *
8004  * By default, errors are only reported against the toplevel file
8005  * itself.  Errors found while recursing are silently ignored, unless
8006  * %G_FILE_MEASURE_REPORT_ANY_ERROR is given in @flags.
8007  *
8008  * The returned size, @disk_usage, is in bytes and should be formatted
8009  * with g_format_size() in order to get something reasonable for showing
8010  * in a user interface.
8011  *
8012  * @progress_callback and @progress_data can be given to request
8013  * periodic progress updates while scanning.  See the documentation for
8014  * #GFileMeasureProgressCallback for information about when and how the
8015  * callback will be invoked.
8016  *
8017  * Returns: %TRUE if successful, with the out parameters set.
8018  *          %FALSE otherwise, with @error set.
8019  *
8020  * Since: 2.38
8021  **/
8022 gboolean
g_file_measure_disk_usage(GFile * file,GFileMeasureFlags flags,GCancellable * cancellable,GFileMeasureProgressCallback progress_callback,gpointer progress_data,guint64 * disk_usage,guint64 * num_dirs,guint64 * num_files,GError ** error)8023 g_file_measure_disk_usage (GFile                         *file,
8024                            GFileMeasureFlags              flags,
8025                            GCancellable                  *cancellable,
8026                            GFileMeasureProgressCallback   progress_callback,
8027                            gpointer                       progress_data,
8028                            guint64                       *disk_usage,
8029                            guint64                       *num_dirs,
8030                            guint64                       *num_files,
8031                            GError                       **error)
8032 {
8033   g_return_val_if_fail (G_IS_FILE (file), FALSE);
8034   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
8035   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
8036 
8037   return G_FILE_GET_IFACE (file)->measure_disk_usage (file, flags, cancellable,
8038                                                       progress_callback, progress_data,
8039                                                       disk_usage, num_dirs, num_files,
8040                                                       error);
8041 }
8042 
8043 /**
8044  * g_file_measure_disk_usage_async:
8045  * @file: a #GFile
8046  * @flags: #GFileMeasureFlags
8047  * @io_priority: the [I/O priority][io-priority] of the request
8048  * @cancellable: (nullable): optional #GCancellable
8049  * @progress_callback: (nullable): a #GFileMeasureProgressCallback
8050  * @progress_data: user_data for @progress_callback
8051  * @callback: (nullable): a #GAsyncReadyCallback to call when complete
8052  * @user_data: the data to pass to callback function
8053  *
8054  * Recursively measures the disk usage of @file.
8055  *
8056  * This is the asynchronous version of g_file_measure_disk_usage().  See
8057  * there for more information.
8058  *
8059  * Since: 2.38
8060  **/
8061 void
g_file_measure_disk_usage_async(GFile * file,GFileMeasureFlags flags,gint io_priority,GCancellable * cancellable,GFileMeasureProgressCallback progress_callback,gpointer progress_data,GAsyncReadyCallback callback,gpointer user_data)8062 g_file_measure_disk_usage_async (GFile                        *file,
8063                                  GFileMeasureFlags             flags,
8064                                  gint                          io_priority,
8065                                  GCancellable                 *cancellable,
8066                                  GFileMeasureProgressCallback  progress_callback,
8067                                  gpointer                      progress_data,
8068                                  GAsyncReadyCallback           callback,
8069                                  gpointer                      user_data)
8070 {
8071   g_return_if_fail (G_IS_FILE (file));
8072   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
8073 
8074   G_FILE_GET_IFACE (file)->measure_disk_usage_async (file, flags, io_priority, cancellable,
8075                                                      progress_callback, progress_data,
8076                                                      callback, user_data);
8077 }
8078 
8079 /**
8080  * g_file_measure_disk_usage_finish:
8081  * @file: a #GFile
8082  * @result: the #GAsyncResult passed to your #GAsyncReadyCallback
8083  * @disk_usage: (out) (optional): the number of bytes of disk space used
8084  * @num_dirs: (out) (optional): the number of directories encountered
8085  * @num_files: (out) (optional): the number of non-directories encountered
8086  * @error: (nullable): %NULL, or a pointer to a %NULL #GError pointer
8087  *
8088  * Collects the results from an earlier call to
8089  * g_file_measure_disk_usage_async().  See g_file_measure_disk_usage() for
8090  * more information.
8091  *
8092  * Returns: %TRUE if successful, with the out parameters set.
8093  *          %FALSE otherwise, with @error set.
8094  *
8095  * Since: 2.38
8096  **/
8097 gboolean
g_file_measure_disk_usage_finish(GFile * file,GAsyncResult * result,guint64 * disk_usage,guint64 * num_dirs,guint64 * num_files,GError ** error)8098 g_file_measure_disk_usage_finish (GFile         *file,
8099                                   GAsyncResult  *result,
8100                                   guint64       *disk_usage,
8101                                   guint64       *num_dirs,
8102                                   guint64       *num_files,
8103                                   GError       **error)
8104 {
8105   g_return_val_if_fail (G_IS_FILE (file), FALSE);
8106   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
8107 
8108   return G_FILE_GET_IFACE (file)->measure_disk_usage_finish (file, result, disk_usage, num_dirs, num_files, error);
8109 }
8110 
8111 /**
8112  * g_file_start_mountable:
8113  * @file: input #GFile
8114  * @flags: flags affecting the operation
8115  * @start_operation: (nullable): a #GMountOperation, or %NULL to avoid user interaction
8116  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
8117  * @callback: (nullable): a #GAsyncReadyCallback to call when the request is satisfied, or %NULL
8118  * @user_data: the data to pass to callback function
8119  *
8120  * Starts a file of type #G_FILE_TYPE_MOUNTABLE.
8121  * Using @start_operation, you can request callbacks when, for instance,
8122  * passwords are needed during authentication.
8123  *
8124  * If @cancellable is not %NULL, then the operation can be cancelled by
8125  * triggering the cancellable object from another thread. If the operation
8126  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
8127  *
8128  * When the operation is finished, @callback will be called.
8129  * You can then call g_file_mount_mountable_finish() to get
8130  * the result of the operation.
8131  *
8132  * Since: 2.22
8133  */
8134 void
g_file_start_mountable(GFile * file,GDriveStartFlags flags,GMountOperation * start_operation,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)8135 g_file_start_mountable (GFile               *file,
8136                         GDriveStartFlags     flags,
8137                         GMountOperation     *start_operation,
8138                         GCancellable        *cancellable,
8139                         GAsyncReadyCallback  callback,
8140                         gpointer             user_data)
8141 {
8142   GFileIface *iface;
8143 
8144   g_return_if_fail (G_IS_FILE (file));
8145 
8146   iface = G_FILE_GET_IFACE (file);
8147 
8148   if (iface->start_mountable == NULL)
8149     {
8150       g_task_report_new_error (file, callback, user_data,
8151                                g_file_start_mountable,
8152                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
8153                                _("Operation not supported"));
8154       return;
8155     }
8156 
8157   (* iface->start_mountable) (file,
8158                               flags,
8159                               start_operation,
8160                               cancellable,
8161                               callback,
8162                               user_data);
8163 }
8164 
8165 /**
8166  * g_file_start_mountable_finish:
8167  * @file: input #GFile
8168  * @result: a #GAsyncResult
8169  * @error: a #GError, or %NULL
8170  *
8171  * Finishes a start operation. See g_file_start_mountable() for details.
8172  *
8173  * Finish an asynchronous start operation that was started
8174  * with g_file_start_mountable().
8175  *
8176  * Returns: %TRUE if the operation finished successfully. %FALSE
8177  * otherwise.
8178  *
8179  * Since: 2.22
8180  */
8181 gboolean
g_file_start_mountable_finish(GFile * file,GAsyncResult * result,GError ** error)8182 g_file_start_mountable_finish (GFile         *file,
8183                                GAsyncResult  *result,
8184                                GError       **error)
8185 {
8186   GFileIface *iface;
8187 
8188   g_return_val_if_fail (G_IS_FILE (file), FALSE);
8189   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
8190 
8191   if (g_async_result_legacy_propagate_error (result, error))
8192     return FALSE;
8193   else if (g_async_result_is_tagged (result, g_file_start_mountable))
8194     return g_task_propagate_boolean (G_TASK (result), error);
8195 
8196   iface = G_FILE_GET_IFACE (file);
8197   return (* iface->start_mountable_finish) (file, result, error);
8198 }
8199 
8200 /**
8201  * g_file_stop_mountable:
8202  * @file: input #GFile
8203  * @flags: flags affecting the operation
8204  * @mount_operation: (nullable): a #GMountOperation,
8205  *     or %NULL to avoid user interaction.
8206  * @cancellable: (nullable): optional #GCancellable object,
8207  *     %NULL to ignore
8208  * @callback: (nullable): a #GAsyncReadyCallback to call
8209  *     when the request is satisfied, or %NULL
8210  * @user_data: the data to pass to callback function
8211  *
8212  * Stops a file of type #G_FILE_TYPE_MOUNTABLE.
8213  *
8214  * If @cancellable is not %NULL, then the operation can be cancelled by
8215  * triggering the cancellable object from another thread. If the operation
8216  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
8217  *
8218  * When the operation is finished, @callback will be called.
8219  * You can then call g_file_stop_mountable_finish() to get
8220  * the result of the operation.
8221  *
8222  * Since: 2.22
8223  */
8224 void
g_file_stop_mountable(GFile * file,GMountUnmountFlags flags,GMountOperation * mount_operation,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)8225 g_file_stop_mountable (GFile               *file,
8226                        GMountUnmountFlags   flags,
8227                        GMountOperation     *mount_operation,
8228                        GCancellable        *cancellable,
8229                        GAsyncReadyCallback  callback,
8230                        gpointer             user_data)
8231 {
8232   GFileIface *iface;
8233 
8234   g_return_if_fail (G_IS_FILE (file));
8235 
8236   iface = G_FILE_GET_IFACE (file);
8237 
8238   if (iface->stop_mountable == NULL)
8239     {
8240       g_task_report_new_error (file, callback, user_data,
8241                                g_file_stop_mountable,
8242                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
8243                                _("Operation not supported"));
8244       return;
8245     }
8246 
8247   (* iface->stop_mountable) (file,
8248                              flags,
8249                              mount_operation,
8250                              cancellable,
8251                              callback,
8252                              user_data);
8253 }
8254 
8255 /**
8256  * g_file_stop_mountable_finish:
8257  * @file: input #GFile
8258  * @result: a #GAsyncResult
8259  * @error: a #GError, or %NULL
8260  *
8261  * Finishes a stop operation, see g_file_stop_mountable() for details.
8262  *
8263  * Finish an asynchronous stop operation that was started
8264  * with g_file_stop_mountable().
8265  *
8266  * Returns: %TRUE if the operation finished successfully.
8267  *     %FALSE otherwise.
8268  *
8269  * Since: 2.22
8270  */
8271 gboolean
g_file_stop_mountable_finish(GFile * file,GAsyncResult * result,GError ** error)8272 g_file_stop_mountable_finish (GFile         *file,
8273                               GAsyncResult  *result,
8274                               GError       **error)
8275 {
8276   GFileIface *iface;
8277 
8278   g_return_val_if_fail (G_IS_FILE (file), FALSE);
8279   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
8280 
8281   if (g_async_result_legacy_propagate_error (result, error))
8282     return FALSE;
8283   else if (g_async_result_is_tagged (result, g_file_stop_mountable))
8284     return g_task_propagate_boolean (G_TASK (result), error);
8285 
8286   iface = G_FILE_GET_IFACE (file);
8287   return (* iface->stop_mountable_finish) (file, result, error);
8288 }
8289 
8290 /**
8291  * g_file_poll_mountable:
8292  * @file: input #GFile
8293  * @cancellable: optional #GCancellable object, %NULL to ignore
8294  * @callback: (nullable): a #GAsyncReadyCallback to call
8295  *     when the request is satisfied, or %NULL
8296  * @user_data: the data to pass to callback function
8297  *
8298  * Polls a file of type #G_FILE_TYPE_MOUNTABLE.
8299  *
8300  * If @cancellable is not %NULL, then the operation can be cancelled by
8301  * triggering the cancellable object from another thread. If the operation
8302  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
8303  *
8304  * When the operation is finished, @callback will be called.
8305  * You can then call g_file_mount_mountable_finish() to get
8306  * the result of the operation.
8307  *
8308  * Since: 2.22
8309  */
8310 void
g_file_poll_mountable(GFile * file,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)8311 g_file_poll_mountable (GFile               *file,
8312                        GCancellable        *cancellable,
8313                        GAsyncReadyCallback  callback,
8314                        gpointer             user_data)
8315 {
8316   GFileIface *iface;
8317 
8318   g_return_if_fail (G_IS_FILE (file));
8319 
8320   iface = G_FILE_GET_IFACE (file);
8321 
8322   if (iface->poll_mountable == NULL)
8323     {
8324       g_task_report_new_error (file, callback, user_data,
8325                                g_file_poll_mountable,
8326                                G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
8327                                _("Operation not supported"));
8328       return;
8329     }
8330 
8331   (* iface->poll_mountable) (file,
8332                              cancellable,
8333                              callback,
8334                              user_data);
8335 }
8336 
8337 /**
8338  * g_file_poll_mountable_finish:
8339  * @file: input #GFile
8340  * @result: a #GAsyncResult
8341  * @error: a #GError, or %NULL
8342  *
8343  * Finishes a poll operation. See g_file_poll_mountable() for details.
8344  *
8345  * Finish an asynchronous poll operation that was polled
8346  * with g_file_poll_mountable().
8347  *
8348  * Returns: %TRUE if the operation finished successfully. %FALSE
8349  * otherwise.
8350  *
8351  * Since: 2.22
8352  */
8353 gboolean
g_file_poll_mountable_finish(GFile * file,GAsyncResult * result,GError ** error)8354 g_file_poll_mountable_finish (GFile         *file,
8355                               GAsyncResult  *result,
8356                               GError       **error)
8357 {
8358   GFileIface *iface;
8359 
8360   g_return_val_if_fail (G_IS_FILE (file), FALSE);
8361   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
8362 
8363   if (g_async_result_legacy_propagate_error (result, error))
8364     return FALSE;
8365   else if (g_async_result_is_tagged (result, g_file_poll_mountable))
8366     return g_task_propagate_boolean (G_TASK (result), error);
8367 
8368   iface = G_FILE_GET_IFACE (file);
8369   return (* iface->poll_mountable_finish) (file, result, error);
8370 }
8371 
8372 /**
8373  * g_file_supports_thread_contexts:
8374  * @file: a #GFile
8375  *
8376  * Checks if @file supports
8377  * [thread-default contexts][g-main-context-push-thread-default-context].
8378  * If this returns %FALSE, you cannot perform asynchronous operations on
8379  * @file in a thread that has a thread-default context.
8380  *
8381  * Returns: Whether or not @file supports thread-default contexts.
8382  *
8383  * Since: 2.22
8384  */
8385 gboolean
g_file_supports_thread_contexts(GFile * file)8386 g_file_supports_thread_contexts (GFile *file)
8387 {
8388  GFileIface *iface;
8389 
8390  g_return_val_if_fail (G_IS_FILE (file), FALSE);
8391 
8392  iface = G_FILE_GET_IFACE (file);
8393  return iface->supports_thread_contexts;
8394 }
8395 
8396 /**
8397  * g_file_load_bytes:
8398  * @file: a #GFile
8399  * @cancellable: (nullable): a #GCancellable or %NULL
8400  * @etag_out: (out) (nullable) (optional): a location to place the current
8401  *     entity tag for the file, or %NULL if the entity tag is not needed
8402  * @error: a location for a #GError or %NULL
8403  *
8404  * Loads the contents of @file and returns it as #GBytes.
8405  *
8406  * If @file is a resource:// based URI, the resulting bytes will reference the
8407  * embedded resource instead of a copy. Otherwise, this is equivalent to calling
8408  * g_file_load_contents() and g_bytes_new_take().
8409  *
8410  * For resources, @etag_out will be set to %NULL.
8411  *
8412  * The data contained in the resulting #GBytes is always zero-terminated, but
8413  * this is not included in the #GBytes length. The resulting #GBytes should be
8414  * freed with g_bytes_unref() when no longer in use.
8415  *
8416  * Returns: (transfer full): a #GBytes or %NULL and @error is set
8417  *
8418  * Since: 2.56
8419  */
8420 GBytes *
g_file_load_bytes(GFile * file,GCancellable * cancellable,gchar ** etag_out,GError ** error)8421 g_file_load_bytes (GFile         *file,
8422                    GCancellable  *cancellable,
8423                    gchar        **etag_out,
8424                    GError       **error)
8425 {
8426   gchar *contents;
8427   gsize len;
8428 
8429   g_return_val_if_fail (G_IS_FILE (file), NULL);
8430   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
8431   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
8432 
8433   if (etag_out != NULL)
8434     *etag_out = NULL;
8435 
8436   if (g_file_has_uri_scheme (file, "resource"))
8437     {
8438       GBytes *bytes;
8439       gchar *uri, *unescaped;
8440 
8441       uri = g_file_get_uri (file);
8442       unescaped = g_uri_unescape_string (uri + strlen ("resource://"), NULL);
8443       g_free (uri);
8444 
8445       bytes = g_resources_lookup_data (unescaped, G_RESOURCE_LOOKUP_FLAGS_NONE, error);
8446       g_free (unescaped);
8447 
8448       return bytes;
8449     }
8450 
8451   /* contents is guaranteed to be \0 terminated */
8452   if (g_file_load_contents (file, cancellable, &contents, &len, etag_out, error))
8453     return g_bytes_new_take (g_steal_pointer (&contents), len);
8454 
8455   return NULL;
8456 }
8457 
8458 static void
g_file_load_bytes_cb(GObject * object,GAsyncResult * result,gpointer user_data)8459 g_file_load_bytes_cb (GObject      *object,
8460                       GAsyncResult *result,
8461                       gpointer      user_data)
8462 {
8463   GFile *file = G_FILE (object);
8464   GTask *task = user_data;
8465   GError *error = NULL;
8466   gchar *etag = NULL;
8467   gchar *contents = NULL;
8468   gsize len = 0;
8469 
8470   g_file_load_contents_finish (file, result, &contents, &len, &etag, &error);
8471   g_task_set_task_data (task, g_steal_pointer (&etag), g_free);
8472 
8473   if (error != NULL)
8474     g_task_return_error (task, g_steal_pointer (&error));
8475   else
8476     g_task_return_pointer (task,
8477                            g_bytes_new_take (g_steal_pointer (&contents), len),
8478                            (GDestroyNotify)g_bytes_unref);
8479 
8480   g_object_unref (task);
8481 }
8482 
8483 /**
8484  * g_file_load_bytes_async:
8485  * @file: a #GFile
8486  * @cancellable: (nullable): a #GCancellable or %NULL
8487  * @callback: (scope async): a #GAsyncReadyCallback to call when the
8488  *     request is satisfied
8489  * @user_data: (closure): the data to pass to callback function
8490  *
8491  * Asynchronously loads the contents of @file as #GBytes.
8492  *
8493  * If @file is a resource:// based URI, the resulting bytes will reference the
8494  * embedded resource instead of a copy. Otherwise, this is equivalent to calling
8495  * g_file_load_contents_async() and g_bytes_new_take().
8496  *
8497  * @callback should call g_file_load_bytes_finish() to get the result of this
8498  * asynchronous operation.
8499  *
8500  * See g_file_load_bytes() for more information.
8501  *
8502  * Since: 2.56
8503  */
8504 void
g_file_load_bytes_async(GFile * file,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)8505 g_file_load_bytes_async (GFile               *file,
8506                          GCancellable        *cancellable,
8507                          GAsyncReadyCallback  callback,
8508                          gpointer             user_data)
8509 {
8510   GError *error = NULL;
8511   GBytes *bytes;
8512   GTask *task;
8513 
8514   g_return_if_fail (G_IS_FILE (file));
8515   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
8516 
8517   task = g_task_new (file, cancellable, callback, user_data);
8518   g_task_set_source_tag (task, g_file_load_bytes_async);
8519 
8520   if (!g_file_has_uri_scheme (file, "resource"))
8521     {
8522       g_file_load_contents_async (file,
8523                                   cancellable,
8524                                   g_file_load_bytes_cb,
8525                                   g_steal_pointer (&task));
8526       return;
8527     }
8528 
8529   bytes = g_file_load_bytes (file, cancellable, NULL, &error);
8530 
8531   if (bytes == NULL)
8532     g_task_return_error (task, g_steal_pointer (&error));
8533   else
8534     g_task_return_pointer (task,
8535                            g_steal_pointer (&bytes),
8536                            (GDestroyNotify)g_bytes_unref);
8537 
8538   g_object_unref (task);
8539 }
8540 
8541 /**
8542  * g_file_load_bytes_finish:
8543  * @file: a #GFile
8544  * @result: a #GAsyncResult provided to the callback
8545  * @etag_out: (out) (nullable) (optional): a location to place the current
8546  *     entity tag for the file, or %NULL if the entity tag is not needed
8547  * @error: a location for a #GError, or %NULL
8548  *
8549  * Completes an asynchronous request to g_file_load_bytes_async().
8550  *
8551  * For resources, @etag_out will be set to %NULL.
8552  *
8553  * The data contained in the resulting #GBytes is always zero-terminated, but
8554  * this is not included in the #GBytes length. The resulting #GBytes should be
8555  * freed with g_bytes_unref() when no longer in use.
8556  *
8557  * See g_file_load_bytes() for more information.
8558  *
8559  * Returns: (transfer full): a #GBytes or %NULL and @error is set
8560  *
8561  * Since: 2.56
8562  */
8563 GBytes *
g_file_load_bytes_finish(GFile * file,GAsyncResult * result,gchar ** etag_out,GError ** error)8564 g_file_load_bytes_finish (GFile         *file,
8565                           GAsyncResult  *result,
8566                           gchar        **etag_out,
8567                           GError       **error)
8568 {
8569   GBytes *bytes;
8570 
8571   g_return_val_if_fail (G_IS_FILE (file), NULL);
8572   g_return_val_if_fail (G_IS_TASK (result), NULL);
8573   g_return_val_if_fail (g_task_is_valid (G_TASK (result), file), NULL);
8574   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
8575 
8576   bytes = g_task_propagate_pointer (G_TASK (result), error);
8577 
8578   if (etag_out != NULL)
8579     *etag_out = g_strdup (g_task_get_task_data (G_TASK (result)));
8580 
8581   return bytes;
8582 }
8583