Bug Summary

File:ctk/ctkfilesystem.c
Warning:line 624, column 12
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctkfilesystem.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/ctk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-172934-43638-1 -x c ctkfilesystem.c
1/* CTK - The GIMP Toolkit
2 * ctkfilesystem.c: Filesystem abstraction functions.
3 * Copyright (C) 2003, Red Hat, Inc.
4 * Copyright (C) 2007-2008 Carlos Garnacho
5 *
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Authors: Carlos Garnacho <carlos@imendio.com>
20 */
21
22#include "config.h"
23
24#include "ctkfilesystem.h"
25
26#include <string.h>
27#include <glib/gi18n-lib.h>
28
29#include "ctkfilechooser.h"
30#include "ctkcssiconthemevalueprivate.h"
31#include "ctkintl.h"
32#include "ctkprivate.h"
33#include "ctkstylecontextprivate.h"
34
35/* #define DEBUG_MODE */
36#ifdef DEBUG_MODE
37#define DEBUG(x) g_debug (x);
38#else
39#define DEBUG(x)
40#endif
41
42#define FILES_PER_QUERY100 100
43
44/* The pointers we return for a CtkFileSystemVolume are opaque tokens; they are
45 * really pointers to GDrive, GVolume or GMount objects. We need an extra
46 * token for the fake “File System” volume. So, we’ll return a pointer to
47 * this particular string.
48 */
49static const gchar *root_volume_token = N_("File System")("File System");
50#define IS_ROOT_VOLUME(volume)((gpointer) (volume) == (gpointer) root_volume_token) ((gpointer) (volume) == (gpointer) root_volume_token)
51
52enum {
53 PROP_0,
54 PROP_FILE,
55 PROP_ENUMERATOR,
56 PROP_ATTRIBUTES
57};
58
59enum {
60 VOLUMES_CHANGED,
61 FS_LAST_SIGNAL
62};
63
64enum {
65 FILES_ADDED,
66 FILES_REMOVED,
67 FILES_CHANGED,
68 FINISHED_LOADING,
69 DELETED,
70 FOLDER_LAST_SIGNAL
71};
72
73static guint fs_signals [FS_LAST_SIGNAL] = { 0, };
74
75typedef struct AsyncFuncData AsyncFuncData;
76
77struct CtkFileSystemPrivate
78{
79 GVolumeMonitor *volume_monitor;
80
81 /* This list contains elements that can be
82 * of type GDrive, GVolume and GMount
83 */
84 GSList *volumes;
85};
86
87struct AsyncFuncData
88{
89 CtkFileSystem *file_system;
90 GFile *file;
91 GCancellable *cancellable;
92
93 gpointer callback;
94 gpointer data;
95};
96
97G_DEFINE_TYPE_WITH_PRIVATE (CtkFileSystem, _ctk_file_system, G_TYPE_OBJECT)static void _ctk_file_system_init (CtkFileSystem *self); static
void _ctk_file_system_class_init (CtkFileSystemClass *klass)
; static GType _ctk_file_system_get_type_once (void); static gpointer
_ctk_file_system_parent_class = ((void*)0); static gint CtkFileSystem_private_offset
; static void _ctk_file_system_class_intern_init (gpointer klass
) { _ctk_file_system_parent_class = g_type_class_peek_parent (
klass); if (CtkFileSystem_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkFileSystem_private_offset); _ctk_file_system_class_init
((CtkFileSystemClass*) klass); } __attribute__ ((__unused__)
) static inline gpointer _ctk_file_system_get_instance_private
(CtkFileSystem *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkFileSystem_private_offset)))); } GType _ctk_file_system_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= _ctk_file_system_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType _ctk_file_system_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkFileSystem"
), sizeof (CtkFileSystemClass), (GClassInitFunc)(void (*)(void
)) _ctk_file_system_class_intern_init, sizeof (CtkFileSystem)
, (GInstanceInitFunc)(void (*)(void)) _ctk_file_system_init, (
GTypeFlags) 0); { {{ CtkFileSystem_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkFileSystemPrivate)); };} } return
g_define_type_id; }
98
99
100/* CtkFileSystem methods */
101static void
102volumes_changed (GVolumeMonitor *volume_monitor G_GNUC_UNUSED__attribute__ ((__unused__)),
103 gpointer volume,
104 gpointer user_data)
105{
106 CtkFileSystem *file_system;
107
108 cdk_threads_enter ();
109
110 file_system = CTK_FILE_SYSTEM (user_data)((((CtkFileSystem*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((_ctk_file_system_get_type ()))))))
;
111 g_signal_emit (file_system, fs_signals[VOLUMES_CHANGED], 0, volume);
112 cdk_threads_leave ();
113}
114
115static void
116ctk_file_system_dispose (GObject *object)
117{
118 CtkFileSystem *file_system = CTK_FILE_SYSTEM (object)((((CtkFileSystem*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((_ctk_file_system_get_type ()))))))
;
119 CtkFileSystemPrivate *priv = file_system->priv;
120
121 DEBUG ("dispose");
122
123 if (priv->volumes)
124 {
125 g_slist_free_full (priv->volumes, g_object_unref);
126 priv->volumes = NULL((void*)0);
127 }
128
129 if (priv->volume_monitor)
130 {
131 g_signal_handlers_disconnect_by_func (priv->volume_monitor, volumes_changed, object)g_signal_handlers_disconnect_matched ((priv->volume_monitor
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (volumes_changed), (object))
;
132 g_object_unref (priv->volume_monitor);
133 priv->volume_monitor = NULL((void*)0);
134 }
135
136 G_OBJECT_CLASS (_ctk_file_system_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((_ctk_file_system_parent_class)), (((GType) ((20) <<
(2))))))))
->dispose (object);
137}
138
139static void
140_ctk_file_system_class_init (CtkFileSystemClass *class)
141{
142 GObjectClass *object_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
;
143
144 object_class->dispose = ctk_file_system_dispose;
145
146 fs_signals[VOLUMES_CHANGED] =
147 g_signal_new (I_("volumes-changed")g_intern_static_string ("volumes-changed"),
148 G_TYPE_FROM_CLASS (object_class)(((GTypeClass*) (object_class))->g_type),
149 G_SIGNAL_RUN_LAST,
150 G_STRUCT_OFFSET (CtkFileSystemClass, volumes_changed)((glong) __builtin_offsetof(CtkFileSystemClass, volumes_changed
))
,
151 NULL((void*)0), NULL((void*)0),
152 NULL((void*)0),
153 G_TYPE_NONE((GType) ((1) << (2))), 0);
154}
155
156static gboolean
157mount_referenced_by_volume_activation_root (GList *volumes, GMount *mount)
158{
159 GList *l;
160 GFile *mount_root;
161 gboolean ret;
162
163 ret = FALSE(0);
164
165 mount_root = g_mount_get_root (mount);
166
167 for (l = volumes; l != NULL((void*)0); l = l->next)
168 {
169 GVolume *volume = G_VOLUME (l->data)((((GVolume*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((g_volume_get_type ()))))))
;
170 GFile *volume_activation_root;
171
172 volume_activation_root = g_volume_get_activation_root (volume);
173 if (volume_activation_root != NULL((void*)0))
174 {
175 if (g_file_has_prefix (volume_activation_root, mount_root))
176 {
177 ret = TRUE(!(0));
178 g_object_unref (volume_activation_root);
179 break;
180 }
181 g_object_unref (volume_activation_root);
182 }
183 }
184
185 g_object_unref (mount_root);
186 return ret;
187}
188
189static void
190get_volumes_list (CtkFileSystem *file_system)
191{
192 CtkFileSystemPrivate *priv = file_system->priv;
193 GList *l, *ll;
194 GList *drives;
195 GList *volumes;
196 GList *mounts;
197 GDrive *drive;
198 GVolume *volume;
199 GMount *mount;
200
201 if (priv->volumes)
202 {
203 g_slist_free_full (priv->volumes, g_object_unref);
204 priv->volumes = NULL((void*)0);
205 }
206
207 /* first go through all connected drives */
208 drives = g_volume_monitor_get_connected_drives (priv->volume_monitor);
209
210 for (l = drives; l != NULL((void*)0); l = l->next)
211 {
212 drive = l->data;
213 volumes = g_drive_get_volumes (drive);
214
215 if (volumes)
216 {
217 for (ll = volumes; ll != NULL((void*)0); ll = ll->next)
218 {
219 volume = ll->data;
220 mount = g_volume_get_mount (volume);
221
222 if (mount)
223 {
224 /* Show mounted volume */
225 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount)((__typeof__ (mount)) (g_object_ref) (mount)));
226 g_object_unref (mount);
227 }
228 else
229 {
230 /* Do show the unmounted volumes in the sidebar;
231 * this is so the user can mount it (in case automounting
232 * is off).
233 *
234 * Also, even if automounting is enabled, this gives a visual
235 * cue that the user should remember to yank out the media if
236 * he just unmounted it.
237 */
238 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume)((__typeof__ (volume)) (g_object_ref) (volume)));
239 }
240
241 g_object_unref (volume);
242 }
243
244 g_list_free (volumes);
245 }
246 else if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive))
247 {
248 /* If the drive has no mountable volumes and we cannot detect media change.. we
249 * display the drive in the sidebar so the user can manually poll the drive by
250 * right clicking and selecting "Rescan..."
251 *
252 * This is mainly for drives like floppies where media detection doesn't
253 * work.. but it's also for human beings who like to turn off media detection
254 * in the OS to save battery juice.
255 */
256
257 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (drive)((__typeof__ (drive)) (g_object_ref) (drive)));
258 }
259
260 g_object_unref (drive);
261 }
262
263 g_list_free (drives);
264
265 /* add all volumes that is not associated with a drive */
266 volumes = g_volume_monitor_get_volumes (priv->volume_monitor);
267
268 for (l = volumes; l != NULL((void*)0); l = l->next)
269 {
270 volume = l->data;
271 drive = g_volume_get_drive (volume);
272
273 if (drive)
274 {
275 g_object_unref (drive);
276 continue;
277 }
278
279 mount = g_volume_get_mount (volume);
280
281 if (mount)
282 {
283 /* show this mount */
284 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount)((__typeof__ (mount)) (g_object_ref) (mount)));
285 g_object_unref (mount);
286 }
287 else
288 {
289 /* see comment above in why we add an icon for a volume */
290 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume)((__typeof__ (volume)) (g_object_ref) (volume)));
291 }
292
293 g_object_unref (volume);
294 }
295
296 /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
297 mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
298
299 for (l = mounts; l != NULL((void*)0); l = l->next)
300 {
301 mount = l->data;
302 volume = g_mount_get_volume (mount);
303
304 if (volume)
305 {
306 g_object_unref (volume);
307 continue;
308 }
309
310 /* if there's exists one or more volumes with an activation root inside the mount,
311 * don't display the mount
312 */
313 if (mount_referenced_by_volume_activation_root (volumes, mount))
314 {
315 g_object_unref (mount);
316 continue;
317 }
318
319 /* show this mount */
320 priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount)((__typeof__ (mount)) (g_object_ref) (mount)));
321 g_object_unref (mount);
322 }
323
324 g_list_free (volumes);
325
326 g_list_free (mounts);
327}
328
329static void
330_ctk_file_system_init (CtkFileSystem *file_system)
331{
332 CtkFileSystemPrivate *priv;
333
334 DEBUG ("init");
335
336 file_system->priv = priv = _ctk_file_system_get_instance_private (file_system);
337
338 /* Volumes */
339 priv->volume_monitor = g_volume_monitor_get ();
340
341 g_signal_connect (priv->volume_monitor, "mount-added",g_signal_connect_data ((priv->volume_monitor), ("mount-added"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
342 G_CALLBACK (volumes_changed), file_system)g_signal_connect_data ((priv->volume_monitor), ("mount-added"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
;
343 g_signal_connect (priv->volume_monitor, "mount-removed",g_signal_connect_data ((priv->volume_monitor), ("mount-removed"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
344 G_CALLBACK (volumes_changed), file_system)g_signal_connect_data ((priv->volume_monitor), ("mount-removed"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
;
345 g_signal_connect (priv->volume_monitor, "mount-changed",g_signal_connect_data ((priv->volume_monitor), ("mount-changed"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
346 G_CALLBACK (volumes_changed), file_system)g_signal_connect_data ((priv->volume_monitor), ("mount-changed"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
;
347 g_signal_connect (priv->volume_monitor, "volume-added",g_signal_connect_data ((priv->volume_monitor), ("volume-added"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
348 G_CALLBACK (volumes_changed), file_system)g_signal_connect_data ((priv->volume_monitor), ("volume-added"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
;
349 g_signal_connect (priv->volume_monitor, "volume-removed",g_signal_connect_data ((priv->volume_monitor), ("volume-removed"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
350 G_CALLBACK (volumes_changed), file_system)g_signal_connect_data ((priv->volume_monitor), ("volume-removed"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
;
351 g_signal_connect (priv->volume_monitor, "volume-changed",g_signal_connect_data ((priv->volume_monitor), ("volume-changed"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
352 G_CALLBACK (volumes_changed), file_system)g_signal_connect_data ((priv->volume_monitor), ("volume-changed"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
;
353 g_signal_connect (priv->volume_monitor, "drive-connected",g_signal_connect_data ((priv->volume_monitor), ("drive-connected"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
354 G_CALLBACK (volumes_changed), file_system)g_signal_connect_data ((priv->volume_monitor), ("drive-connected"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
;
355 g_signal_connect (priv->volume_monitor, "drive-disconnected",g_signal_connect_data ((priv->volume_monitor), ("drive-disconnected"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
356 G_CALLBACK (volumes_changed), file_system)g_signal_connect_data ((priv->volume_monitor), ("drive-disconnected"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
;
357 g_signal_connect (priv->volume_monitor, "drive-changed",g_signal_connect_data ((priv->volume_monitor), ("drive-changed"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
358 G_CALLBACK (volumes_changed), file_system)g_signal_connect_data ((priv->volume_monitor), ("drive-changed"
), (((GCallback) (volumes_changed))), (file_system), ((void*)
0), (GConnectFlags) 0)
;
359}
360
361/* CtkFileSystem public methods */
362CtkFileSystem *
363_ctk_file_system_new (void)
364{
365 return g_object_new (CTK_TYPE_FILE_SYSTEM(_ctk_file_system_get_type ()), NULL((void*)0));
366}
367
368GSList *
369_ctk_file_system_list_volumes (CtkFileSystem *file_system)
370{
371 CtkFileSystemPrivate *priv = file_system->priv;
372 GSList *list;
373
374 DEBUG ("list_volumes");
375
376 get_volumes_list (file_system);
377
378 list = g_slist_copy (priv->volumes);
379
380#ifndef G_OS_WIN32
381 /* Prepend root volume */
382 list = g_slist_prepend (list, (gpointer) root_volume_token);
383#endif
384
385 return list;
386}
387
388static void
389free_async_data (AsyncFuncData *async_data)
390{
391 g_object_unref (async_data->file_system);
392 g_object_unref (async_data->file);
393 g_object_unref (async_data->cancellable);
394
395 g_free (async_data);
396}
397
398static void
399query_info_callback (GObject *source_object,
400 GAsyncResult *result,
401 gpointer user_data)
402{
403 AsyncFuncData *async_data;
404 GError *error = NULL((void*)0);
405 GFileInfo *file_info;
406 GFile *file;
407
408 DEBUG ("query_info_callback");
409
410 file = G_FILE (source_object)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_file_get_type ()))))))
;
411 async_data = (AsyncFuncData *) user_data;
412 file_info = g_file_query_info_finish (file, result, &error);
413
414 if (async_data->callback)
415 {
416 cdk_threads_enter ();
417 ((CtkFileSystemGetInfoCallback) async_data->callback) (async_data->cancellable,
418 file_info, error, async_data->data);
419 cdk_threads_leave ();
420 }
421
422 if (file_info)
423 g_object_unref (file_info);
424
425 if (error)
426 g_error_free (error);
427
428 free_async_data (async_data);
429}
430
431GCancellable *
432_ctk_file_system_get_info (CtkFileSystem *file_system,
433 GFile *file,
434 const gchar *attributes,
435 CtkFileSystemGetInfoCallback callback,
436 gpointer data)
437{
438 GCancellable *cancellable;
439 AsyncFuncData *async_data;
440
441 g_return_val_if_fail (CTK_IS_FILE_SYSTEM (file_system), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file_system)); GType __t = ((_ctk_file_system_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM (file_system)"); return
(((void*)0)); } } while (0)
;
442 g_return_val_if_fail (G_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = ((g_file_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "G_IS_FILE (file)"); return (((void*)0)); } } while (0)
;
443
444 cancellable = g_cancellable_new ();
445
446 async_data = g_new0 (AsyncFuncData, 1)((AsyncFuncData *) g_malloc0_n ((1), sizeof (AsyncFuncData)));
447 async_data->file_system = g_object_ref (file_system)((__typeof__ (file_system)) (g_object_ref) (file_system));
448 async_data->file = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
449 async_data->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
450
451 async_data->callback = callback;
452 async_data->data = data;
453
454 g_file_query_info_async (file,
455 attributes,
456 G_FILE_QUERY_INFO_NONE,
457 G_PRIORITY_DEFAULT0,
458 cancellable,
459 query_info_callback,
460 async_data);
461
462 return cancellable;
463}
464
465static void
466drive_poll_for_media_cb (GObject *source_object,
467 GAsyncResult *result,
468 gpointer user_data)
469{
470 AsyncFuncData *async_data;
471 GError *error = NULL((void*)0);
472
473 g_drive_poll_for_media_finish (G_DRIVE (source_object)((((GDrive*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_drive_get_type ()))))))
, result, &error);
474 async_data = (AsyncFuncData *) user_data;
475
476 cdk_threads_enter ();
477 ((CtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
478 (CtkFileSystemVolume *) source_object,
479 error, async_data->data);
480 cdk_threads_leave ();
481
482 if (error)
483 g_error_free (error);
484}
485
486static void
487volume_mount_cb (GObject *source_object,
488 GAsyncResult *result,
489 gpointer user_data)
490{
491 AsyncFuncData *async_data;
492 GError *error = NULL((void*)0);
493
494 g_volume_mount_finish (G_VOLUME (source_object)((((GVolume*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_volume_get_type ()))))))
, result, &error);
495 async_data = (AsyncFuncData *) user_data;
496
497 cdk_threads_enter ();
498 ((CtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
499 (CtkFileSystemVolume *) source_object,
500 error, async_data->data);
501 cdk_threads_leave ();
502
503 if (error)
504 g_error_free (error);
505}
506
507GCancellable *
508_ctk_file_system_mount_volume (CtkFileSystem *file_system,
509 CtkFileSystemVolume *volume,
510 GMountOperation *mount_operation,
511 CtkFileSystemVolumeMountCallback callback,
512 gpointer data)
513{
514 GCancellable *cancellable;
515 AsyncFuncData *async_data;
516 gboolean handled = FALSE(0);
517
518 DEBUG ("volume_mount");
519
520 cancellable = g_cancellable_new ();
521
522 async_data = g_new0 (AsyncFuncData, 1)((AsyncFuncData *) g_malloc0_n ((1), sizeof (AsyncFuncData)));
523 async_data->file_system = g_object_ref (file_system)((__typeof__ (file_system)) (g_object_ref) (file_system));
524 async_data->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
525
526 async_data->callback = callback;
527 async_data->data = data;
528
529 if (G_IS_DRIVE (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_drive_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
530 {
531 /* this path happens for drives that are not polled by the OS and where the last media
532 * check indicated that no media was available. So the thing to do here is to
533 * invoke poll_for_media() on the drive
534 */
535 g_drive_poll_for_media (G_DRIVE (volume)((((GDrive*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_drive_get_type ()))))))
, cancellable, drive_poll_for_media_cb, async_data);
536 handled = TRUE(!(0));
537 }
538 else if (G_IS_VOLUME (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_volume_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
539 {
540 g_volume_mount (G_VOLUME (volume)((((GVolume*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_volume_get_type ()))))))
, G_MOUNT_MOUNT_NONE, mount_operation, cancellable, volume_mount_cb, async_data);
541 handled = TRUE(!(0));
542 }
543
544 if (!handled)
545 free_async_data (async_data);
546
547 return cancellable;
548}
549
550static void
551enclosing_volume_mount_cb (GObject *source_object,
552 GAsyncResult *result,
553 gpointer user_data)
554{
555 CtkFileSystemVolume *volume;
556 AsyncFuncData *async_data;
557 GError *error = NULL((void*)0);
558
559 async_data = (AsyncFuncData *) user_data;
560 g_file_mount_enclosing_volume_finish (G_FILE (source_object)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_file_get_type ()))))))
, result, &error);
561 volume = _ctk_file_system_get_volume_for_file (async_data->file_system, G_FILE (source_object)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_file_get_type ()))))))
);
562
563 /* Silently drop G_IO_ERROR_ALREADY_MOUNTED error for gvfs backends without visible mounts. */
564 /* Better than doing query_info with additional I/O every time. */
565 if (error && g_error_matches (error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_ALREADY_MOUNTED))
566 g_clear_error (&error);
567
568 cdk_threads_enter ();
569 ((CtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable, volume,
570 error, async_data->data);
571 cdk_threads_leave ();
572
573 if (error)
574 g_error_free (error);
575
576 _ctk_file_system_volume_unref (volume);
577}
578
579GCancellable *
580_ctk_file_system_mount_enclosing_volume (CtkFileSystem *file_system,
581 GFile *file,
582 GMountOperation *mount_operation,
583 CtkFileSystemVolumeMountCallback callback,
584 gpointer data)
585{
586 GCancellable *cancellable;
587 AsyncFuncData *async_data;
588
589 g_return_val_if_fail (CTK_IS_FILE_SYSTEM (file_system), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file_system)); GType __t = ((_ctk_file_system_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM (file_system)"); return
(((void*)0)); } } while (0)
;
590 g_return_val_if_fail (G_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = ((g_file_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "G_IS_FILE (file)"); return (((void*)0)); } } while (0)
;
591
592 DEBUG ("mount_enclosing_volume");
593
594 cancellable = g_cancellable_new ();
595
596 async_data = g_new0 (AsyncFuncData, 1)((AsyncFuncData *) g_malloc0_n ((1), sizeof (AsyncFuncData)));
597 async_data->file_system = g_object_ref (file_system)((__typeof__ (file_system)) (g_object_ref) (file_system));
598 async_data->file = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
599 async_data->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
600
601 async_data->callback = callback;
602 async_data->data = data;
603
604 g_file_mount_enclosing_volume (file,
605 G_MOUNT_MOUNT_NONE,
606 mount_operation,
607 cancellable,
608 enclosing_volume_mount_cb,
609 async_data);
610 return cancellable;
611}
612
613CtkFileSystemVolume *
614_ctk_file_system_get_volume_for_file (CtkFileSystem *file_system G_GNUC_UNUSED__attribute__ ((__unused__)),
615 GFile *file)
616{
617 GMount *mount;
618
619 DEBUG ("get_volume_for_file");
620
621 mount = g_file_find_enclosing_mount (file, NULL((void*)0), NULL((void*)0));
622
623 if (!mount && g_file_is_native (file))
624 return (CtkFileSystemVolume *) root_volume_token;
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
625
626 return (CtkFileSystemVolume *) mount;
627}
628
629/* CtkFileSystemVolume public methods */
630gchar *
631_ctk_file_system_volume_get_display_name (CtkFileSystemVolume *volume)
632{
633 DEBUG ("volume_get_display_name");
634
635 if (IS_ROOT_VOLUME (volume)((gpointer) (volume) == (gpointer) root_volume_token))
636 return g_strdup (_(root_volume_token))g_strdup_inline (((char *) g_dgettext ("ctk30", root_volume_token
)))
;
637 if (G_IS_DRIVE (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_drive_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
638 return g_drive_get_name (G_DRIVE (volume)((((GDrive*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_drive_get_type ()))))))
);
639 else if (G_IS_MOUNT (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_mount_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
640 return g_mount_get_name (G_MOUNT (volume)((((GMount*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_mount_get_type ()))))))
);
641 else if (G_IS_VOLUME (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_volume_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
642 return g_volume_get_name (G_VOLUME (volume)((((GVolume*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_volume_get_type ()))))))
);
643
644 return NULL((void*)0);
645}
646
647gboolean
648_ctk_file_system_volume_is_mounted (CtkFileSystemVolume *volume)
649{
650 gboolean mounted;
651
652 DEBUG ("volume_is_mounted");
653
654 if (IS_ROOT_VOLUME (volume)((gpointer) (volume) == (gpointer) root_volume_token))
655 return TRUE(!(0));
656
657 mounted = FALSE(0);
658
659 if (G_IS_MOUNT (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_mount_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
660 mounted = TRUE(!(0));
661 else if (G_IS_VOLUME (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_volume_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
662 {
663 GMount *mount;
664
665 mount = g_volume_get_mount (G_VOLUME (volume)((((GVolume*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_volume_get_type ()))))))
);
666
667 if (mount)
668 {
669 mounted = TRUE(!(0));
670 g_object_unref (mount);
671 }
672 }
673
674 return mounted;
675}
676
677GFile *
678_ctk_file_system_volume_get_root (CtkFileSystemVolume *volume)
679{
680 GFile *file = NULL((void*)0);
681
682 DEBUG ("volume_get_base");
683
684 if (IS_ROOT_VOLUME (volume)((gpointer) (volume) == (gpointer) root_volume_token))
685 return g_file_new_for_uri ("file:///");
686
687 if (G_IS_MOUNT (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_mount_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
688 file = g_mount_get_root (G_MOUNT (volume)((((GMount*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_mount_get_type ()))))))
);
689 else if (G_IS_VOLUME (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_volume_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
690 {
691 GMount *mount;
692
693 mount = g_volume_get_mount (G_VOLUME (volume)((((GVolume*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_volume_get_type ()))))))
);
694
695 if (mount)
696 {
697 file = g_mount_get_root (mount);
698 g_object_unref (mount);
699 }
700 }
701
702 return file;
703}
704
705static cairo_surface_t *
706get_surface_from_gicon (GIcon *icon,
707 CtkWidget *widget,
708 gint icon_size,
709 GError **error)
710{
711 CtkStyleContext *context;
712 CtkIconTheme *icon_theme;
713 CtkIconInfo *icon_info;
714 GdkPixbuf *pixbuf;
715 cairo_surface_t *surface;
716
717 context = ctk_widget_get_style_context (widget);
718 icon_theme = ctk_css_icon_theme_value_get_icon_theme
719 (_ctk_style_context_peek_property (context, CTK_CSS_PROPERTY_ICON_THEME));
720
721 icon_info = ctk_icon_theme_lookup_by_gicon_for_scale (icon_theme,
722 icon,
723 icon_size,
724 ctk_widget_get_scale_factor (widget),
725 CTK_ICON_LOOKUP_USE_BUILTIN);
726
727 if (!icon_info)
728 return NULL((void*)0);
729
730 pixbuf = ctk_icon_info_load_symbolic_for_context (icon_info,
731 context,
732 NULL((void*)0),
733 error);
734
735 g_object_unref (icon_info);
736
737 if (pixbuf == NULL((void*)0))
738 return NULL((void*)0);
739
740 surface = cdk_cairo_surface_create_from_pixbuf (pixbuf,
741 ctk_widget_get_scale_factor (widget),
742 ctk_widget_get_window (widget));
743 g_object_unref (pixbuf);
744
745 return surface;
746}
747
748cairo_surface_t *
749_ctk_file_system_volume_render_icon (CtkFileSystemVolume *volume,
750 CtkWidget *widget,
751 gint icon_size,
752 GError **error)
753{
754 GIcon *icon = NULL((void*)0);
755 cairo_surface_t *surface;
756
757 if (IS_ROOT_VOLUME (volume)((gpointer) (volume) == (gpointer) root_volume_token))
758 icon = g_themed_icon_new ("drive-harddisk");
759 else if (G_IS_DRIVE (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_drive_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
760 icon = g_drive_get_icon (G_DRIVE (volume)((((GDrive*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_drive_get_type ()))))))
);
761 else if (G_IS_VOLUME (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_volume_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
762 icon = g_volume_get_icon (G_VOLUME (volume)((((GVolume*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_volume_get_type ()))))))
);
763 else if (G_IS_MOUNT (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_mount_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
764 icon = g_mount_get_icon (G_MOUNT (volume)((((GMount*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_mount_get_type ()))))))
);
765
766 if (!icon)
767 return NULL((void*)0);
768
769 surface = get_surface_from_gicon (icon, widget, icon_size, error);
770
771 g_object_unref (icon);
772
773 return surface;
774}
775
776GIcon *
777_ctk_file_system_volume_get_symbolic_icon (CtkFileSystemVolume *volume)
778{
779 if (IS_ROOT_VOLUME (volume)((gpointer) (volume) == (gpointer) root_volume_token))
780 return g_themed_icon_new ("drive-harddisk-symbolic");
781 else if (G_IS_DRIVE (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_drive_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
782 return g_drive_get_symbolic_icon (G_DRIVE (volume)((((GDrive*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_drive_get_type ()))))))
);
783 else if (G_IS_VOLUME (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_volume_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
784 return g_volume_get_symbolic_icon (G_VOLUME (volume)((((GVolume*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_volume_get_type ()))))))
);
785 else if (G_IS_MOUNT (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_mount_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
786 return g_mount_get_symbolic_icon (G_MOUNT (volume)((((GMount*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((volume)), ((g_mount_get_type ()))))))
);
787 else
788 return NULL((void*)0);
789}
790
791CtkFileSystemVolume *
792_ctk_file_system_volume_ref (CtkFileSystemVolume *volume)
793{
794 if (IS_ROOT_VOLUME (volume)((gpointer) (volume) == (gpointer) root_volume_token))
795 return volume;
796
797 if (G_IS_MOUNT (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_mount_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
||
798 G_IS_VOLUME (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_volume_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
||
799 G_IS_DRIVE (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_drive_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
800 g_object_ref (volume)((__typeof__ (volume)) (g_object_ref) (volume));
801
802 return volume;
803}
804
805void
806_ctk_file_system_volume_unref (CtkFileSystemVolume *volume)
807{
808 /* Root volume doesn't need to be freed */
809 if (IS_ROOT_VOLUME (volume)((gpointer) (volume) == (gpointer) root_volume_token))
810 return;
811
812 if (G_IS_MOUNT (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_mount_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
||
813 G_IS_VOLUME (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_volume_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
||
814 G_IS_DRIVE (volume)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(volume)); GType __t = ((g_drive_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
815 g_object_unref (volume);
816}
817
818/* GFileInfo helper functions */
819static cairo_surface_t *
820_ctk_file_info_render_icon_internal (GFileInfo *info,
821 CtkWidget *widget,
822 gint icon_size,
823 gboolean symbolic)
824{
825 GIcon *icon;
826 GdkPixbuf *pixbuf;
827 const gchar *thumbnail_path;
828 cairo_surface_t *surface = NULL((void*)0);
829 int scale;
830
831 thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH"thumbnail::path");
832
833 if (thumbnail_path)
834 {
835 scale = ctk_widget_get_scale_factor (widget);
836 pixbuf = gdk_pixbuf_new_from_file_at_size (thumbnail_path,
837 icon_size*scale, icon_size*scale,
838 NULL((void*)0));
839
840 if (pixbuf != NULL((void*)0))
841 {
842 surface = cdk_cairo_surface_create_from_pixbuf (pixbuf, scale,
843 ctk_widget_get_window (widget));
844 g_object_unref (pixbuf);
845 }
846 }
847
848 if (!surface)
849 {
850 if (symbolic)
851 icon = g_file_info_get_symbolic_icon (info);
852 else
853 icon = g_file_info_get_icon (info);
854
855 if (icon)
856 surface = get_surface_from_gicon (icon, widget, icon_size, NULL((void*)0));
857
858 if (!surface)
859 {
860 /* Use general fallback for all files without icon */
861 if (symbolic)
862 icon = g_themed_icon_new ("text-x-generic-symbolic");
863 else
864 icon = g_themed_icon_new ("text-x-generic");
865 surface = get_surface_from_gicon (icon, widget, icon_size, NULL((void*)0));
866 g_object_unref (icon);
867 }
868 }
869
870 return surface;
871}
872
873cairo_surface_t *
874_ctk_file_info_render_icon (GFileInfo *info,
875 CtkWidget *widget,
876 gint icon_size)
877{
878 return _ctk_file_info_render_icon_internal (info, widget, icon_size, FALSE(0));
879}
880
881gboolean
882_ctk_file_info_consider_as_directory (GFileInfo *info)
883{
884 GFileType type = g_file_info_get_file_type (info);
885
886 return (type == G_FILE_TYPE_DIRECTORY ||
887 type == G_FILE_TYPE_MOUNTABLE ||
888 type == G_FILE_TYPE_SHORTCUT);
889}
890
891gboolean
892_ctk_file_has_native_path (GFile *file)
893{
894 char *local_file_path;
895 gboolean has_native_path;
896
897 /* Don't use g_file_is_native(), as we want to support FUSE paths if available */
898 local_file_path = g_file_get_path (file);
899 has_native_path = (local_file_path != NULL((void*)0));
900 g_free (local_file_path);
901
902 return has_native_path;
903}
904
905gboolean
906_ctk_file_consider_as_remote (GFile *file)
907{
908 GFileInfo *info;
909 gboolean is_remote;
910
911 info = g_file_query_filesystem_info (file, G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE"filesystem::remote", NULL((void*)0), NULL((void*)0));
912 if (info)
913 {
914 is_remote = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE"filesystem::remote");
915
916 g_object_unref (info);
917 }
918 else
919 is_remote = FALSE(0);
920
921 return is_remote;
922}