Bug Summary

File:libbaul-private/baul-file.c
Warning:line 1195, column 2
Value stored to 'ret' is never read

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 baul-file.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 -fdebug-compilation-dir=/rootdir/libbaul-private -fcoverage-compilation-dir=/rootdir/libbaul-private -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -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/cafe-desktop-2.0 -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -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/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -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/startup-notification-1.0 -I /usr/include/dconf -I /usr/include/cail-3.0 -I /usr/include/libxml2 -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/share" -D SYSCONFDIR="/usr/etc" -D BAUL_DATADIR="/usr/share/baul" -D BAUL_EXTENSIONDIR="/usr/lib/baul/extensions-2.0" -D PIC -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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.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/2025-10-09-074357-27286-1 -x c baul-file.c
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3 baul-file.c: Baul file model.
4
5 Copyright (C) 1999, 2000, 2001 Eazel, Inc.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program 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 General Public License for more details.
16
17 You should have received a copy of the GNU General Public
18 License along with this program; if not, write to the
19 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Author: Darin Adler <darin@bentspoon.com>
23*/
24
25#include <config.h>
26#include <grp.h>
27#include <ctk/ctk.h>
28#include <glib/gi18n.h>
29#include <glib/gstdio.h>
30#include <gio/gio.h>
31#include <glib.h>
32#include <libxml/parser.h>
33#include <pwd.h>
34#include <stdlib.h>
35#include <ctype.h>
36#include <sys/time.h>
37#include <time.h>
38#include <unistd.h>
39#include <sys/stat.h>
40
41#include <eel/eel-debug.h>
42#include <eel/eel-glib-extensions.h>
43#include <eel/eel-ctk-extensions.h>
44#include <eel/eel-vfs-extensions.h>
45#include <eel/eel-ctk-macros.h>
46#include <eel/eel-string.h>
47
48#include <libbaul-extension/baul-file-info.h>
49#include <libbaul-extension/baul-extension-private.h>
50#include <libbaul-private/baul-extensions.h>
51
52#include "baul-file.h"
53#include "baul-directory-notify.h"
54#include "baul-directory-private.h"
55#include "baul-signaller.h"
56#include "baul-desktop-directory.h"
57#include "baul-desktop-directory-file.h"
58#include "baul-desktop-icon-file.h"
59#include "baul-file-attributes.h"
60#include "baul-file-private.h"
61#include "baul-file-operations.h"
62#include "baul-file-utilities.h"
63#include "baul-global-preferences.h"
64#include "baul-lib-self-check-functions.h"
65#include "baul-link.h"
66#include "baul-metadata.h"
67#include "baul-module.h"
68#include "baul-search-directory.h"
69#include "baul-search-directory-file.h"
70#include "baul-thumbnails.h"
71#include "baul-ui-utilities.h"
72#include "baul-vfs-file.h"
73#include "baul-saved-search-file.h"
74
75#ifdef HAVE_SELINUX1
76#include <selinux/selinux.h>
77#endif
78
79/* Time in seconds to cache getpwuid results */
80#define GETPWUID_CACHE_TIME(5*60) (5*60)
81
82#define ICON_NAME_THUMBNAIL_LOADING"image-loading" "image-loading"
83
84#undef BAUL_FILE_DEBUG_REF
85#undef BAUL_FILE_DEBUG_REF_VALGRIND
86
87#ifdef BAUL_FILE_DEBUG_REF_VALGRIND
88#include <valgrind/valgrind.h>
89#define DEBUG_REF_PRINTFprintf VALGRIND_PRINTF_BACKTRACE
90#else
91#define DEBUG_REF_PRINTFprintf printf
92#endif
93
94/* Files that start with these characters sort after files that don't. */
95#define SORT_LAST_CHAR1'.' '.'
96#define SORT_LAST_CHAR2'#' '#'
97
98/* Name of Baul trash directories */
99#define TRASH_DIRECTORY_NAME".Trash" ".Trash"
100
101#define METADATA_ID_IS_LIST_MASK(1U<<31) (1U<<31)
102
103#define SORT_BY_EXTENSION_FOLLOWING_MAX_LENGTH3 3
104#define SORT_BY_EXTENSION_MAX_SEGMENTS3 3
105
106typedef enum {
107 SHOW_HIDDEN = 1 << 0,
108 SHOW_BACKUP = 1 << 1,
109} FilterOptions;
110
111typedef void (* ModifyListFunction) (GList **list, BaulFile *file);
112
113enum {
114 CHANGED,
115 UPDATED_DEEP_COUNT_IN_PROGRESS,
116 LAST_SIGNAL
117};
118
119static int date_format_pref;
120
121static guint signals[LAST_SIGNAL] = { 0 };
122
123static GHashTable *symbolic_links;
124
125static GQuark attribute_name_q,
126 attribute_size_q,
127 attribute_size_on_disk_q,
128 attribute_type_q,
129 attribute_modification_date_q,
130 attribute_date_modified_q,
131 attribute_accessed_date_q,
132 attribute_date_accessed_q,
133 attribute_emblems_q,
134 attribute_extension_q,
135 attribute_mime_type_q,
136 attribute_size_detail_q,
137 attribute_size_on_disk_detail_q,
138 attribute_deep_size_q,
139 attribute_deep_size_on_disk_q,
140 attribute_deep_file_count_q,
141 attribute_deep_directory_count_q,
142 attribute_deep_total_count_q,
143 attribute_date_changed_q,
144 attribute_trashed_on_q,
145 attribute_trash_orig_path_q,
146 attribute_date_permissions_q,
147 attribute_permissions_q,
148 attribute_selinux_context_q,
149 attribute_octal_permissions_q,
150 attribute_owner_q,
151 attribute_group_q,
152 attribute_uri_q,
153 attribute_where_q,
154 attribute_link_target_q,
155 attribute_volume_q,
156 attribute_free_space_q;
157
158static void baul_file_info_iface_init (BaulFileInfoIface *iface);
159static char * baul_file_get_owner_as_string (BaulFile *file,
160 gboolean include_real_name);
161static char * baul_file_get_type_as_string (BaulFile *file);
162static gboolean update_info_and_name (BaulFile *file,
163 GFileInfo *info);
164static const char * baul_file_peek_display_name (BaulFile *file);
165static const char * baul_file_peek_display_name_collation_key (BaulFile *file);
166static void file_mount_unmounted (GMount *mount, gpointer data);
167static void metadata_hash_free (GHashTable *hash);
168
169G_DEFINE_TYPE_WITH_CODE (BaulFile, baul_file, G_TYPE_OBJECT,static void baul_file_init (BaulFile *self); static void baul_file_class_init
(BaulFileClass *klass); static GType baul_file_get_type_once
(void); static gpointer baul_file_parent_class = ((void*)0);
static gint BaulFile_private_offset; static void baul_file_class_intern_init
(gpointer klass) { baul_file_parent_class = g_type_class_peek_parent
(klass); if (BaulFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &BaulFile_private_offset); baul_file_class_init (
(BaulFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer baul_file_get_instance_private (BaulFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (BaulFile_private_offset
)))); } GType baul_file_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
= baul_file_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 baul_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("BaulFile"), sizeof
(BaulFileClass), (GClassInitFunc)(void (*)(void)) baul_file_class_intern_init
, sizeof (BaulFile), (GInstanceInitFunc)(void (*)(void)) baul_file_init
, (GTypeFlags) 0); { {{ BaulFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (BaulFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) baul_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (baul_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
170 G_ADD_PRIVATE (BaulFile)static void baul_file_init (BaulFile *self); static void baul_file_class_init
(BaulFileClass *klass); static GType baul_file_get_type_once
(void); static gpointer baul_file_parent_class = ((void*)0);
static gint BaulFile_private_offset; static void baul_file_class_intern_init
(gpointer klass) { baul_file_parent_class = g_type_class_peek_parent
(klass); if (BaulFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &BaulFile_private_offset); baul_file_class_init (
(BaulFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer baul_file_get_instance_private (BaulFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (BaulFile_private_offset
)))); } GType baul_file_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
= baul_file_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 baul_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("BaulFile"), sizeof
(BaulFileClass), (GClassInitFunc)(void (*)(void)) baul_file_class_intern_init
, sizeof (BaulFile), (GInstanceInitFunc)(void (*)(void)) baul_file_init
, (GTypeFlags) 0); { {{ BaulFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (BaulFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) baul_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (baul_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
171 G_IMPLEMENT_INTERFACE (BAUL_TYPE_FILE_INFO,static void baul_file_init (BaulFile *self); static void baul_file_class_init
(BaulFileClass *klass); static GType baul_file_get_type_once
(void); static gpointer baul_file_parent_class = ((void*)0);
static gint BaulFile_private_offset; static void baul_file_class_intern_init
(gpointer klass) { baul_file_parent_class = g_type_class_peek_parent
(klass); if (BaulFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &BaulFile_private_offset); baul_file_class_init (
(BaulFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer baul_file_get_instance_private (BaulFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (BaulFile_private_offset
)))); } GType baul_file_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
= baul_file_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 baul_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("BaulFile"), sizeof
(BaulFileClass), (GClassInitFunc)(void (*)(void)) baul_file_class_intern_init
, sizeof (BaulFile), (GInstanceInitFunc)(void (*)(void)) baul_file_init
, (GTypeFlags) 0); { {{ BaulFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (BaulFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) baul_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (baul_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
172 baul_file_info_iface_init))static void baul_file_init (BaulFile *self); static void baul_file_class_init
(BaulFileClass *klass); static GType baul_file_get_type_once
(void); static gpointer baul_file_parent_class = ((void*)0);
static gint BaulFile_private_offset; static void baul_file_class_intern_init
(gpointer klass) { baul_file_parent_class = g_type_class_peek_parent
(klass); if (BaulFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &BaulFile_private_offset); baul_file_class_init (
(BaulFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer baul_file_get_instance_private (BaulFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (BaulFile_private_offset
)))); } GType baul_file_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
= baul_file_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 baul_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("BaulFile"), sizeof
(BaulFileClass), (GClassInitFunc)(void (*)(void)) baul_file_class_intern_init
, sizeof (BaulFile), (GInstanceInitFunc)(void (*)(void)) baul_file_init
, (GTypeFlags) 0); { {{ BaulFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (BaulFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) baul_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (baul_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
;
173
174static void
175baul_file_init (BaulFile *file)
176{
177 file->details = baul_file_get_instance_private (file);
178
179 baul_file_clear_info (file);
180 baul_file_invalidate_extension_info_internal (file);
181}
182
183static GObject*
184baul_file_constructor (GType type,
185 guint n_construct_properties,
186 GObjectConstructParam *construct_params)
187{
188 GObject *object;
189 BaulFile *file;
190
191 object = (* G_OBJECT_CLASS (baul_file_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((baul_file_parent_class)), (((GType) ((20) << (2)))
)))))
->constructor) (type,
192 n_construct_properties,
193 construct_params);
194
195 file = BAUL_FILE (object)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), (baul_file_get_type())))))
;
196
197 /* Set to default type after full construction */
198 if (BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type != G_FILE_TYPE_UNKNOWN) {
199 file->details->type = BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type;
200 }
201
202 return object;
203}
204
205gboolean
206baul_file_set_display_name (BaulFile *file,
207 const char *display_name,
208 const char *edit_name,
209 gboolean custom)
210{
211 gboolean changed;
212
213 if (custom && display_name == NULL((void*)0)) {
214 /* We're re-setting a custom display name, invalidate it if
215 we already set it so that the old one is re-read */
216 if (file->details->got_custom_display_name) {
217 file->details->got_custom_display_name = FALSE(0);
218 baul_file_invalidate_attributes (file,
219 BAUL_FILE_ATTRIBUTE_INFO);
220 }
221 return FALSE(0);
222 }
223
224 if (display_name == NULL((void*)0) || *display_name == 0) {
225 return FALSE(0);
226 }
227
228 if (!custom && file->details->got_custom_display_name) {
229 return FALSE(0);
230 }
231
232 if (edit_name == NULL((void*)0)) {
233 edit_name = display_name;
234 }
235
236 changed = FALSE(0);
237
238 if (eel_strcmp (file->details->display_name, display_name) != 0) {
239 changed = TRUE(!(0));
240
241 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
242
243 if (eel_strcmp (file->details->name, display_name) == 0) {
244 file->details->display_name = g_ref_string_acquire (file->details->name);
245 } else {
246 file->details->display_name = g_ref_string_new (display_name);
247 }
248
249 g_free (file->details->display_name_collation_key);
250 file->details->display_name_collation_key = g_utf8_collate_key_for_filename (display_name, -1);
251 }
252
253 if (eel_strcmp (file->details->edit_name, edit_name) != 0) {
254 changed = TRUE(!(0));
255
256 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
257 if (eel_strcmp (file->details->display_name, edit_name) == 0) {
258 file->details->edit_name = g_ref_string_acquire (file->details->display_name);
259 } else {
260 file->details->edit_name = g_ref_string_new (edit_name);
261 }
262 }
263
264 file->details->got_custom_display_name = custom;
265 return changed;
266}
267
268static void
269baul_file_clear_display_name (BaulFile *file)
270{
271 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
272 file->details->display_name = NULL((void*)0);
273 g_free (file->details->display_name_collation_key);
274 file->details->display_name_collation_key = NULL((void*)0);
275 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
276 file->details->edit_name = NULL((void*)0);
277}
278
279static gboolean
280foreach_metadata_free (gpointer key,
281 gpointer value,
282 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
283{
284 guint id;
285
286 id = GPOINTER_TO_UINT (key)((guint) (gulong) (key));
287
288 if (id & METADATA_ID_IS_LIST_MASK(1U<<31)) {
289 g_strfreev ((char **)value);
290 } else {
291 g_free ((char *)value);
292 }
293 return TRUE(!(0));
294}
295
296
297static void
298metadata_hash_free (GHashTable *hash)
299{
300 g_hash_table_foreach_remove (hash,
301 foreach_metadata_free,
302 NULL((void*)0));
303 g_hash_table_destroy (hash);
304}
305
306static gboolean
307metadata_hash_equal (GHashTable *hash1,
308 GHashTable *hash2)
309{
310 GHashTableIter iter;
311 gpointer key1, value1, value2;
312 guint id;
313
314 if (hash1 == NULL((void*)0) && hash2 == NULL((void*)0)) {
315 return TRUE(!(0));
316 }
317
318 if (hash1 == NULL((void*)0) || hash2 == NULL((void*)0)) {
319 return FALSE(0);
320 }
321
322 if (g_hash_table_size (hash1) !=
323 g_hash_table_size (hash2)) {
324 return FALSE(0);
325 }
326
327 g_hash_table_iter_init (&iter, hash1);
328 while (g_hash_table_iter_next (&iter, &key1, &value1)) {
329 value2 = g_hash_table_lookup (hash2, key1);
330 if (value2 == NULL((void*)0)) {
331 return FALSE(0);
332 }
333 id = GPOINTER_TO_UINT (key1)((guint) (gulong) (key1));
334 if (id & METADATA_ID_IS_LIST_MASK(1U<<31)) {
335 if (!eel_g_strv_equal ((char **)value1, (char **)value2)) {
336 return FALSE(0);
337 }
338 } else {
339 if (strcmp ((char *)value1, (char *)value2) != 0) {
340 return FALSE(0);
341 }
342 }
343 }
344
345 return TRUE(!(0));
346}
347
348static void
349clear_metadata (BaulFile *file)
350{
351 if (file->details->metadata) {
352 metadata_hash_free (file->details->metadata);
353 file->details->metadata = NULL((void*)0);
354 }
355}
356
357static GHashTable *
358get_metadata_from_info (GFileInfo *info)
359{
360 GHashTable *metadata;
361 char **attrs;
362 guint id;
363 int i;
364 GFileAttributeType type;
365 gpointer value;
366
367 attrs = g_file_info_list_attributes (info, "metadata");
368
369 metadata = g_hash_table_new (NULL((void*)0), NULL((void*)0));
370
371 for (i = 0; attrs[i] != NULL((void*)0); i++) {
372 id = baul_metadata_get_id (attrs[i] + strlen ("metadata::"));
373 if (id == 0) {
374 continue;
375 }
376
377 if (!g_file_info_get_attribute_data (info, attrs[i],
378 &type, &value, NULL((void*)0))) {
379 continue;
380 }
381
382 if (type == G_FILE_ATTRIBUTE_TYPE_STRING) {
383 g_hash_table_insert (metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)),
384 g_strdup ((char *)value)g_strdup_inline ((char *)value));
385 } else if (type == G_FILE_ATTRIBUTE_TYPE_STRINGV) {
386 id |= METADATA_ID_IS_LIST_MASK(1U<<31);
387 g_hash_table_insert (metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)),
388 g_strdupv ((char **)value));
389 }
390 }
391
392 g_strfreev (attrs);
393
394 return metadata;
395}
396
397gboolean
398baul_file_update_metadata_from_info (BaulFile *file,
399 GFileInfo *info)
400{
401 gboolean changed = FALSE(0);
402
403 if (g_file_info_has_namespace (info, "metadata")) {
404 GHashTable *metadata;
405
406 metadata = get_metadata_from_info (info);
407 if (!metadata_hash_equal (metadata,
408 file->details->metadata)) {
409 changed = TRUE(!(0));
410 clear_metadata (file);
411 file->details->metadata = metadata;
412 } else {
413 metadata_hash_free (metadata);
414 }
415 } else if (file->details->metadata) {
416 changed = TRUE(!(0));
417 clear_metadata (file);
418 }
419 return changed;
420}
421
422void
423baul_file_clear_info (BaulFile *file)
424{
425 file->details->got_file_info = FALSE(0);
426 if (file->details->get_info_error) {
427 g_error_free (file->details->get_info_error);
428 file->details->get_info_error = NULL((void*)0);
429 }
430 /* Reset to default type, which might be other than unknown for
431 special kinds of files like the desktop or a search directory */
432 file->details->type = BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type;
433
434 if (!file->details->got_custom_display_name) {
435 baul_file_clear_display_name (file);
436 }
437
438 if (!file->details->got_custom_activation_uri &&
439 file->details->activation_uri != NULL((void*)0)) {
440 g_free (file->details->activation_uri);
441 file->details->activation_uri = NULL((void*)0);
442 }
443
444 if (file->details->icon != NULL((void*)0)) {
445 g_object_unref (file->details->icon);
446 file->details->icon = NULL((void*)0);
447 }
448
449 g_free (file->details->thumbnail_path);
450 file->details->thumbnail_path = NULL((void*)0);
451 file->details->thumbnailing_failed = FALSE(0);
452
453 file->details->is_launcher = FALSE(0);
454 file->details->is_foreign_link = FALSE(0);
455 file->details->is_trusted_link = FALSE(0);
456 file->details->is_symlink = FALSE(0);
457 file->details->is_hidden = FALSE(0);
458 file->details->is_backup = FALSE(0);
459 file->details->is_mountpoint = FALSE(0);
460 file->details->uid = -1;
461 file->details->gid = -1;
462 file->details->can_read = TRUE(!(0));
463 file->details->can_write = TRUE(!(0));
464 file->details->can_execute = TRUE(!(0));
465 file->details->can_delete = TRUE(!(0));
466 file->details->can_trash = TRUE(!(0));
467 file->details->can_rename = TRUE(!(0));
468 file->details->can_mount = FALSE(0);
469 file->details->can_unmount = FALSE(0);
470 file->details->can_eject = FALSE(0);
471 file->details->can_start = FALSE(0);
472 file->details->can_start_degraded = FALSE(0);
473 file->details->can_stop = FALSE(0);
474 file->details->start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
475 file->details->can_poll_for_media = FALSE(0);
476 file->details->is_media_check_automatic = FALSE(0);
477 file->details->has_permissions = FALSE(0);
478 file->details->permissions = 0;
479 file->details->size = -1;
480 file->details->size_on_disk = -1;
481 file->details->sort_order = 0;
482 file->details->mtime = 0;
483 file->details->atime = 0;
484 file->details->ctime = 0;
485 file->details->trash_time = 0;
486 g_free (file->details->symlink_name);
487 file->details->symlink_name = NULL((void*)0);
488 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
489 file->details->mime_type = NULL((void*)0);
490 g_free (file->details->selinux_context);
491 file->details->selinux_context = NULL((void*)0);
492 g_free (file->details->description);
493 file->details->description = NULL((void*)0);
494 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
495 file->details->owner = NULL((void*)0);
496 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
497 file->details->owner_real = NULL((void*)0);
498 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
499 file->details->group = NULL((void*)0);
500
501 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
502 file->details->filesystem_id = NULL((void*)0);
503
504 clear_metadata (file);
505}
506
507static BaulFile *
508baul_file_new_from_filename (BaulDirectory *directory,
509 const char *filename,
510 gboolean self_owned)
511{
512 BaulFile *file;
513
514 g_assert (BAUL_IS_DIRECTORY (directory))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory)); GType __t = (baul_directory_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 514, (
(const char*) (__func__)), "BAUL_IS_DIRECTORY (directory)"); }
while (0)
;
515 g_assert (filename != NULL)do { if (filename != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 515, ((const char*) (__func__)
), "filename != NULL"); } while (0)
;
516 g_assert (filename[0] != '\0')do { if (filename[0] != '\0') ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 516, ((const char*) (__func__)
), "filename[0] != '\\0'"); } while (0)
;
517
518 if (BAUL_IS_DESKTOP_DIRECTORY (directory)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory)); GType __t = (baul_desktop_directory_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; }
))))
) {
519 if (self_owned) {
520 file = BAUL_FILE (g_object_new (BAUL_TYPE_DESKTOP_DIRECTORY_FILE, NULL))((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((g_object_new (baul_desktop_directory_file_get_type(), ((
void*)0)))), (baul_file_get_type())))))
;
521 } else {
522 /* This doesn't normally happen, unless the user somehow types in a uri
523 * that references a file like this. (See #349840) */
524 file = BAUL_FILE (g_object_new (BAUL_TYPE_VFS_FILE, NULL))((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((g_object_new (baul_vfs_file_get_type(), ((void*)0)))), (
baul_file_get_type())))))
;
525 }
526 } else if (BAUL_IS_SEARCH_DIRECTORY (directory)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory)); GType __t = (baul_search_directory_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; }
))))
) {
527 if (self_owned) {
528 file = BAUL_FILE (g_object_new (BAUL_TYPE_SEARCH_DIRECTORY_FILE, NULL))((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((g_object_new (baul_search_directory_file_get_type(), ((void
*)0)))), (baul_file_get_type())))))
;
529 } else {
530 /* This doesn't normally happen, unless the user somehow types in a uri
531 * that references a file like this. (See #349840) */
532 file = BAUL_FILE (g_object_new (BAUL_TYPE_VFS_FILE, NULL))((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((g_object_new (baul_vfs_file_get_type(), ((void*)0)))), (
baul_file_get_type())))))
;
533 }
534 } else if (g_str_has_suffix (filename, BAUL_SAVED_SEARCH_EXTENSION)(__builtin_constant_p (".savedSearch")? __extension__ ({ const
char * const __str = (filename); const char * const __suffix
= (".savedSearch"); gboolean __result = (0); if (__str == ((
void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (filename, ".savedSearch") )
) {
535 file = BAUL_FILE (g_object_new (BAUL_TYPE_SAVED_SEARCH_FILE, NULL))((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((g_object_new (baul_saved_search_file_get_type(), ((void*
)0)))), (baul_file_get_type())))))
;
536 } else {
537 file = BAUL_FILE (g_object_new (BAUL_TYPE_VFS_FILE, NULL))((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((g_object_new (baul_vfs_file_get_type(), ((void*)0)))), (
baul_file_get_type())))))
;
538 }
539
540 file->details->directory = baul_directory_ref (directory);
541
542 file->details->name = g_ref_string_new (filename);
543
544#ifdef BAUL_FILE_DEBUG_REF
545 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
546#endif
547
548 return file;
549}
550
551static void
552modify_link_hash_table (BaulFile *file,
553 ModifyListFunction modify_function)
554{
555 char *target_uri;
556 gboolean found;
557 gpointer original_key;
558 GList **list_ptr;
559
560 /* Check if there is a symlink name. If none, we are OK. */
561 if (file->details->symlink_name == NULL((void*)0) || !baul_file_is_symbolic_link (file)) {
562 return;
563 }
564
565 /* Create the hash table first time through. */
566 if (symbolic_links == NULL((void*)0)) {
567 symbolic_links = g_hash_table_new (g_str_hash, g_str_equal);
568 }
569
570 target_uri = baul_file_get_symbolic_link_target_uri (file);
571
572 /* Find the old contents of the hash table. */
573 found = g_hash_table_lookup_extended
574 (symbolic_links, target_uri,
575 &original_key, (gpointer *)&list_ptr);
576 if (!found) {
577 list_ptr = g_new0 (GList *, 1)((GList * *) g_malloc0_n ((1), sizeof (GList *)));
578 original_key = g_strdup (target_uri)g_strdup_inline (target_uri);
579 g_hash_table_insert (symbolic_links, original_key, list_ptr);
580 }
581 (* modify_function) (list_ptr, file);
582 if (*list_ptr == NULL((void*)0)) {
583 g_hash_table_remove (symbolic_links, target_uri);
584 g_free (list_ptr);
585 g_free (original_key);
586 }
587 g_free (target_uri);
588}
589
590static void
591symbolic_link_weak_notify (gpointer data,
592 GObject *where_the_object_was)
593{
594 GList **list = data;
595 /* This really shouldn't happen, but we're seeing some strange things in
596 bug #358172 where the symlink hashtable isn't correctly updated. */
597 *list = g_list_remove (*list, where_the_object_was);
598}
599
600static void
601add_to_link_hash_table_list (GList **list, BaulFile *file)
602{
603 if (g_list_find (*list, file) != NULL((void*)0)) {
604 g_warning ("Adding file to symlink_table multiple times. "
605 "Please add feedback of what you were doing at https://bugzilla.gnome.org/show_bug.cgi?id=358172\n");
606 return;
607 }
608 g_object_weak_ref (G_OBJECT (file)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((file)), (((GType) ((20) << (2))))))))
, symbolic_link_weak_notify, list);
609 *list = g_list_prepend (*list, file);
610}
611
612static void
613add_to_link_hash_table (BaulFile *file)
614{
615 modify_link_hash_table (file, add_to_link_hash_table_list);
616}
617
618static void
619remove_from_link_hash_table_list (GList **list, BaulFile *file)
620{
621 if (g_list_find (*list, file) != NULL((void*)0)) {
622 g_object_weak_unref (G_OBJECT (file)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((file)), (((GType) ((20) << (2))))))))
, symbolic_link_weak_notify, list);
623 *list = g_list_remove (*list, file);
624 }
625}
626
627static void
628remove_from_link_hash_table (BaulFile *file)
629{
630 modify_link_hash_table (file, remove_from_link_hash_table_list);
631}
632
633BaulFile *
634baul_file_new_from_info (BaulDirectory *directory,
635 GFileInfo *info)
636{
637 BaulFile *file;
638 const char *mime_type;
639
640 g_return_val_if_fail (BAUL_IS_DIRECTORY (directory), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory)); GType __t = (baul_directory_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_DIRECTORY (directory)"); return (((void
*)0)); } } while (0)
;
641 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "info != NULL"); return
(((void*)0)); } } while (0)
;
642
643 mime_type = g_file_info_get_content_type (info);
644 if (mime_type &&
645 strcmp (mime_type, BAUL_SAVED_SEARCH_MIMETYPE"application/x-cafe-saved-search") == 0) {
646 g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
647 file = BAUL_FILE (g_object_new (BAUL_TYPE_SAVED_SEARCH_FILE, NULL))((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((g_object_new (baul_saved_search_file_get_type(), ((void*
)0)))), (baul_file_get_type())))))
;
648 } else {
649 file = BAUL_FILE (g_object_new (BAUL_TYPE_VFS_FILE, NULL))((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((g_object_new (baul_vfs_file_get_type(), ((void*)0)))), (
baul_file_get_type())))))
;
650 }
651
652 file->details->directory = baul_directory_ref (directory);
653
654 update_info_and_name (file, info);
655
656#ifdef BAUL_FILE_DEBUG_REF
657 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
658#endif
659
660 return file;
661}
662
663static BaulFile *
664baul_file_get_internal (GFile *location, gboolean create)
665{
666 gboolean self_owned;
667 BaulDirectory *directory;
668 BaulFile *file;
669 GFile *parent;
670 char *basename;
671
672 g_assert (location != NULL)do { if (location != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 672, ((const char*) (__func__)
), "location != NULL"); } while (0)
;
673
674 parent = g_file_get_parent (location);
675
676 self_owned = FALSE(0);
677 if (parent == NULL((void*)0)) {
678 self_owned = TRUE(!(0));
679 parent = g_object_ref (location)((__typeof__ (location)) (g_object_ref) (location));
680 }
681
682 /* Get object that represents the directory. */
683 directory = baul_directory_get_internal (parent, create);
684
685 g_object_unref (parent);
686
687 /* Get the name for the file. */
688 if (self_owned && directory != NULL((void*)0)) {
689 basename = baul_directory_get_name_for_self_as_new_file (directory);
690 } else {
691 basename = g_file_get_basename (location);
692 }
693 /* Check to see if it's a file that's already known. */
694 if (directory == NULL((void*)0)) {
695 file = NULL((void*)0);
696 } else if (self_owned) {
697 file = directory->details->as_file;
698 } else {
699 file = baul_directory_find_file_by_name (directory, basename);
700 }
701
702 /* Ref or create the file. */
703 if (file != NULL((void*)0)) {
704 baul_file_ref (file);
705 } else if (create && directory != NULL((void*)0)) {
706 file = baul_file_new_from_filename (directory, basename, self_owned);
707 if (self_owned) {
708 g_assert (directory->details->as_file == NULL)do { if (directory->details->as_file == ((void*)0)) ; else
g_assertion_message_expr (((gchar*) 0), "baul-file.c", 708, (
(const char*) (__func__)), "directory->details->as_file == NULL"
); } while (0)
;
709 directory->details->as_file = file;
710 } else {
711 baul_directory_add_file (directory, file);
712 }
713 }
714
715 g_free (basename);
716 baul_directory_unref (directory);
717
718 return file;
719}
720
721BaulFile *
722baul_file_get (GFile *location)
723{
724 return baul_file_get_internal (location, TRUE(!(0)));
725}
726
727BaulFile *
728baul_file_get_existing (GFile *location)
729{
730 return baul_file_get_internal (location, FALSE(0));
731}
732
733BaulFile *
734baul_file_get_existing_by_uri (const char *uri)
735{
736 GFile *location;
737 BaulFile *file;
738
739 location = g_file_new_for_uri (uri);
740 file = baul_file_get_internal (location, FALSE(0));
741 g_object_unref (location);
742
743 return file;
744}
745
746BaulFile *
747baul_file_get_by_uri (const char *uri)
748{
749 GFile *location;
750 BaulFile *file;
751
752 location = g_file_new_for_uri (uri);
753 file = baul_file_get_internal (location, TRUE(!(0)));
754 g_object_unref (location);
755
756 return file;
757}
758
759gboolean
760baul_file_is_self_owned (BaulFile *file)
761{
762 return file->details->directory->details->as_file == file;
763}
764
765static void
766finalize (GObject *object)
767{
768 BaulDirectory *directory;
769 BaulFile *file;
770
771 file = BAUL_FILE (object)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), (baul_file_get_type())))))
;
772
773 g_assert (file->details->operations_in_progress == NULL)do { if (file->details->operations_in_progress == ((void
*)0)) ; else g_assertion_message_expr (((gchar*) 0), "baul-file.c"
, 773, ((const char*) (__func__)), "file->details->operations_in_progress == NULL"
); } while (0)
;
774
775 if (file->details->is_thumbnailing) {
776 char *uri;
777
778 uri = baul_file_get_uri (file);
779 baul_thumbnail_remove_from_queue (uri);
780 g_free (uri);
781 }
782
783 baul_async_destroying_file (file);
784
785 remove_from_link_hash_table (file);
786
787 directory = file->details->directory;
788
789 if (baul_file_is_self_owned (file)) {
790 directory->details->as_file = NULL((void*)0);
791 } else {
792 if (!file->details->is_gone) {
793 baul_directory_remove_file (directory, file);
794 }
795 }
796
797 if (file->details->get_info_error) {
798 g_error_free (file->details->get_info_error);
799 }
800
801 baul_directory_unref (directory);
802 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
803 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
804 g_free (file->details->display_name_collation_key);
805 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
806 if (file->details->icon) {
807 g_object_unref (file->details->icon);
808 }
809 g_free (file->details->thumbnail_path);
810 g_free (file->details->symlink_name);
811 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
812 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
813 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
814 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
815 g_free (file->details->selinux_context);
816 g_free (file->details->description);
817 g_free (file->details->top_left_text);
818 g_free (file->details->custom_icon);
819 g_free (file->details->activation_uri);
820 g_free (file->details->compare_by_emblem_cache);
821
822 if (file->details->thumbnail) {
823 g_object_unref (file->details->thumbnail);
824 }
825 if (file->details->mount) {
826 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file)g_signal_handlers_disconnect_matched ((file->details->mount
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (file_mount_unmounted), (file))
;
827 g_object_unref (file->details->mount);
828 }
829
830 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
831
832 g_list_free_full (file->details->mime_list, g_free);
833 g_list_free_full (file->details->pending_extension_emblems, g_free);
834 g_list_free_full (file->details->extension_emblems, g_free);
835 g_list_free_full (file->details->pending_info_providers, g_object_unref);
836
837 if (file->details->pending_extension_attributes) {
838 g_hash_table_destroy (file->details->pending_extension_attributes);
839 }
840
841 if (file->details->extension_attributes) {
842 g_hash_table_destroy (file->details->extension_attributes);
843 }
844
845 if (file->details->metadata) {
846 metadata_hash_free (file->details->metadata);
847 }
848
849 G_OBJECT_CLASS (baul_file_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((baul_file_parent_class)), (((GType) ((20) << (2)))
)))))
->finalize (object);
850}
851
852BaulFile *
853baul_file_ref (BaulFile *file)
854{
855 if (file == NULL((void*)0)) {
856 return NULL((void*)0);
857 }
858 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
859
860#ifdef BAUL_FILE_DEBUG_REF
861 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
862#endif
863
864 return g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
865}
866
867void
868baul_file_unref (BaulFile *file)
869{
870 if (file == NULL((void*)0)) {
871 return;
872 }
873
874 g_return_if_fail (BAUL_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return; } } while (0)
;
875
876#ifdef BAUL_FILE_DEBUG_REF
877 DEBUG_REF_PRINTFprintf("%10p unref'd", file);
878#endif
879
880 g_object_unref (file);
881}
882
883/**
884 * baul_file_get_parent_uri_for_display:
885 *
886 * Get the uri for the parent directory.
887 *
888 * @file: The file in question.
889 *
890 * Return value: A string representing the parent's location,
891 * formatted for user display (including stripping "file://").
892 * If the parent is NULL, returns the empty string.
893 */
894char *
895baul_file_get_parent_uri_for_display (BaulFile *file)
896{
897 GFile *parent;
898 char *result;
899
900 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 900, (
(const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (0
)
;
901
902 parent = baul_file_get_parent_location (file);
903 if (parent) {
904 result = g_file_get_parse_name (parent);
905 g_object_unref (parent);
906 } else {
907 result = g_strdup ("")g_strdup_inline ("");
908 }
909
910 return result;
911}
912
913/**
914 * baul_file_get_parent_uri:
915 *
916 * Get the uri for the parent directory.
917 *
918 * @file: The file in question.
919 *
920 * Return value: A string for the parent's location, in "raw URI" form.
921 * Use baul_file_get_parent_uri_for_display instead if the
922 * result is to be displayed on-screen.
923 * If the parent is NULL, returns the empty string.
924 */
925char *
926baul_file_get_parent_uri (BaulFile *file)
927{
928 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 928, (
(const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (0
)
;
929
930 if (baul_file_is_self_owned (file)) {
931 /* Callers expect an empty string, not a NULL. */
932 return g_strdup ("")g_strdup_inline ("");
933 }
934
935 return baul_directory_get_uri (file->details->directory);
936}
937
938GFile *
939baul_file_get_parent_location (BaulFile *file)
940{
941 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 941, (
(const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (0
)
;
942
943 if (baul_file_is_self_owned (file)) {
944 /* Callers expect an empty string, not a NULL. */
945 return NULL((void*)0);
946 }
947
948 return baul_directory_get_location (file->details->directory);
949}
950
951BaulFile *
952baul_file_get_parent (BaulFile *file)
953{
954 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 954, (
(const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (0
)
;
955
956 if (baul_file_is_self_owned (file)) {
957 return NULL((void*)0);
958 }
959
960 return baul_directory_get_corresponding_file (file->details->directory);
961}
962
963/**
964 * baul_file_can_read:
965 *
966 * Check whether the user is allowed to read the contents of this file.
967 *
968 * @file: The file to check.
969 *
970 * Return value: FALSE if the user is definitely not allowed to read
971 * the contents of the file. If the user has read permission, or
972 * the code can't tell whether the user has read permission,
973 * returns TRUE (so failures must always be handled).
974 */
975gboolean
976baul_file_can_read (BaulFile *file)
977{
978 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
979
980 return file->details->can_read;
981}
982
983/**
984 * baul_file_can_write:
985 *
986 * Check whether the user is allowed to write to this file.
987 *
988 * @file: The file to check.
989 *
990 * Return value: FALSE if the user is definitely not allowed to write
991 * to the file. If the user has write permission, or
992 * the code can't tell whether the user has write permission,
993 * returns TRUE (so failures must always be handled).
994 */
995gboolean
996baul_file_can_write (BaulFile *file)
997{
998 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
999
1000 return file->details->can_write;
1001}
1002
1003/**
1004 * baul_file_can_execute:
1005 *
1006 * Check whether the user is allowed to execute this file.
1007 *
1008 * @file: The file to check.
1009 *
1010 * Return value: FALSE if the user is definitely not allowed to execute
1011 * the file. If the user has execute permission, or
1012 * the code can't tell whether the user has execute permission,
1013 * returns TRUE (so failures must always be handled).
1014 */
1015gboolean
1016baul_file_can_execute (BaulFile *file)
1017{
1018 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
1019
1020 return file->details->can_execute;
1021}
1022
1023gboolean
1024baul_file_can_mount (BaulFile *file)
1025{
1026 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
1027
1028 return file->details->can_mount;
1029}
1030
1031gboolean
1032baul_file_can_unmount (BaulFile *file)
1033{
1034 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
1035
1036 return file->details->can_unmount ||
1037 (file->details->mount != NULL((void*)0) &&
1038 g_mount_can_unmount (file->details->mount));
1039}
1040
1041gboolean
1042baul_file_can_eject (BaulFile *file)
1043{
1044 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
1045
1046 return file->details->can_eject ||
1047 (file->details->mount != NULL((void*)0) &&
1048 g_mount_can_eject (file->details->mount));
1049}
1050
1051gboolean
1052baul_file_can_start (BaulFile *file)
1053{
1054 gboolean ret;
1055 GDrive *drive;
1056
1057 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
1058
1059 ret = FALSE(0);
1060
1061 if (file->details->can_start) {
1062 ret = TRUE(!(0));
1063 goto out;
1064 }
1065
1066 if (file->details->mount != NULL((void*)0)) {
1067 drive = g_mount_get_drive (file->details->mount);
1068 if (drive != NULL((void*)0)) {
1069 ret = g_drive_can_start (drive);
1070 g_object_unref (drive);
1071 }
1072 }
1073
1074 out:
1075 return ret;
1076}
1077
1078gboolean
1079baul_file_can_start_degraded (BaulFile *file)
1080{
1081 gboolean ret;
1082 GDrive *drive;
1083
1084 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
1085
1086 ret = FALSE(0);
1087
1088 if (file->details->can_start_degraded) {
1089 ret = TRUE(!(0));
1090 goto out;
1091 }
1092
1093 if (file->details->mount != NULL((void*)0)) {
1094 drive = g_mount_get_drive (file->details->mount);
1095 if (drive != NULL((void*)0)) {
1096 ret = g_drive_can_start_degraded (drive);
1097 g_object_unref (drive);
1098 }
1099 }
1100
1101 out:
1102 return ret;
1103}
1104
1105gboolean
1106baul_file_can_poll_for_media (BaulFile *file)
1107{
1108 gboolean ret;
1109 GDrive *drive;
1110
1111 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
1112
1113 ret = FALSE(0);
1114
1115 if (file->details->can_poll_for_media) {
1116 ret = TRUE(!(0));
1117 goto out;
1118 }
1119
1120 if (file->details->mount != NULL((void*)0)) {
1121 drive = g_mount_get_drive (file->details->mount);
1122 if (drive != NULL((void*)0)) {
1123 ret = g_drive_can_poll_for_media (drive);
1124 g_object_unref (drive);
1125 }
1126 }
1127
1128 out:
1129 return ret;
1130}
1131
1132gboolean
1133baul_file_is_media_check_automatic (BaulFile *file)
1134{
1135 gboolean ret;
1136 GDrive *drive;
1137
1138 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
1139
1140 ret = FALSE(0);
1141
1142 if (file->details->is_media_check_automatic) {
1143 ret = TRUE(!(0));
1144 goto out;
1145 }
1146
1147 if (file->details->mount != NULL((void*)0)) {
1148 drive = g_mount_get_drive (file->details->mount);
1149 if (drive != NULL((void*)0)) {
1150 ret = g_drive_is_media_check_automatic (drive);
1151 g_object_unref (drive);
1152 }
1153 }
1154
1155 out:
1156 return ret;
1157}
1158
1159
1160gboolean
1161baul_file_can_stop (BaulFile *file)
1162{
1163 gboolean ret;
1164 GDrive *drive;
1165
1166 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
1167
1168 ret = FALSE(0);
1169
1170 if (file->details->can_stop) {
1171 ret = TRUE(!(0));
1172 goto out;
1173 }
1174
1175 if (file->details->mount != NULL((void*)0)) {
1176 drive = g_mount_get_drive (file->details->mount);
1177 if (drive != NULL((void*)0)) {
1178 ret = g_drive_can_stop (drive);
1179 g_object_unref (drive);
1180 }
1181 }
1182
1183 out:
1184 return ret;
1185}
1186
1187GDriveStartStopType
1188baul_file_get_start_stop_type (BaulFile *file)
1189{
1190 GDriveStartStopType ret;
1191 GDrive *drive;
1192
1193 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
1194
1195 ret = G_DRIVE_START_STOP_TYPE_UNKNOWN;
Value stored to 'ret' is never read
1196
1197 ret = file->details->start_stop_type;
1198 if (ret != G_DRIVE_START_STOP_TYPE_UNKNOWN)
1199 goto out;
1200
1201 if (file->details->mount != NULL((void*)0)) {
1202 drive = g_mount_get_drive (file->details->mount);
1203 if (drive != NULL((void*)0)) {
1204 ret = g_drive_get_start_stop_type (drive);
1205 g_object_unref (drive);
1206 }
1207 }
1208
1209 out:
1210 return ret;
1211}
1212
1213void
1214baul_file_mount (BaulFile *file,
1215 GMountOperation *mount_op,
1216 GCancellable *cancellable,
1217 BaulFileOperationCallback callback,
1218 gpointer callback_data)
1219{
1220 GError *error;
1221
1222 if (BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->mount == NULL((void*)0)) {
1223 if (callback) {
1224 error = NULL((void*)0);
1225 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1226 _("This file cannot be mounted")gettext ("This file cannot be mounted"));
1227 callback (file, NULL((void*)0), error, callback_data);
1228 g_error_free (error);
1229 }
1230 } else {
1231 BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->mount (file, mount_op, cancellable, callback, callback_data);
1232 }
1233}
1234
1235typedef struct {
1236 BaulFile *file;
1237 BaulFileOperationCallback callback;
1238 gpointer callback_data;
1239} UnmountData;
1240
1241static void
1242unmount_done (void *callback_data)
1243{
1244 UnmountData *data;
1245
1246 data = (UnmountData *)callback_data;
1247 if (data->callback) {
1248 data->callback (data->file, NULL((void*)0), NULL((void*)0), data->callback_data);
1249 }
1250 baul_file_unref (data->file);
1251 g_free (data);
1252}
1253
1254void
1255baul_file_unmount (BaulFile *file,
1256 GMountOperation *mount_op,
1257 GCancellable *cancellable,
1258 BaulFileOperationCallback callback,
1259 gpointer callback_data)
1260{
1261 GError *error;
1262 UnmountData *data;
1263
1264 if (file->details->can_unmount) {
1265 if (BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->unmount != NULL((void*)0)) {
1266 BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->unmount (file, mount_op, cancellable, callback, callback_data);
1267 } else {
1268 if (callback) {
1269 error = NULL((void*)0);
1270 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1271 _("This file cannot be unmounted")gettext ("This file cannot be unmounted"));
1272 callback (file, NULL((void*)0), error, callback_data);
1273 g_error_free (error);
1274 }
1275 }
1276 } else if (file->details->mount != NULL((void*)0) &&
1277 g_mount_can_unmount (file->details->mount)) {
1278 data = g_new0 (UnmountData, 1)((UnmountData *) g_malloc0_n ((1), sizeof (UnmountData)));
1279 data->file = baul_file_ref (file);
1280 data->callback = callback;
1281 data->callback_data = callback_data;
1282 baul_file_operations_unmount_mount_full (NULL((void*)0), file->details->mount, FALSE(0), TRUE(!(0)), unmount_done, data);
1283 } else if (callback) {
1284 callback (file, NULL((void*)0), NULL((void*)0), callback_data);
1285 }
1286}
1287
1288void
1289baul_file_eject (BaulFile *file,
1290 GMountOperation *mount_op,
1291 GCancellable *cancellable,
1292 BaulFileOperationCallback callback,
1293 gpointer callback_data)
1294{
1295 GError *error;
1296 UnmountData *data;
1297
1298 if (file->details->can_eject) {
1299 if (BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->eject != NULL((void*)0)) {
1300 BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->eject (file, mount_op, cancellable, callback, callback_data);
1301 } else {
1302 if (callback) {
1303 error = NULL((void*)0);
1304 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1305 _("This file cannot be ejected")gettext ("This file cannot be ejected"));
1306 callback (file, NULL((void*)0), error, callback_data);
1307 g_error_free (error);
1308 }
1309 }
1310 } else if (file->details->mount != NULL((void*)0) &&
1311 g_mount_can_eject (file->details->mount)) {
1312 data = g_new0 (UnmountData, 1)((UnmountData *) g_malloc0_n ((1), sizeof (UnmountData)));
1313 data->file = baul_file_ref (file);
1314 data->callback = callback;
1315 data->callback_data = callback_data;
1316 baul_file_operations_unmount_mount_full (NULL((void*)0), file->details->mount, TRUE(!(0)), TRUE(!(0)), unmount_done, data);
1317 } else if (callback) {
1318 callback (file, NULL((void*)0), NULL((void*)0), callback_data);
1319 }
1320}
1321
1322void
1323baul_file_start (BaulFile *file,
1324 GMountOperation *start_op,
1325 GCancellable *cancellable,
1326 BaulFileOperationCallback callback,
1327 gpointer callback_data)
1328{
1329 GError *error;
1330
1331 if ((file->details->can_start || file->details->can_start_degraded) &&
1332 BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->start != NULL((void*)0)) {
1333 BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->start (file, start_op, cancellable, callback, callback_data);
1334 } else {
1335 if (callback) {
1336 error = NULL((void*)0);
1337 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1338 _("This file cannot be started")gettext ("This file cannot be started"));
1339 callback (file, NULL((void*)0), error, callback_data);
1340 g_error_free (error);
1341 }
1342 }
1343}
1344
1345static void
1346file_stop_callback (GObject *source_object,
1347 GAsyncResult *res,
1348 gpointer callback_data)
1349{
1350 BaulFileOperation *op;
1351 gboolean stopped;
1352 GError *error;
1353
1354 op = callback_data;
1355
1356 error = NULL((void*)0);
1357 stopped = g_drive_stop_finish (G_DRIVE (source_object)((((GDrive*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_drive_get_type ()))))))
,
1358 res, &error);
1359
1360 if (!stopped &&
1361 error->domain == G_IO_ERRORg_io_error_quark() &&
1362 (error->code == G_IO_ERROR_FAILED_HANDLED ||
1363 error->code == G_IO_ERROR_CANCELLED)) {
1364 g_error_free (error);
1365 error = NULL((void*)0);
1366 }
1367
1368 baul_file_operation_complete (op, NULL((void*)0), error);
1369 if (error) {
1370 g_error_free (error);
1371 }
1372}
1373
1374void
1375baul_file_stop (BaulFile *file,
1376 GMountOperation *mount_op,
1377 GCancellable *cancellable,
1378 BaulFileOperationCallback callback,
1379 gpointer callback_data)
1380{
1381 GError *error;
1382
1383 if (BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop != NULL((void*)0)) {
1384 if (file->details->can_stop) {
1385 BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop (file, mount_op, cancellable, callback, callback_data);
1386 } else {
1387 if (callback) {
1388 error = NULL((void*)0);
1389 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1390 _("This file cannot be stopped")gettext ("This file cannot be stopped"));
1391 callback (file, NULL((void*)0), error, callback_data);
1392 g_error_free (error);
1393 }
1394 }
1395 } else {
1396 GDrive *drive;
1397
1398 drive = NULL((void*)0);
1399 if (file->details->mount != NULL((void*)0))
1400 drive = g_mount_get_drive (file->details->mount);
1401
1402 if (drive != NULL((void*)0) && g_drive_can_stop (drive)) {
1403 BaulFileOperation *op;
1404
1405 op = baul_file_operation_new (file, callback, callback_data);
1406 if (cancellable) {
1407 g_object_unref (op->cancellable);
1408 op->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
1409 }
1410
1411 g_drive_stop (drive,
1412 G_MOUNT_UNMOUNT_NONE,
1413 mount_op,
1414 op->cancellable,
1415 file_stop_callback,
1416 op);
1417 } else {
1418 if (callback) {
1419 error = NULL((void*)0);
1420 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1421 _("This file cannot be stopped")gettext ("This file cannot be stopped"));
1422 callback (file, NULL((void*)0), error, callback_data);
1423 g_error_free (error);
1424 }
1425 }
1426
1427 if (drive != NULL((void*)0)) {
1428 g_object_unref (drive);
1429 }
1430 }
1431}
1432
1433void
1434baul_file_poll_for_media (BaulFile *file)
1435{
1436 if (file->details->can_poll_for_media) {
1437 if (BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop != NULL((void*)0)) {
1438 BAUL_FILE_GET_CLASS (file)((((BaulFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->poll_for_media (file);
1439 }
1440 } else if (file->details->mount != NULL((void*)0)) {
1441 GDrive *drive;
1442 drive = g_mount_get_drive (file->details->mount);
1443 if (drive != NULL((void*)0)) {
1444 g_drive_poll_for_media (drive,
1445 NULL((void*)0), /* cancellable */
1446 NULL((void*)0), /* GAsyncReadyCallback */
1447 NULL((void*)0)); /* user_data */
1448 g_object_unref (drive);
1449 }
1450 }
1451}
1452
1453/**
1454 * baul_file_is_desktop_directory:
1455 *
1456 * Check whether this file is the desktop directory.
1457 *
1458 * @file: The file to check.
1459 *
1460 * Return value: TRUE if this is the physical desktop directory.
1461 */
1462gboolean
1463baul_file_is_desktop_directory (BaulFile *file)
1464{
1465 GFile *dir;
1466
1467 dir = file->details->directory->details->location;
1468
1469 if (dir == NULL((void*)0)) {
1470 return FALSE(0);
1471 }
1472
1473 return baul_is_desktop_directory_file (dir, file->details->name);
1474}
1475
1476static gboolean
1477is_desktop_file (BaulFile *file)
1478{
1479 return baul_file_is_mime_type (file, "application/x-desktop");
1480}
1481
1482static gboolean
1483can_rename_desktop_file (BaulFile *file)
1484{
1485 GFile *location;
1486 gboolean res;
1487
1488 location = baul_file_get_location (file);
1489 res = g_file_is_native (location);
1490 g_object_unref (location);
1491 return res;
1492}
1493
1494/**
1495 * baul_file_can_rename:
1496 *
1497 * Check whether the user is allowed to change the name of the file.
1498 *
1499 * @file: The file to check.
1500 *
1501 * Return value: FALSE if the user is definitely not allowed to change
1502 * the name of the file. If the user is allowed to change the name, or
1503 * the code can't tell whether the user is allowed to change the name,
1504 * returns TRUE (so rename failures must always be handled).
1505 */
1506gboolean
1507baul_file_can_rename (BaulFile *file)
1508{
1509 gboolean can_rename;
1510
1511 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
1512
1513 /* Nonexistent files can't be renamed. */
1514 if (baul_file_is_gone (file)) {
1515 return FALSE(0);
1516 }
1517
1518 /* Self-owned files can't be renamed */
1519 if (baul_file_is_self_owned (file)) {
1520 return FALSE(0);
1521 }
1522
1523 if ((is_desktop_file (file) && !can_rename_desktop_file (file)) ||
1524 baul_file_is_home (file)) {
1525 return FALSE(0);
1526 }
1527
1528 can_rename = TRUE(!(0));
1529
1530 /* Certain types of links can't be renamed */
1531 if (BAUL_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (baul_desktop_icon_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; }))))
) {
1532 BaulDesktopLink *link;
1533
1534 link = baul_desktop_icon_file_get_link (BAUL_DESKTOP_ICON_FILE (file)((((BaulDesktopIconFile*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((file)), (baul_desktop_icon_file_get_type
())))))
);
1535
1536 if (link != NULL((void*)0)) {
1537 can_rename = baul_desktop_link_can_rename (link);
1538 g_object_unref (link);
1539 }
1540 }
1541
1542 if (!can_rename) {
1543 return FALSE(0);
1544 }
1545
1546 return file->details->can_rename;
1547}
1548
1549gboolean
1550baul_file_can_delete (BaulFile *file)
1551{
1552 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
1553
1554 /* Nonexistent files can't be deleted. */
1555 if (baul_file_is_gone (file)) {
1556 return FALSE(0);
1557 }
1558
1559 /* Self-owned files can't be deleted */
1560 if (baul_file_is_self_owned (file)) {
1561 return FALSE(0);
1562 }
1563
1564 return file->details->can_delete;
1565}
1566
1567gboolean
1568baul_file_can_trash (BaulFile *file)
1569{
1570 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
1571
1572 /* Nonexistent files can't be deleted. */
1573 if (baul_file_is_gone (file)) {
1574 return FALSE(0);
1575 }
1576
1577 /* Self-owned files can't be deleted */
1578 if (baul_file_is_self_owned (file)) {
1579 return FALSE(0);
1580 }
1581
1582 return file->details->can_trash;
1583}
1584
1585GFile *
1586baul_file_get_location (BaulFile *file)
1587{
1588 GFile *dir;
1589
1590 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
1591
1592 dir = file->details->directory->details->location;
1593
1594 if (baul_file_is_self_owned (file)) {
1595 return g_object_ref (dir)((__typeof__ (dir)) (g_object_ref) (dir));
1596 }
1597
1598 return g_file_get_child (dir, file->details->name);
1599}
1600
1601/* Return the actual uri associated with the passed-in file. */
1602char *
1603baul_file_get_uri (BaulFile *file)
1604{
1605 char *uri;
1606 GFile *loc;
1607
1608 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
1609
1610 loc = baul_file_get_location (file);
1611 uri = g_file_get_uri (loc);
1612 g_object_unref (loc);
1613
1614 return uri;
1615}
1616
1617char *
1618baul_file_get_uri_scheme (BaulFile *file)
1619{
1620 GFile *loc;
1621 char *scheme;
1622
1623 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
1624
1625 if (file->details->directory == NULL((void*)0) ||
1626 file->details->directory->details->location == NULL((void*)0)) {
1627 return NULL((void*)0);
1628 }
1629
1630 loc = baul_directory_get_location (file->details->directory);
1631 scheme = g_file_get_uri_scheme (loc);
1632 g_object_unref (loc);
1633
1634 return scheme;
1635}
1636
1637BaulFileOperation *
1638baul_file_operation_new (BaulFile *file,
1639 BaulFileOperationCallback callback,
1640 gpointer callback_data)
1641{
1642 BaulFileOperation *op;
1643
1644 op = g_new0 (BaulFileOperation, 1)((BaulFileOperation *) g_malloc0_n ((1), sizeof (BaulFileOperation
)))
;
1645 op->file = baul_file_ref (file);
1646 op->callback = callback;
1647 op->callback_data = callback_data;
1648 op->cancellable = g_cancellable_new ();
1649
1650 op->file->details->operations_in_progress = g_list_prepend
1651 (op->file->details->operations_in_progress, op);
1652
1653 return op;
1654}
1655
1656static void
1657baul_file_operation_remove (BaulFileOperation *op)
1658{
1659 op->file->details->operations_in_progress = g_list_remove
1660 (op->file->details->operations_in_progress, op);
1661}
1662
1663void
1664baul_file_operation_free (BaulFileOperation *op)
1665{
1666 baul_file_operation_remove (op);
1667 baul_file_unref (op->file);
1668 g_object_unref (op->cancellable);
1669 if (op->free_data) {
1670 op->free_data (op->data);
1671 }
1672 // Start UNDO-REDO
1673 baul_undostack_manager_add_action (baul_undostack_manager_instance(),
1674 op->undo_redo_data);
1675 // End UNDO-REDO
1676 g_free (op);
1677}
1678
1679void
1680baul_file_operation_complete (BaulFileOperation *op, GFile *result_file, GError *error)
1681{
1682 /* Claim that something changed even if the operation failed.
1683 * This makes it easier for some clients who see the "reverting"
1684 * as "changing back".
1685 */
1686 baul_file_operation_remove (op);
1687 baul_file_changed (op->file);
1688 if (op->callback) {
1689 (* op->callback) (op->file, result_file, error, op->callback_data);
1690 }
1691 baul_file_operation_free (op);
1692}
1693
1694void
1695baul_file_operation_cancel (BaulFileOperation *op)
1696{
1697 /* Cancel the operation if it's still in progress. */
1698 g_cancellable_cancel (op->cancellable);
1699}
1700
1701static void
1702rename_get_info_callback (GObject *source_object,
1703 GAsyncResult *res,
1704 gpointer callback_data)
1705{
1706 BaulFileOperation *op;
1707 GFileInfo *new_info;
1708 GError *error;
1709
1710 op = callback_data;
1711
1712 error = NULL((void*)0);
1713 new_info = g_file_query_info_finish (G_FILE (source_object)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_file_get_type ()))))))
, res, &error);
1714 if (new_info != NULL((void*)0)) {
1715 BaulDirectory *directory;
1716 BaulFile *existing_file;
1717 char *old_name;
1718 char *old_uri;
1719 char *new_uri;
1720 const char *new_name;
1721
1722 directory = op->file->details->directory;
1723
1724 new_name = g_file_info_get_name (new_info);
1725
1726 /* If there was another file by the same name in this
1727 * directory, mark it gone.
1728 */
1729 existing_file = baul_directory_find_file_by_name (directory, new_name);
1730 if (existing_file != NULL((void*)0)) {
1731 baul_file_mark_gone (existing_file);
1732 baul_file_changed (existing_file);
1733 }
1734
1735 old_uri = baul_file_get_uri (op->file);
1736 old_name = g_strdup (op->file->details->name)g_strdup_inline (op->file->details->name);
1737
1738 update_info_and_name (op->file, new_info);
1739
1740 g_free (old_name);
1741
1742 new_uri = baul_file_get_uri (op->file);
1743 baul_directory_moved (old_uri, new_uri);
1744 g_free (new_uri);
1745 g_free (old_uri);
1746
1747 /* the rename could have affected the display name if e.g.
1748 * we're in a vfolder where the name comes from a desktop file
1749 * and a rename affects the contents of the desktop file.
1750 */
1751 if (op->file->details->got_custom_display_name) {
1752 baul_file_invalidate_attributes (op->file,
1753 BAUL_FILE_ATTRIBUTE_INFO |
1754 BAUL_FILE_ATTRIBUTE_LINK_INFO);
1755 }
1756
1757 g_object_unref (new_info);
1758 }
1759 baul_file_operation_complete (op, NULL((void*)0), error);
1760 if (error) {
1761 g_error_free (error);
1762 }
1763}
1764
1765static void
1766rename_callback (GObject *source_object,
1767 GAsyncResult *res,
1768 gpointer callback_data)
1769{
1770 BaulFileOperation *op;
1771 GFile *new_file;
1772 GError *error;
1773
1774 op = callback_data;
1775
1776 error = NULL((void*)0);
1777 new_file = g_file_set_display_name_finish (G_FILE (source_object)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_file_get_type ()))))))
,
1778 res, &error);
1779
1780 if (new_file != NULL((void*)0)) {
1781 // Start UNDO-REDO
1782 baul_undostack_manager_data_set_rename_information(op->undo_redo_data, G_FILE (source_object)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_file_get_type ()))))))
, new_file);
1783 // End UNDO-REDO
1784 g_file_query_info_async (new_file,
1785 BAUL_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
1786 0,
1787 G_PRIORITY_DEFAULT0,
1788 op->cancellable,
1789 rename_get_info_callback, op);
1790 } else {
1791 baul_file_operation_complete (op, NULL((void*)0), error);
1792 g_error_free (error);
1793 }
1794}
1795
1796static gboolean
1797name_is (BaulFile *file, const char *new_name)
1798{
1799 const char *old_name;
1800 old_name = file->details->name;
1801 return strcmp (new_name, old_name) == 0;
1802}
1803
1804void
1805baul_file_rename (BaulFile *file,
1806 const char *new_name,
1807 BaulFileOperationCallback callback,
1808 gpointer callback_data)
1809{
1810 BaulFileOperation *op;
1811 char *old_name;
1812 char *new_file_name;
1813 gboolean success, name_changed;
1814 gboolean is_renameable_desktop_file;
1815 GFile *location;
1816 GError *error;
1817
1818 g_return_if_fail (BAUL_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return; } } while (0)
;
1819 g_return_if_fail (new_name != NULL)do { if ((new_name != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "new_name != NULL"
); return; } } while (0)
;
1820 g_return_if_fail (callback != NULL)do { if ((callback != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "callback != NULL"
); return; } } while (0)
;
1821
1822 is_renameable_desktop_file =
1823 is_desktop_file (file) && can_rename_desktop_file (file);
1824
1825 /* Return an error for incoming names containing path separators.
1826 * But not for .desktop files as '/' are allowed for them */
1827 if (strstr (new_name, "/") != NULL((void*)0) && !is_renameable_desktop_file) {
1828 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
1829 _("Slashes are not allowed in filenames")gettext ("Slashes are not allowed in filenames"));
1830 (* callback) (file, NULL((void*)0), error, callback_data);
1831 g_error_free (error);
1832 return;
1833 }
1834
1835 /* Can't rename a file that's already gone.
1836 * We need to check this here because there may be a new
1837 * file with the same name.
1838 */
1839 if (baul_file_is_gone (file)) {
1840 /* Claim that something changed even if the rename
1841 * failed. This makes it easier for some clients who
1842 * see the "reverting" to the old name as "changing
1843 * back".
1844 */
1845 baul_file_changed (file);
1846 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_FOUND,
1847 _("File not found")gettext ("File not found"));
1848 (* callback) (file, NULL((void*)0), error, callback_data);
1849 g_error_free (error);
1850 return;
1851 }
1852
1853 /* Test the name-hasn't-changed case explicitly, for two reasons.
1854 * (1) rename returns an error if new & old are same.
1855 * (2) We don't want to send file-changed signal if nothing changed.
1856 */
1857 if (!BAUL_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (baul_desktop_icon_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; }))))
&&
1858 !is_renameable_desktop_file &&
1859 name_is (file, new_name)) {
1860 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1861 return;
1862 }
1863
1864 /* Self-owned files can't be renamed. Test the name-not-actually-changing
1865 * case before this case.
1866 */
1867 if (baul_file_is_self_owned (file)) {
1868 /* Claim that something changed even if the rename
1869 * failed. This makes it easier for some clients who
1870 * see the "reverting" to the old name as "changing
1871 * back".
1872 */
1873 baul_file_changed (file);
1874 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1875 _("Toplevel files cannot be renamed")gettext ("Toplevel files cannot be renamed"));
1876
1877 (* callback) (file, NULL((void*)0), error, callback_data);
1878 g_error_free (error);
1879 return;
1880 }
1881
1882 if (BAUL_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (baul_desktop_icon_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; }))))
) {
1883 BaulDesktopLink *link;
1884
1885 link = baul_desktop_icon_file_get_link (BAUL_DESKTOP_ICON_FILE (file)((((BaulDesktopIconFile*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((file)), (baul_desktop_icon_file_get_type
())))))
);
1886 old_name = baul_file_get_display_name (file);
1887
1888 if ((old_name != NULL((void*)0) && strcmp (new_name, old_name) == 0)) {
1889 success = TRUE(!(0));
1890 } else {
1891 success = (link != NULL((void*)0) && baul_desktop_link_rename (link, new_name));
1892 }
1893
1894 if (success) {
1895 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1896 } else {
1897 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_FAILED,
1898 _("Unable to rename desktop icon")gettext ("Unable to rename desktop icon"));
1899 (* callback) (file, NULL((void*)0), error, callback_data);
1900 g_error_free (error);
1901 }
1902
1903 g_free (old_name);
1904 g_object_unref (link);
1905 return;
1906 }
1907
1908 if (is_renameable_desktop_file) {
1909 char *uri;
1910
1911 /* Don't actually change the name if the new name is the same.
1912 * This helps for the vfolder method where this can happen and
1913 * we want to minimize actual changes
1914 */
1915 uri = baul_file_get_uri (file);
1916 old_name = baul_link_local_get_text (uri);
1917 if (old_name != NULL((void*)0) && strcmp (new_name, old_name) == 0) {
1918 success = TRUE(!(0));
1919 name_changed = FALSE(0);
1920 } else {
1921 success = baul_link_local_set_text (uri, new_name);
1922 name_changed = TRUE(!(0));
1923 }
1924 g_free (old_name);
1925 g_free (uri);
1926
1927 if (!success) {
1928 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_FAILED,
1929 _("Unable to rename desktop file")gettext ("Unable to rename desktop file"));
1930 (* callback) (file, NULL((void*)0), error, callback_data);
1931 g_error_free (error);
1932 return;
1933 }
1934 new_file_name = g_strdup_printf ("%s.desktop", new_name);
1935 new_file_name = g_strdelimit (new_file_name, "/", '-');
1936
1937 if (name_is (file, new_file_name)) {
1938 if (name_changed) {
1939 baul_file_invalidate_attributes (file,
1940 BAUL_FILE_ATTRIBUTE_INFO |
1941 BAUL_FILE_ATTRIBUTE_LINK_INFO);
1942 }
1943
1944 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1945 g_free (new_file_name);
1946 return;
1947 }
1948 } else {
1949 new_file_name = g_strdup (new_name)g_strdup_inline (new_name);
1950 }
1951
1952 /* Set up a renaming operation. */
1953 op = baul_file_operation_new (file, callback, callback_data);
1954 op->is_rename = TRUE(!(0));
1955
1956 /* Do the renaming. */
1957
1958 location = baul_file_get_location (file);
1959
1960 // Start UNDO-REDO
1961 if (!baul_undostack_manager_is_undo_redo(baul_undostack_manager_instance())) {
1962 op->undo_redo_data = baul_undostack_manager_data_new (BAUL_UNDOSTACK_RENAME, 1);
1963 }
1964 // End UNDO-REDO
1965
1966 g_file_set_display_name_async (location,
1967 new_file_name,
1968 G_PRIORITY_DEFAULT0,
1969 op->cancellable,
1970 rename_callback,
1971 op);
1972 g_free (new_file_name);
1973 g_object_unref (location);
1974}
1975
1976gboolean
1977baul_file_rename_in_progress (BaulFile *file)
1978{
1979 GList *node;
1980 BaulFileOperation *op = NULL((void*)0);
1981
1982 for (node = file->details->operations_in_progress; node != NULL((void*)0); node = node->next) {
1983 op = node->data;
1984 if (op->is_rename) {
1985 return TRUE(!(0));
1986 }
1987 }
1988 return FALSE(0);
1989}
1990
1991void
1992baul_file_cancel (BaulFile *file,
1993 BaulFileOperationCallback callback,
1994 gpointer callback_data)
1995{
1996 GList *node, *next;
1997 BaulFileOperation *op = NULL((void*)0);
1998
1999 for (node = file->details->operations_in_progress; node != NULL((void*)0); node = next) {
2000 next = node->next;
2001 op = node->data;
2002
2003 g_assert (op->file == file)do { if (op->file == file) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 2003, ((const char*) (__func__
)), "op->file == file"); } while (0)
;
2004 if (op->callback == callback && op->callback_data == callback_data) {
2005 baul_file_operation_cancel (op);
2006 }
2007 }
2008}
2009
2010gboolean
2011baul_file_matches_uri (BaulFile *file, const char *match_uri)
2012{
2013 GFile *match_file, *location;
2014 gboolean result;
2015
2016 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
2017 g_return_val_if_fail (match_uri != NULL, FALSE)do { if ((match_uri != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "match_uri != NULL"
); return ((0)); } } while (0)
;
2018
2019 location = baul_file_get_location (file);
2020 match_file = g_file_new_for_uri (match_uri);
2021 result = g_file_equal (location, match_file);
2022 g_object_unref (location);
2023 g_object_unref (match_file);
2024
2025 return result;
2026}
2027
2028int
2029baul_file_compare_location (BaulFile *file_1,
2030 BaulFile *file_2)
2031{
2032 GFile *loc_a, *loc_b;
2033 gboolean res;
2034
2035 loc_a = baul_file_get_location (file_1);
2036 loc_b = baul_file_get_location (file_2);
2037
2038 res = !g_file_equal (loc_a, loc_b);
2039
2040 g_object_unref (loc_a);
2041 g_object_unref (loc_b);
2042
2043 return (gint) res;
2044}
2045
2046gboolean
2047baul_file_is_local (BaulFile *file)
2048{
2049 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
2050
2051 return baul_directory_is_local (file->details->directory);
2052}
2053
2054static void
2055update_link (BaulFile *link_file, BaulFile *target_file)
2056{
2057 g_assert (BAUL_IS_FILE (link_file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((link_file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 2057,
((const char*) (__func__)), "BAUL_IS_FILE (link_file)"); } while
(0)
;
2058 g_assert (BAUL_IS_FILE (target_file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((target_file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 2058,
((const char*) (__func__)), "BAUL_IS_FILE (target_file)"); }
while (0)
;
2059
2060 /* FIXME bugzilla.gnome.org 42044: If we don't put any code
2061 * here then the hash table is a waste of time.
2062 */
2063}
2064
2065static GList *
2066get_link_files (BaulFile *target_file)
2067{
2068 GList **link_files;
2069
2070 if (symbolic_links == NULL((void*)0)) {
2071 link_files = NULL((void*)0);
2072 } else {
2073 char *uri;
2074
2075 uri = baul_file_get_uri (target_file);
2076 link_files = g_hash_table_lookup (symbolic_links, uri);
2077 g_free (uri);
2078 }
2079 if (link_files) {
2080 return baul_file_list_copy (*link_files);
2081 }
2082 return NULL((void*)0);
2083}
2084
2085static void
2086update_links_if_target (BaulFile *target_file)
2087{
2088 GList *link_files, *p;
2089
2090 link_files = get_link_files (target_file);
2091 for (p = link_files; p != NULL((void*)0); p = p->next) {
2092 update_link (BAUL_FILE (p->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((p->data)), (baul_file_get_type())))))
, target_file);
2093 }
2094 baul_file_list_free (link_files);
2095}
2096
2097static gboolean
2098update_info_internal (BaulFile *file,
2099 GFileInfo *info,
2100 gboolean update_name)
2101{
2102 gboolean changed;
2103 gboolean is_symlink, is_hidden, is_backup, is_mountpoint;
2104 gboolean has_permissions;
2105 guint32 permissions;
2106 gboolean can_read, can_write, can_execute, can_delete, can_trash, can_rename, can_mount, can_unmount, can_eject;
2107 gboolean can_start, can_start_degraded, can_stop, can_poll_for_media, is_media_check_automatic;
2108 GDriveStartStopType start_stop_type;
2109 gboolean thumbnailing_failed;
2110 int uid, gid;
2111 goffset size;
2112 goffset size_on_disk;
2113 int sort_order;
2114 time_t atime, mtime, ctime;
2115 time_t trash_time;
2116 const char * time_string;
2117 const char *symlink_name, *mime_type, *selinux_context, *thumbnail_path;
2118 GFileType file_type;
2119 GIcon *icon;
2120 const char *description;
2121 const char *filesystem_id;
2122 const char *trash_orig_path;
2123 const char *group, *owner, *owner_real;
2124 gboolean free_owner, free_group;
2125
2126 if (file->details->is_gone) {
2127 return FALSE(0);
2128 }
2129
2130 if (info == NULL((void*)0)) {
2131 baul_file_mark_gone (file);
2132 return TRUE(!(0));
2133 }
2134
2135 file->details->file_info_is_up_to_date = TRUE(!(0));
2136
2137 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2138 * point to the old name know that the file has been renamed.
2139 */
2140
2141 remove_from_link_hash_table (file);
2142
2143 changed = FALSE(0);
2144
2145 if (!file->details->got_file_info) {
2146 changed = TRUE(!(0));
2147 }
2148 file->details->got_file_info = TRUE(!(0));
2149
2150 changed |= baul_file_set_display_name (file,
2151 g_file_info_get_display_name (info),
2152 g_file_info_get_edit_name (info),
2153 FALSE(0));
2154
2155 file_type = g_file_info_get_file_type (info);
2156 if (file->details->type != file_type) {
2157 changed = TRUE(!(0));
2158 }
2159 file->details->type = file_type;
2160
2161 if (!file->details->got_custom_activation_uri) {
2162 const char *activation_uri;
2163
2164 activation_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI"standard::target-uri");
2165 if (activation_uri == NULL((void*)0)) {
2166 if (file->details->activation_uri) {
2167 g_free (file->details->activation_uri);
2168 file->details->activation_uri = NULL((void*)0);
2169 changed = TRUE(!(0));
2170 }
2171 } else {
2172 char *old_activation_uri;
2173
2174 old_activation_uri = file->details->activation_uri;
2175 file->details->activation_uri = g_strdup (activation_uri)g_strdup_inline (activation_uri);
2176
2177 if (old_activation_uri) {
2178 if (strcmp (old_activation_uri,
2179 file->details->activation_uri) != 0) {
2180 changed = TRUE(!(0));
2181 }
2182 g_free (old_activation_uri);
2183 } else {
2184 changed = TRUE(!(0));
2185 }
2186 }
2187 }
2188
2189 is_symlink = g_file_info_get_is_symlink (info);
2190 if (file->details->is_symlink != is_symlink) {
2191 changed = TRUE(!(0));
2192 }
2193 file->details->is_symlink = is_symlink;
2194
2195 is_hidden = g_file_info_get_is_hidden (info);
2196 is_backup = g_file_info_get_is_backup (info);
2197 if (file->details->is_hidden != is_hidden ||
2198 file->details->is_backup != is_backup) {
2199 changed = TRUE(!(0));
2200 }
2201 file->details->is_hidden = is_hidden;
2202 file->details->is_backup = is_backup;
2203
2204 is_mountpoint = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT"unix::is-mountpoint");
2205 if (file->details->is_mountpoint != is_mountpoint) {
2206 changed = TRUE(!(0));
2207 }
2208 file->details->is_mountpoint = is_mountpoint;
2209
2210 has_permissions = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
2211 permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");;
2212 if (file->details->has_permissions != has_permissions ||
2213 file->details->permissions != permissions) {
2214 changed = TRUE(!(0));
2215 }
2216 file->details->has_permissions = has_permissions;
2217 file->details->permissions = permissions;
2218
2219 /* We default to TRUE for this if we can't know */
2220 can_read = TRUE(!(0));
2221 can_write = TRUE(!(0));
2222 can_execute = TRUE(!(0));
2223 can_delete = TRUE(!(0));
2224 can_trash = TRUE(!(0));
2225 can_rename = TRUE(!(0));
2226 can_mount = FALSE(0);
2227 can_unmount = FALSE(0);
2228 can_eject = FALSE(0);
2229 can_start = FALSE(0);
2230 can_start_degraded = FALSE(0);
2231 can_stop = FALSE(0);
2232 can_poll_for_media = FALSE(0);
2233 is_media_check_automatic = FALSE(0);
2234 start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
2235 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read")) {
2236 can_read = g_file_info_get_attribute_boolean (info,
2237 G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read");
2238 }
2239 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write")) {
2240 can_write = g_file_info_get_attribute_boolean (info,
2241 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write");
2242 }
2243 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute")) {
2244 can_execute = g_file_info_get_attribute_boolean (info,
2245 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute");
2246 }
2247 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete")) {
2248 can_delete = g_file_info_get_attribute_boolean (info,
2249 G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete");
2250 }
2251 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash")) {
2252 can_trash = g_file_info_get_attribute_boolean (info,
2253 G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash");
2254 }
2255 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename")) {
2256 can_rename = g_file_info_get_attribute_boolean (info,
2257 G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename");
2258 }
2259 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount")) {
2260 can_mount = g_file_info_get_attribute_boolean (info,
2261 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount");
2262 }
2263 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount")) {
2264 can_unmount = g_file_info_get_attribute_boolean (info,
2265 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount");
2266 }
2267 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject")) {
2268 can_eject = g_file_info_get_attribute_boolean (info,
2269 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject");
2270 }
2271 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start")) {
2272 can_start = g_file_info_get_attribute_boolean (info,
2273 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start");
2274 }
2275 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded")) {
2276 can_start_degraded = g_file_info_get_attribute_boolean (info,
2277 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded");
2278 }
2279 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop")) {
2280 can_stop = g_file_info_get_attribute_boolean (info,
2281 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop");
2282 }
2283 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type")) {
2284 start_stop_type = g_file_info_get_attribute_uint32 (info,
2285 G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type");
2286 }
2287 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll")) {
2288 can_poll_for_media = g_file_info_get_attribute_boolean (info,
2289 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll");
2290 }
2291 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic")) {
2292 is_media_check_automatic = g_file_info_get_attribute_boolean (info,
2293 G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic");
2294 }
2295 if (file->details->can_read != can_read ||
2296 file->details->can_write != can_write ||
2297 file->details->can_execute != can_execute ||
2298 file->details->can_delete != can_delete ||
2299 file->details->can_trash != can_trash ||
2300 file->details->can_rename != can_rename ||
2301 file->details->can_mount != can_mount ||
2302 file->details->can_unmount != can_unmount ||
2303 file->details->can_eject != can_eject ||
2304 file->details->can_start != can_start ||
2305 file->details->can_start_degraded != can_start_degraded ||
2306 file->details->can_stop != can_stop ||
2307 file->details->start_stop_type != start_stop_type ||
2308 file->details->can_poll_for_media != can_poll_for_media ||
2309 file->details->is_media_check_automatic != is_media_check_automatic) {
2310 changed = TRUE(!(0));
2311 }
2312
2313 file->details->can_read = can_read;
2314 file->details->can_write = can_write;
2315 file->details->can_execute = can_execute;
2316 file->details->can_delete = can_delete;
2317 file->details->can_trash = can_trash;
2318 file->details->can_rename = can_rename;
2319 file->details->can_mount = can_mount;
2320 file->details->can_unmount = can_unmount;
2321 file->details->can_eject = can_eject;
2322 file->details->can_start = can_start;
2323 file->details->can_start_degraded = can_start_degraded;
2324 file->details->can_stop = can_stop;
2325 file->details->start_stop_type = start_stop_type;
2326 file->details->can_poll_for_media = can_poll_for_media;
2327 file->details->is_media_check_automatic = is_media_check_automatic;
2328
2329 free_owner = FALSE(0);
2330 owner = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER"owner::user");
2331 owner_real = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER_REAL"owner::user-real");
2332 free_group = FALSE(0);
2333 group = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP"owner::group");
2334
2335 uid = -1;
2336 gid = -1;
2337 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid")) {
2338 uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid");
2339 if (owner == NULL((void*)0)) {
2340 free_owner = TRUE(!(0));
2341 owner = g_strdup_printf ("%d", uid);
2342 }
2343 }
2344 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid")) {
2345 gid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid");
2346 if (group == NULL((void*)0)) {
2347 free_group = TRUE(!(0));
2348 group = g_strdup_printf ("%d", gid);
2349 }
2350 }
2351 if (file->details->uid != uid ||
2352 file->details->gid != gid) {
2353 changed = TRUE(!(0));
2354 }
2355 file->details->uid = uid;
2356 file->details->gid = gid;
2357
2358 if (eel_strcmp (file->details->owner, owner) != 0) {
2359 changed = TRUE(!(0));
2360 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2361 file->details->owner = g_ref_string_new_intern (owner);
2362 }
2363
2364 if (eel_strcmp (file->details->owner_real, owner_real) != 0) {
2365 changed = TRUE(!(0));
2366 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
2367 file->details->owner_real = g_ref_string_new_intern (owner_real);
2368 }
2369
2370 if (eel_strcmp (file->details->group, group) != 0) {
2371 changed = TRUE(!(0));
2372 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2373 file->details->group = g_ref_string_new_intern (group);
2374 }
2375
2376 if (free_owner) {
2377 g_free ((char *)owner);
2378 }
2379 if (free_group) {
2380 g_free ((char *)group);
2381 }
2382
2383 size = -1;
2384 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size")) {
2385 size = g_file_info_get_size (info);
2386 }
2387 if (file->details->size != size) {
2388 changed = TRUE(!(0));
2389 }
2390 file->details->size = size;
2391
2392 size_on_disk = -1;
2393 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size")) {
2394 size_on_disk = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size");
2395 }
2396 if (file->details->size_on_disk != size_on_disk) {
2397 changed = TRUE(!(0));
2398 }
2399 file->details->size_on_disk = size_on_disk;
2400
2401 sort_order = g_file_info_get_attribute_int32 (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER"standard::sort-order");
2402
2403 if (file->details->sort_order != sort_order) {
2404 changed = TRUE(!(0));
2405 }
2406 file->details->sort_order = sort_order;
2407
2408 atime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS"time::access");
2409 ctime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED"time::changed");
2410 mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED"time::modified");
2411 if (file->details->atime != atime ||
2412 file->details->mtime != mtime ||
2413 file->details->ctime != ctime) {
2414 if (file->details->thumbnail == NULL((void*)0)) {
2415 file->details->thumbnail_is_up_to_date = FALSE(0);
2416 }
2417
2418 changed = TRUE(!(0));
2419 }
2420 file->details->atime = atime;
2421 file->details->ctime = ctime;
2422 file->details->mtime = mtime;
2423
2424 if (file->details->thumbnail != NULL((void*)0) &&
2425 file->details->thumbnail_mtime != 0 &&
2426 file->details->thumbnail_mtime != mtime) {
2427 file->details->thumbnail_is_up_to_date = FALSE(0);
2428 changed = TRUE(!(0));
2429 }
2430
2431 icon = g_file_info_get_icon (info);
2432 if (!g_icon_equal (icon, file->details->icon)) {
2433 changed = TRUE(!(0));
2434
2435 if (file->details->icon) {
2436 g_object_unref (file->details->icon);
2437 }
2438 file->details->icon = g_object_ref (icon)((__typeof__ (icon)) (g_object_ref) (icon));
2439 }
2440
2441 thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH"thumbnail::path");
2442 if (eel_strcmp (file->details->thumbnail_path, thumbnail_path) != 0) {
2443 changed = TRUE(!(0));
2444 g_free (file->details->thumbnail_path);
2445 file->details->thumbnail_path = g_strdup (thumbnail_path)g_strdup_inline (thumbnail_path);
2446 }
2447
2448 thumbnailing_failed = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED"thumbnail::failed");
2449 if (file->details->thumbnailing_failed != thumbnailing_failed) {
2450 changed = TRUE(!(0));
2451 file->details->thumbnailing_failed = thumbnailing_failed;
2452 }
2453
2454 symlink_name = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET"standard::symlink-target");
2455
2456 if (eel_strcmp (file->details->symlink_name, symlink_name) != 0) {
2457 changed = TRUE(!(0));
2458 g_free (file->details->symlink_name);
2459 file->details->symlink_name = g_strdup (symlink_name)g_strdup_inline (symlink_name);
2460 }
2461
2462 mime_type = g_file_info_get_content_type (info);
2463 if (eel_strcmp (file->details->mime_type, mime_type) != 0) {
2464 changed = TRUE(!(0));
2465 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
2466 file->details->mime_type = g_ref_string_new_intern (mime_type);
2467 }
2468
2469 selinux_context = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_SELINUX_CONTEXT"selinux::context");
2470 if (eel_strcmp (file->details->selinux_context, selinux_context) != 0) {
2471 changed = TRUE(!(0));
2472 g_free (file->details->selinux_context);
2473 file->details->selinux_context = g_strdup (selinux_context)g_strdup_inline (selinux_context);
2474 }
2475
2476 description = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION"standard::description");
2477 if (eel_strcmp (file->details->description, description) != 0) {
2478 changed = TRUE(!(0));
2479 g_free (file->details->description);
2480 file->details->description = g_strdup (description)g_strdup_inline (description);
2481 }
2482
2483 filesystem_id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem");
2484 if (eel_strcmp (file->details->filesystem_id, filesystem_id) != 0) {
2485 changed = TRUE(!(0));
2486 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
2487 file->details->filesystem_id = g_ref_string_new_intern (filesystem_id);
2488 }
2489
2490 trash_time = 0;
2491 time_string = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_TRASH_DELETION_DATE"trash::deletion-date");
2492 if (time_string != NULL((void*)0)) {
2493 GDateTime *dt;
2494 GTimeZone *tz;
2495 tz = g_time_zone_new_local ();
2496 dt = g_date_time_new_from_iso8601 (time_string, tz);
2497 if (dt) {
2498 trash_time = (time_t) g_date_time_to_unix (dt);
2499 g_date_time_unref (dt);
2500 }
2501 g_time_zone_unref (tz);
2502 }
2503 if (file->details->trash_time != trash_time) {
2504 changed = TRUE(!(0));
2505 file->details->trash_time = trash_time;
2506 }
2507
2508 trash_orig_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH"trash::orig-path");
2509 if (eel_strcmp (file->details->trash_orig_path, trash_orig_path) != 0) {
2510 changed = TRUE(!(0));
2511 g_free (file->details->trash_orig_path);
2512 file->details->trash_orig_path = g_strdup (trash_orig_path)g_strdup_inline (trash_orig_path);
2513 }
2514
2515 changed |=
2516 baul_file_update_metadata_from_info (file, info);
2517
2518 if (update_name) {
2519 const char *name;
2520
2521 name = g_file_info_get_name (info);
2522 if (file->details->name == NULL((void*)0) ||
2523 strcmp (file->details->name, name) != 0) {
2524 GList *node;
2525
2526 changed = TRUE(!(0));
2527
2528 node = baul_directory_begin_file_name_change
2529 (file->details->directory, file);
2530
2531 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2532 if (eel_strcmp (file->details->display_name, name) == 0) {
2533 file->details->name = g_ref_string_acquire (file->details->display_name);
2534 } else {
2535 file->details->name = g_ref_string_new (name);
2536 }
2537
2538 if (!file->details->got_custom_display_name &&
2539 g_file_info_get_display_name (info) == NULL((void*)0)) {
2540 /* If the file info's display name is NULL,
2541 * baul_file_set_display_name() did
2542 * not unset the display name.
2543 */
2544 baul_file_clear_display_name (file);
2545 }
2546
2547 baul_directory_end_file_name_change
2548 (file->details->directory, file, node);
2549 }
2550 }
2551
2552 if (changed) {
2553 add_to_link_hash_table (file);
2554
2555 update_links_if_target (file);
2556 }
2557
2558 return changed;
2559}
2560
2561static gboolean
2562update_info_and_name (BaulFile *file,
2563 GFileInfo *info)
2564{
2565 return update_info_internal (file, info, TRUE(!(0)));
2566}
2567
2568gboolean
2569baul_file_update_info (BaulFile *file,
2570 GFileInfo *info)
2571{
2572 return update_info_internal (file, info, FALSE(0));
2573}
2574
2575void
2576baul_file_refresh_info (BaulFile *file)
2577{
2578 GFile *gfile;
2579 GFileInfo *new_info;
2580
2581 gfile = baul_file_get_location (file);
2582 new_info = g_file_query_info (gfile, BAUL_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
2583 G_FILE_QUERY_INFO_NONE, NULL((void*)0), NULL((void*)0));
2584 if (new_info != NULL((void*)0)) {
2585 if (baul_file_update_info (file, new_info)) {
2586 baul_file_changed (file);
2587 }
2588 g_object_unref (new_info);
2589 }
2590 g_object_unref (gfile);
2591}
2592
2593static gboolean
2594update_name_internal (BaulFile *file,
2595 const char *name,
2596 gboolean in_directory)
2597{
2598 GList *node;
2599
2600 g_assert (name != NULL)do { if (name != ((void*)0)) ; else g_assertion_message_expr (
((gchar*) 0), "baul-file.c", 2600, ((const char*) (__func__))
, "name != NULL"); } while (0)
;
2601
2602 if (file->details->is_gone) {
2603 return FALSE(0);
2604 }
2605
2606 if (name_is (file, name)) {
2607 return FALSE(0);
2608 }
2609
2610 node = NULL((void*)0);
2611 if (in_directory) {
2612 node = baul_directory_begin_file_name_change
2613 (file->details->directory, file);
2614 }
2615
2616 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2617 file->details->name = g_ref_string_new (name);
2618
2619 if (!file->details->got_custom_display_name) {
2620 baul_file_clear_display_name (file);
2621 }
2622
2623 if (in_directory) {
2624 baul_directory_end_file_name_change
2625 (file->details->directory, file, node);
2626 }
2627
2628 return TRUE(!(0));
2629}
2630
2631gboolean
2632baul_file_update_name (BaulFile *file, const char *name)
2633{
2634 gboolean ret;
2635
2636 ret = update_name_internal (file, name, TRUE(!(0)));
2637
2638 if (ret) {
2639 update_links_if_target (file);
2640 }
2641
2642 return ret;
2643}
2644
2645gboolean
2646baul_file_update_name_and_directory (BaulFile *file,
2647 const char *name,
2648 BaulDirectory *new_directory)
2649{
2650 BaulDirectory *old_directory;
2651 FileMonitors *monitors;
2652
2653 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
2654 g_return_val_if_fail (BAUL_IS_DIRECTORY (file->details->directory), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file->details->directory)); GType __t = (baul_directory_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 (((gchar*) 0
), ((const char*) (__func__)), "BAUL_IS_DIRECTORY (file->details->directory)"
); return ((0)); } } while (0)
;
2655 g_return_val_if_fail (!file->details->is_gone, FALSE)do { if ((!file->details->is_gone)) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "!file->details->is_gone"
); return ((0)); } } while (0)
;
2656 g_return_val_if_fail (!baul_file_is_self_owned (file), FALSE)do { if ((!baul_file_is_self_owned (file))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "!baul_file_is_self_owned (file)"
); return ((0)); } } while (0)
;
2657 g_return_val_if_fail (BAUL_IS_DIRECTORY (new_directory), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((new_directory)); GType __t = (baul_directory_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 (((gchar*) 0), ((const
char*) (__func__)), "BAUL_IS_DIRECTORY (new_directory)"); return
((0)); } } while (0)
;
2658
2659 old_directory = file->details->directory;
2660 if (old_directory == new_directory) {
2661 if (name) {
2662 return update_name_internal (file, name, TRUE(!(0)));
2663 } else {
2664 return FALSE(0);
2665 }
2666 }
2667
2668 baul_file_ref (file);
2669
2670 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2671 * point to the old name know that the file has been moved.
2672 */
2673
2674 remove_from_link_hash_table (file);
2675
2676 monitors = baul_directory_remove_file_monitors (old_directory, file);
2677 baul_directory_remove_file (old_directory, file);
2678
2679 file->details->directory = baul_directory_ref (new_directory);
2680 baul_directory_unref (old_directory);
2681
2682 if (name) {
2683 update_name_internal (file, name, FALSE(0));
2684 }
2685
2686 baul_directory_add_file (new_directory, file);
2687 baul_directory_add_file_monitors (new_directory, file, monitors);
2688
2689 add_to_link_hash_table (file);
2690
2691 update_links_if_target (file);
2692
2693 baul_file_unref (file);
2694
2695 return TRUE(!(0));
2696}
2697
2698void
2699baul_file_set_directory (BaulFile *file,
2700 BaulDirectory *new_directory)
2701{
2702 baul_file_update_name_and_directory (file, NULL((void*)0), new_directory);
2703}
2704
2705static Knowledge
2706get_item_count (BaulFile *file,
2707 guint *count)
2708{
2709 gboolean known, unreadable;
2710
2711 known = baul_file_get_directory_item_count
2712 (file, count, &unreadable);
2713 if (!known) {
2714 return UNKNOWN;
2715 }
2716 if (unreadable) {
2717 return UNKNOWABLE;
2718 }
2719 return KNOWN;
2720}
2721
2722static Knowledge
2723get_size (BaulFile *file,
2724 goffset *size,
2725 gboolean size_on_disk)
2726{
2727 /* If we tried and failed, then treat it like there is no size
2728 * to know.
2729 */
2730 if (file->details->get_info_failed) {
2731 return UNKNOWABLE;
2732 }
2733
2734 /* If the info is NULL that means we haven't even tried yet,
2735 * so it's just unknown, not unknowable.
2736 */
2737 if (!file->details->got_file_info) {
2738 return UNKNOWN;
2739 }
2740
2741 /* If we got info with no size in it, it means there is no
2742 * such thing as a size as far as cafe-vfs is concerned,
2743 * so "unknowable".
2744 */
2745 if (size_on_disk && file->details->size_on_disk == -1) {
2746 return UNKNOWABLE;
2747 }
2748
2749 if (!size_on_disk && file->details->size == -1) {
2750 return UNKNOWABLE;
2751 }
2752
2753 /* We have a size! */
2754 if (size_on_disk) {
2755 *size = file->details->size_on_disk;
2756 } else {
2757 *size = file->details->size;
2758 }
2759
2760 return KNOWN;
2761}
2762
2763static Knowledge
2764get_time (BaulFile *file,
2765 time_t *time_out,
2766 BaulDateType type)
2767{
2768 time_t time;
2769
2770 /* If we tried and failed, then treat it like there is no size
2771 * to know.
2772 */
2773 if (file->details->get_info_failed) {
2774 return UNKNOWABLE;
2775 }
2776
2777 /* If the info is NULL that means we haven't even tried yet,
2778 * so it's just unknown, not unknowable.
2779 */
2780 if (!file->details->got_file_info) {
2781 return UNKNOWN;
2782 }
2783
2784 time = 0;
2785 switch (type) {
2786 case BAUL_DATE_TYPE_MODIFIED:
2787 time = file->details->mtime;
2788 break;
2789 case BAUL_DATE_TYPE_ACCESSED:
2790 time = file->details->atime;
2791 break;
2792 case BAUL_DATE_TYPE_TRASHED:
2793 time = file->details->trash_time;
2794 break;
2795 default:
2796 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "baul-file.c", 2796
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2797 break;
2798 }
2799
2800 *time_out = time;
2801
2802 /* If we got info with no modification time in it, it means
2803 * there is no such thing as a modification time as far as
2804 * cafe-vfs is concerned, so "unknowable".
2805 */
2806 if (time == 0) {
2807 return UNKNOWABLE;
2808 }
2809 return KNOWN;
2810}
2811
2812static int
2813compare_directories_by_count (BaulFile *file_1, BaulFile *file_2)
2814{
2815 /* Sort order:
2816 * Directories with unknown # of items
2817 * Directories with "unknowable" # of items
2818 * Directories with 0 items
2819 * Directories with n items
2820 */
2821
2822 Knowledge count_known_1, count_known_2;
2823 guint count_1, count_2;
2824
2825 count_known_1 = get_item_count (file_1, &count_1);
2826 count_known_2 = get_item_count (file_2, &count_2);
2827
2828 if (count_known_1 > count_known_2) {
2829 return -1;
2830 }
2831 if (count_known_1 < count_known_2) {
2832 return +1;
2833 }
2834
2835 /* count_known_1 and count_known_2 are equal now. Check if count
2836 * details are UNKNOWABLE or UNKNOWN.
2837 */
2838 if (count_known_1 == UNKNOWABLE || count_known_1 == UNKNOWN) {
2839 return 0;
2840 }
2841
2842 if (count_1 < count_2) {
2843 return -1;
2844 }
2845 if (count_1 > count_2) {
2846 return +1;
2847 }
2848
2849 return 0;
2850}
2851
2852static int
2853compare_files_by_size (BaulFile *file_1, BaulFile *file_2, gboolean size_on_disk)
2854{
2855 /* Sort order:
2856 * Files with unknown size.
2857 * Files with "unknowable" size.
2858 * Files with smaller sizes.
2859 * Files with large sizes.
2860 */
2861
2862 Knowledge size_known_1, size_known_2;
2863 goffset size_1 = 0, size_2 = 0;
2864
2865 size_known_1 = get_size (file_1, &size_1, size_on_disk);
2866 size_known_2 = get_size (file_2, &size_2, size_on_disk);
2867
2868 if (size_known_1 > size_known_2) {
2869 return -1;
2870 }
2871 if (size_known_1 < size_known_2) {
2872 return +1;
2873 }
2874
2875 /* size_known_1 and size_known_2 are equal now. Check if size
2876 * details are UNKNOWABLE or UNKNOWN
2877 */
2878 if (size_known_1 == UNKNOWABLE || size_known_1 == UNKNOWN) {
2879 return 0;
2880 }
2881
2882 if (size_1 < size_2) {
2883 return -1;
2884 }
2885 if (size_1 > size_2) {
2886 return +1;
2887 }
2888
2889 return 0;
2890}
2891
2892static int
2893compare_by_size (BaulFile *file_1, BaulFile *file_2, gboolean size_on_disk)
2894{
2895 /* Sort order:
2896 * Directories with n items
2897 * Directories with 0 items
2898 * Directories with "unknowable" # of items
2899 * Directories with unknown # of items
2900 * Files with large sizes.
2901 * Files with smaller sizes.
2902 * Files with "unknowable" size.
2903 * Files with unknown size.
2904 */
2905
2906 gboolean is_directory_1, is_directory_2;
2907
2908 is_directory_1 = baul_file_is_directory (file_1);
2909 is_directory_2 = baul_file_is_directory (file_2);
2910
2911 if (is_directory_1 && !is_directory_2) {
2912 return -1;
2913 }
2914 if (is_directory_2 && !is_directory_1) {
2915 return +1;
2916 }
2917
2918 if (is_directory_1) {
2919 return compare_directories_by_count (file_1, file_2);
2920 } else {
2921 return compare_files_by_size (file_1, file_2, size_on_disk);
2922 }
2923}
2924
2925static int
2926compare_by_display_name (BaulFile *file_1, BaulFile *file_2)
2927{
2928 const char *name_1, *name_2;
2929 const char *key_1, *key_2;
2930 gboolean sort_last_1, sort_last_2;
2931 int compare;
2932
2933 name_1 = baul_file_peek_display_name (file_1);
2934 name_2 = baul_file_peek_display_name (file_2);
2935
2936 sort_last_1 = name_1[0] == SORT_LAST_CHAR1'.' || name_1[0] == SORT_LAST_CHAR2'#';
2937 sort_last_2 = name_2[0] == SORT_LAST_CHAR1'.' || name_2[0] == SORT_LAST_CHAR2'#';
2938
2939 if (sort_last_1 && !sort_last_2) {
2940 compare = +1;
2941 } else if (!sort_last_1 && sort_last_2) {
2942 compare = -1;
2943 } else {
2944 key_1 = baul_file_peek_display_name_collation_key (file_1);
2945 key_2 = baul_file_peek_display_name_collation_key (file_2);
2946 compare = strcmp (key_1, key_2);
2947 }
2948
2949 return compare;
2950}
2951
2952static int
2953compare_by_directory_name (BaulFile *file_1, BaulFile *file_2)
2954{
2955 char *directory_1, *directory_2;
2956 int compare;
2957
2958 if (file_1->details->directory == file_2->details->directory) {
2959 return 0;
2960 }
2961
2962 directory_1 = baul_file_get_parent_uri_for_display (file_1);
2963 directory_2 = baul_file_get_parent_uri_for_display (file_2);
2964
2965 compare = g_utf8_collate (directory_1, directory_2);
2966
2967 g_free (directory_1);
2968 g_free (directory_2);
2969
2970 return compare;
2971}
2972
2973static gboolean
2974file_has_note (BaulFile *file)
2975{
2976 char *note;
2977 gboolean res;
2978
2979 note = baul_file_get_metadata (file, BAUL_METADATA_KEY_ANNOTATION"annotation", NULL((void*)0));
2980 res = note != NULL((void*)0) && note[0] != 0;
2981 g_free (note);
2982
2983 return res;
2984}
2985
2986static GList *
2987prepend_automatic_keywords (BaulFile *file,
2988 GList *names)
2989{
2990 /* Prepend in reverse order. */
2991 BaulFile *parent;
2992
2993 parent = baul_file_get_parent (file);
2994
2995#ifdef TRASH_IS_FAST_ENOUGH
2996 if (baul_file_is_in_trash (file)) {
2997 names = g_list_prepend
2998 (names, g_strdup (BAUL_FILE_EMBLEM_NAME_TRASH)g_strdup_inline ("trash"));
2999 }
3000#endif
3001 if (file_has_note (file)) {
3002 names = g_list_prepend
3003 (names, g_strdup (BAUL_FILE_EMBLEM_NAME_NOTE)g_strdup_inline ("note"));
3004 }
3005
3006 /* Trash files are assumed to be read-only,
3007 * so we want to ignore them here. */
3008 if (!baul_file_can_write (file) &&
3009 !baul_file_is_in_trash (file) &&
3010 (parent == NULL((void*)0) || baul_file_can_write (parent))) {
3011 names = g_list_prepend
3012 (names, g_strdup (BAUL_FILE_EMBLEM_NAME_CANT_WRITE)g_strdup_inline ("nowrite"));
3013 }
3014 if (!baul_file_can_read (file)) {
3015 names = g_list_prepend
3016 (names, g_strdup (BAUL_FILE_EMBLEM_NAME_CANT_READ)g_strdup_inline ("noread"));
3017 }
3018 if (baul_file_is_symbolic_link (file)) {
3019 names = g_list_prepend
3020 (names, g_strdup (BAUL_FILE_EMBLEM_NAME_SYMBOLIC_LINK)g_strdup_inline ("symbolic-link"));
3021 }
3022
3023 if (parent) {
3024 baul_file_unref (parent);
3025 }
3026
3027
3028 return names;
3029}
3030
3031static void
3032fill_emblem_cache_if_needed (BaulFile *file)
3033{
3034 GList *node, *keywords;
3035 char *scanner;
3036 size_t length;
3037
3038 if (file->details->compare_by_emblem_cache != NULL((void*)0)) {
3039 /* Got a cache already. */
3040 return;
3041 }
3042
3043 keywords = baul_file_get_keywords (file);
3044
3045 /* Add up the keyword string lengths */
3046 length = 1;
3047 for (node = keywords; node != NULL((void*)0); node = node->next) {
3048 length += strlen ((const char *) node->data) + 1;
3049 }
3050
3051 /* Now that we know how large the cache struct needs to be, allocate it. */
3052 file->details->compare_by_emblem_cache = g_malloc (sizeof(BaulFileSortByEmblemCache) + length);
3053
3054 /* Copy them into the cache. */
3055 scanner = file->details->compare_by_emblem_cache->emblem_keywords;
3056 for (node = keywords; node != NULL((void*)0); node = node->next) {
3057 length = strlen ((const char *) node->data) + 1;
3058 memcpy (scanner, (const char *) node->data, length);
3059 scanner += length;
3060 }
3061
3062 /* Zero-terminate so we can tell where the list ends. */
3063 *scanner = 0;
3064
3065 g_list_free_full (keywords, g_free);
3066}
3067
3068static int
3069compare_by_emblems (BaulFile *file_1, BaulFile *file_2)
3070{
3071 const char *keyword_cache_1, *keyword_cache_2;
3072 int compare_result;
3073
3074 fill_emblem_cache_if_needed (file_1);
3075 fill_emblem_cache_if_needed (file_2);
3076
3077 /* We ignore automatic emblems, and only sort by user-added keywords. */
3078 compare_result = 0;
3079 keyword_cache_1 = file_1->details->compare_by_emblem_cache->emblem_keywords;
3080 keyword_cache_2 = file_2->details->compare_by_emblem_cache->emblem_keywords;
3081 for (; *keyword_cache_1 != '\0' && *keyword_cache_2 != '\0';) {
3082 size_t length;
3083
3084 compare_result = g_utf8_collate (keyword_cache_1, keyword_cache_2);
3085 if (compare_result != 0) {
3086 return compare_result;
3087 }
3088
3089 /* Advance to the next keyword */
3090 length = strlen (keyword_cache_1);
3091 keyword_cache_1 += length + 1;
3092 keyword_cache_2 += length + 1;
3093 }
3094
3095
3096 /* One or both is now NULL. */
3097 if (*keyword_cache_1 != '\0') {
3098 g_assert (*keyword_cache_2 == '\0')do { if (*keyword_cache_2 == '\0') ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 3098, ((const char*) (__func__
)), "*keyword_cache_2 == '\\0'"); } while (0)
;
3099 return -1;
3100 } else if (*keyword_cache_2 != '\0') {
3101 return +1;
3102 }
3103
3104 return 0;
3105}
3106
3107static int
3108compare_by_type (BaulFile *file_1, BaulFile *file_2)
3109{
3110 gboolean is_directory_1;
3111 gboolean is_directory_2;
3112 char *type_string_1;
3113 char *type_string_2;
3114 int result;
3115
3116 /* Directories go first. Then, if mime types are identical,
3117 * don't bother getting strings (for speed). This assumes
3118 * that the string is dependent entirely on the mime type,
3119 * which is true now but might not be later.
3120 */
3121 is_directory_1 = baul_file_is_directory (file_1);
3122 is_directory_2 = baul_file_is_directory (file_2);
3123
3124 if (is_directory_1 && is_directory_2) {
3125 return 0;
3126 }
3127
3128 if (is_directory_1) {
3129 return -1;
3130 }
3131
3132 if (is_directory_2) {
3133 return +1;
3134 }
3135
3136 if (file_1->details->mime_type != NULL((void*)0) &&
3137 file_2->details->mime_type != NULL((void*)0) &&
3138 strcmp (file_1->details->mime_type,
3139 file_2->details->mime_type) == 0) {
3140 return 0;
3141 }
3142
3143 type_string_1 = baul_file_get_type_as_string (file_1);
3144 type_string_2 = baul_file_get_type_as_string (file_2);
3145
3146 result = g_utf8_collate (type_string_1, type_string_2);
3147
3148 g_free (type_string_1);
3149 g_free (type_string_2);
3150
3151 return result;
3152}
3153
3154static int
3155compare_by_time (BaulFile *file_1, BaulFile *file_2, BaulDateType type)
3156{
3157 /* Sort order:
3158 * Files with unknown times.
3159 * Files with "unknowable" times.
3160 * Files with older times.
3161 * Files with newer times.
3162 */
3163
3164 Knowledge time_known_1, time_known_2;
3165 time_t time_1, time_2;
3166
3167 time_1 = 0;
3168 time_2 = 0;
3169
3170 time_known_1 = get_time (file_1, &time_1, type);
3171 time_known_2 = get_time (file_2, &time_2, type);
3172
3173 if (time_known_1 > time_known_2) {
3174 return -1;
3175 }
3176 if (time_known_1 < time_known_2) {
3177 return +1;
3178 }
3179
3180 /* Now time_known_1 is equal to time_known_2. Check whether
3181 * we failed to get modification times for files
3182 */
3183 if(time_known_1 == UNKNOWABLE || time_known_1 == UNKNOWN) {
3184 return 0;
3185 }
3186
3187 if (time_1 < time_2) {
3188 return -1;
3189 }
3190 if (time_1 > time_2) {
3191 return +1;
3192 }
3193
3194 return 0;
3195}
3196
3197static int
3198compare_by_full_path (BaulFile *file_1, BaulFile *file_2)
3199{
3200 int compare;
3201
3202 compare = compare_by_directory_name (file_1, file_2);
3203 if (compare != 0) {
3204 return compare;
3205 }
3206 return compare_by_display_name (file_1, file_2);
3207}
3208
3209/* prev_extension_segment:
3210 * @basename The basename of a file
3211 * @rem_chars A pointer to the amount of remaining characters
3212 *
3213 * Finds the next segment delimiter to the left. A starting character of '.' is
3214 * set to '\0'.
3215 *
3216 * Return value: The start of the previous segment (right of the dot) or
3217 * basename if there are none remaining.
3218 */
3219static char *
3220prev_extension_segment (char *basename, int *rem_chars)
3221{
3222 if (*basename == '.') {
3223 *basename = 0;
3224 basename--;
3225 (*rem_chars)--;
3226 }
3227
3228 while (*rem_chars > 0 && *basename != '.') {
3229 (*rem_chars)--;
3230 basename--;
3231 }
3232
3233 return basename + 1;
3234}
3235
3236/* is_valid_extension_segment:
3237 * @segment Part of a modifiable zero-terminated string
3238 * @segment_index The index of the current segment
3239 *
3240 * Uses a heuristic to identify valid file extensions.
3241 *
3242 * Return value: Whether the segment is part of the file extension.
3243 */
3244static gboolean
3245is_valid_extension_segment (const char *segment, int segment_index)
3246{
3247 gboolean result;
3248 gboolean has_letters;
3249 int char_offset;
3250 switch (segment_index) {
3251 case 0:
3252 /* extremely long segments are probably not part of the extension */
3253 result = strlen (segment) < 20;
3254 break;
3255 default:
3256 has_letters = FALSE(0);
3257 char_offset = 0;
3258 while (TRUE(!(0))) {
3259 char c;
3260
3261 c = *(segment + char_offset);
3262 if (c == '\0') {
3263 result = has_letters;
3264 break;
3265 }
3266 /* allow digits if there are also letters */
3267 else if (isalpha (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISalpha
)
) {
3268 has_letters = TRUE(!(0));
3269 }
3270 /* fail if it is neither digit nor letter */
3271 else if (!isdigit (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISdigit
)
) {
3272 result = FALSE(0);
3273 break;
3274 }
3275
3276 if (char_offset >= SORT_BY_EXTENSION_FOLLOWING_MAX_LENGTH3) {
3277 result = FALSE(0);
3278 break;
3279 }
3280 char_offset++;
3281 }
3282 }
3283 return result;
3284}
3285
3286static int
3287compare_by_extension_segments (BaulFile *file_1, BaulFile *file_2)
3288{
3289 char *name_1, *name_2;
3290 char *segment_1, *segment_2;
3291 int compare;
3292 int rem_chars_1, rem_chars_2;
3293 gboolean done_1, done_2;
3294 gboolean is_directory_1, is_directory_2;
3295 int segment_index;
3296
3297
3298 /* Directories do not have an extension */
3299 is_directory_1 = baul_file_is_directory (file_1);
3300 is_directory_2 = baul_file_is_directory (file_2);
3301
3302 if (is_directory_1 && is_directory_2) {
3303 return 0;
3304 } else if (is_directory_1) {
3305 return -1;
3306 } else if (is_directory_2) {
3307 return 1;
3308 }
3309
3310 name_1 = baul_file_get_display_name (file_1);
3311 name_2 = baul_file_get_display_name (file_2);
3312 rem_chars_1 = strlen (name_1);
3313 rem_chars_2 = strlen (name_2);
3314
3315 /* Point to one after the zero character */
3316 segment_1 = name_1 + rem_chars_1 + 1;
3317 segment_2 = name_2 + rem_chars_2 + 1;
3318
3319 segment_index = 0;
3320 do {
3321 segment_1 = prev_extension_segment (segment_1 - 1, &rem_chars_1);
3322 segment_2 = prev_extension_segment (segment_2 - 1, &rem_chars_2);
3323
3324 done_1 = rem_chars_1 <= 0 || !is_valid_extension_segment (segment_1, segment_index);
3325 done_2 = rem_chars_2 <= 0 || !is_valid_extension_segment (segment_2, segment_index);
3326 if (done_1 && !done_2) {
3327 compare = -1;
3328 break;
3329 }
3330 else if (!done_1 && done_2) {
3331 compare = 1;
3332 break;
3333 }
3334 else if (done_1 && done_2) {
3335 compare = 0;
3336 break;
3337 }
3338
3339 segment_index++;
3340 if (segment_index > SORT_BY_EXTENSION_MAX_SEGMENTS3 - 1) {
3341 break;
3342 }
3343 compare = strcmp (segment_1, segment_2);
3344 } while (compare == 0);
3345
3346 g_free (name_1);
3347 g_free (name_2);
3348
3349 return compare;
3350}
3351
3352static gchar *
3353baul_file_get_extension_as_string (BaulFile *file)
3354{
3355 int rem_chars;
3356 char *segment;
3357
3358 if (!baul_file_is_directory (file)) {
3359 char *name;
3360
3361 name = baul_file_get_display_name (file);
3362 rem_chars = strlen (name);
3363 segment = prev_extension_segment (name + rem_chars, &rem_chars);
3364
3365 if (rem_chars > 0 && is_valid_extension_segment (segment, 0)) {
3366 int segment_index;
3367 char *right_segment;
3368 char *result;
3369
3370 segment_index = 1;
3371 do {
3372 right_segment = segment;
3373 segment = prev_extension_segment (segment - 1, &rem_chars);
3374 if (rem_chars > 0 && is_valid_extension_segment (segment, segment_index)) {
3375 /* remove zero-termination of segment */
3376 *(right_segment - 1) = '.';
3377 }
3378 else {
3379 break;
3380 }
3381
3382 segment_index++;
3383 } while (segment_index < SORT_BY_EXTENSION_MAX_SEGMENTS3 + 1);
3384 result = g_strdup (right_segment)g_strdup_inline (right_segment);
3385 g_free (name);
3386 return result;
3387 }
3388 g_free (name);
3389 }
3390 return g_strdup ("")g_strdup_inline ("");
3391}
3392
3393static int
3394baul_file_compare_for_sort_internal (BaulFile *file_1,
3395 BaulFile *file_2,
3396 gboolean directories_first,
3397 gboolean reversed)
3398{
3399 gboolean is_directory_1, is_directory_2;
3400
3401 if (directories_first) {
3402 is_directory_1 = baul_file_is_directory (file_1);
3403 is_directory_2 = baul_file_is_directory (file_2);
3404
3405 if (is_directory_1 && !is_directory_2) {
3406 return -1;
3407 }
3408
3409 if (is_directory_2 && !is_directory_1) {
3410 return +1;
3411 }
3412 }
3413
3414 if (file_1->details->sort_order < file_2->details->sort_order) {
3415 return reversed ? 1 : -1;
3416 } else if (file_1->details->sort_order > file_2->details->sort_order) {
3417 return reversed ? -1 : 1;
3418 }
3419
3420 return 0;
3421}
3422
3423/**
3424 * baul_file_compare_for_sort:
3425 * @file_1: A file object
3426 * @file_2: Another file object
3427 * @sort_type: Sort criterion
3428 * @directories_first: Put all directories before any non-directories
3429 * @reversed: Reverse the order of the items, except that
3430 * the directories_first flag is still respected.
3431 *
3432 * Return value: int < 0 if @file_1 should come before file_2 in a
3433 * sorted list; int > 0 if @file_2 should come before file_1 in a
3434 * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
3435 * that each named sort type may actually break ties several ways, with the name
3436 * of the sort criterion being the primary but not only differentiator.
3437 **/
3438int
3439baul_file_compare_for_sort (BaulFile *file_1,
3440 BaulFile *file_2,
3441 BaulFileSortType sort_type,
3442 gboolean directories_first,
3443 gboolean reversed)
3444{
3445 int result;
3446
3447 if (file_1 == file_2) {
3448 return 0;
3449 }
3450
3451 result = baul_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3452
3453 if (result == 0) {
3454 switch (sort_type) {
3455 case BAUL_FILE_SORT_BY_DISPLAY_NAME:
3456 result = compare_by_display_name (file_1, file_2);
3457 if (result == 0) {
3458 result = compare_by_directory_name (file_1, file_2);
3459 }
3460 break;
3461 case BAUL_FILE_SORT_BY_DIRECTORY:
3462 result = compare_by_full_path (file_1, file_2);
3463 break;
3464 case BAUL_FILE_SORT_BY_SIZE:
3465 /* Compare directory sizes ourselves, then if necessary
3466 * use CafeVFS to compare file sizes.
3467 */
3468 result = compare_by_size (file_1, file_2, FALSE(0));
3469 if (result == 0) {
3470 result = compare_by_full_path (file_1, file_2);
3471 }
3472 break;
3473 case BAUL_FILE_SORT_BY_SIZE_ON_DISK:
3474 /* Compare directory sizes ourselves, then if necessary
3475 * use CafeVFS to compare file sizes.
3476 */
3477 result = compare_by_size (file_1, file_2, TRUE(!(0)));
3478 if (result == 0) {
3479 result = compare_by_full_path (file_1, file_2);
3480 }
3481 break;
3482 case BAUL_FILE_SORT_BY_TYPE:
3483 /* CafeVFS doesn't know about our special text for certain
3484 * mime types, so we handle the mime-type sorting ourselves.
3485 */
3486 result = compare_by_type (file_1, file_2);
3487 if (result == 0) {
3488 result = compare_by_full_path (file_1, file_2);
3489 }
3490 break;
3491 case BAUL_FILE_SORT_BY_MTIME:
3492 result = compare_by_time (file_1, file_2, BAUL_DATE_TYPE_MODIFIED);
3493 if (result == 0) {
3494 result = compare_by_full_path (file_1, file_2);
3495 }
3496 break;
3497 case BAUL_FILE_SORT_BY_ATIME:
3498 result = compare_by_time (file_1, file_2, BAUL_DATE_TYPE_ACCESSED);
3499 if (result == 0) {
3500 result = compare_by_full_path (file_1, file_2);
3501 }
3502 break;
3503 case BAUL_FILE_SORT_BY_TRASHED_TIME:
3504 result = compare_by_time (file_1, file_2, BAUL_DATE_TYPE_TRASHED);
3505 if (result == 0) {
3506 result = compare_by_full_path (file_1, file_2);
3507 }
3508 break;
3509 case BAUL_FILE_SORT_BY_EMBLEMS:
3510 /* CafeVFS doesn't know squat about our emblems, so
3511 * we handle comparing them here, before falling back
3512 * to tie-breakers.
3513 */
3514 result = compare_by_emblems (file_1, file_2);
3515 if (result == 0) {
3516 result = compare_by_full_path (file_1, file_2);
3517 }
3518 break;
3519 case BAUL_FILE_SORT_BY_EXTENSION:
3520 result = compare_by_extension_segments (file_1, file_2);
3521 if (result == 0) {
3522 result = compare_by_full_path (file_1, file_2);
3523 }
3524 break;
3525 default:
3526 g_return_val_if_reached (0)do { g_log (((gchar*) 0), G_LOG_LEVEL_CRITICAL, "file %s: line %d (%s): should not be reached"
, "baul-file.c", 3526, ((const char*) (__func__))); return (0
); } while (0)
;
3527 }
3528
3529 if (reversed) {
3530 result = -result;
3531 }
3532 }
3533
3534 return result;
3535}
3536
3537int
3538baul_file_compare_for_sort_by_attribute_q (BaulFile *file_1,
3539 BaulFile *file_2,
3540 GQuark attribute,
3541 gboolean directories_first,
3542 gboolean reversed)
3543{
3544 int result;
3545
3546 if (file_1 == file_2) {
3547 return 0;
3548 }
3549
3550 /* Convert certain attributes into BaulFileSortTypes and use
3551 * baul_file_compare_for_sort()
3552 */
3553 if (attribute == 0 || attribute == attribute_name_q) {
3554 return baul_file_compare_for_sort (file_1, file_2,
3555 BAUL_FILE_SORT_BY_DISPLAY_NAME,
3556 directories_first,
3557 reversed);
3558 } else if (attribute == attribute_size_q) {
3559 return baul_file_compare_for_sort (file_1, file_2,
3560 BAUL_FILE_SORT_BY_SIZE,
3561 directories_first,
3562 reversed);
3563 } else if (attribute == attribute_size_on_disk_q) {
3564 return baul_file_compare_for_sort (file_1, file_2,
3565 BAUL_FILE_SORT_BY_SIZE_ON_DISK,
3566 directories_first,
3567 reversed);
3568 } else if (attribute == attribute_type_q) {
3569 return baul_file_compare_for_sort (file_1, file_2,
3570 BAUL_FILE_SORT_BY_TYPE,
3571 directories_first,
3572 reversed);
3573 } else if (attribute == attribute_modification_date_q || attribute == attribute_date_modified_q) {
3574 return baul_file_compare_for_sort (file_1, file_2,
3575 BAUL_FILE_SORT_BY_MTIME,
3576 directories_first,
3577 reversed);
3578 } else if (attribute == attribute_accessed_date_q || attribute == attribute_date_accessed_q) {
3579 return baul_file_compare_for_sort (file_1, file_2,
3580 BAUL_FILE_SORT_BY_ATIME,
3581 directories_first,
3582 reversed);
3583 } else if (attribute == attribute_trashed_on_q) {
3584 return baul_file_compare_for_sort (file_1, file_2,
3585 BAUL_FILE_SORT_BY_TRASHED_TIME,
3586 directories_first,
3587 reversed);
3588 } else if (attribute == attribute_emblems_q) {
3589 return baul_file_compare_for_sort (file_1, file_2,
3590 BAUL_FILE_SORT_BY_EMBLEMS,
3591 directories_first,
3592 reversed);
3593 } else if (attribute == attribute_extension_q) {
3594 return baul_file_compare_for_sort (file_1, file_2,
3595 BAUL_FILE_SORT_BY_EXTENSION,
3596 directories_first,
3597 reversed);
3598 }
3599
3600 /* it is a normal attribute, compare by strings */
3601
3602 result = baul_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3603
3604 if (result == 0) {
3605 char *value_1;
3606 char *value_2;
3607
3608 value_1 = baul_file_get_string_attribute_q (file_1,
3609 attribute);
3610 value_2 = baul_file_get_string_attribute_q (file_2,
3611 attribute);
3612
3613 if (value_1 != NULL((void*)0) && value_2 != NULL((void*)0)) {
3614 result = strcmp (value_1, value_2);
3615 }
3616
3617 g_free (value_1);
3618 g_free (value_2);
3619
3620 if (reversed) {
3621 result = -result;
3622 }
3623 }
3624
3625 return result;
3626}
3627
3628int
3629baul_file_compare_for_sort_by_attribute (BaulFile *file_1,
3630 BaulFile *file_2,
3631 const char *attribute,
3632 gboolean directories_first,
3633 gboolean reversed)
3634{
3635 return baul_file_compare_for_sort_by_attribute_q (file_1, file_2,
3636 g_quark_from_string (attribute),
3637 directories_first,
3638 reversed);
3639}
3640
3641
3642/**
3643 * baul_file_compare_name:
3644 * @file: A file object
3645 * @pattern: A string we are comparing it with
3646 *
3647 * Return value: result of a comparison of the file name and the given pattern,
3648 * using the same sorting order as sort by name.
3649 **/
3650int
3651baul_file_compare_display_name (BaulFile *file,
3652 const char *pattern)
3653{
3654 const char *name;
3655 int result;
3656
3657 g_return_val_if_fail (pattern != NULL, -1)do { if ((pattern != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "pattern != NULL"
); return (-1); } } while (0)
;
3658
3659 name = baul_file_peek_display_name (file);
3660 result = g_utf8_collate (name, pattern);
3661 return result;
3662}
3663
3664
3665gboolean
3666baul_file_is_hidden_file (BaulFile *file)
3667{
3668 return file->details->is_hidden;
3669}
3670
3671gboolean
3672baul_file_is_backup_file (BaulFile *file)
3673{
3674 return file->details->is_backup;
3675}
3676
3677/**
3678 * baul_file_should_show:
3679 * @file: the file to check.
3680 * @show_hidden: whether we want to show hidden files or not.
3681 * @show_backup: whether we want to show backup files or not.
3682 *
3683 * Determines if a #BaulFile should be shown. Note that when browsing
3684 * a trash directory, this function will always return %TRUE.
3685 *
3686 * Returns: %TRUE if the file should be shown, %FALSE if it shouldn't.
3687 */
3688gboolean
3689baul_file_should_show (BaulFile *file,
3690 gboolean show_hidden,
3691 gboolean show_foreign,
3692 gboolean show_backup)
3693{
3694 /* Never hide any files in trash. */
3695 if (baul_file_is_in_trash (file)) {
3696 return TRUE(!(0));
3697 } else {
3698 return (show_hidden || !baul_file_is_hidden_file (file)) &&
3699 (show_backup || !baul_file_is_backup_file (file)) &&
3700 (show_foreign || !(baul_file_is_in_desktop (file) && baul_file_is_foreign_link (file)));
3701 }
3702}
3703
3704gboolean
3705baul_file_is_home (BaulFile *file)
3706{
3707 GFile *dir;
3708
3709 dir = file->details->directory->details->location;
3710 if (dir == NULL((void*)0)) {
3711 return FALSE(0);
3712 }
3713
3714 return baul_is_home_directory_file (dir, file->details->name);
3715}
3716
3717gboolean
3718baul_file_is_in_desktop (BaulFile *file)
3719{
3720 if (file->details->directory->details->location) {
3721 return baul_is_desktop_directory (file->details->directory->details->location);
3722 }
3723 return FALSE(0);
3724
3725}
3726
3727static gboolean
3728filter_hidden_partition_callback (gpointer data,
3729 gpointer callback_data)
3730{
3731 BaulFile *file;
3732 FilterOptions options;
3733
3734 file = BAUL_FILE (data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), (baul_file_get_type())))))
;
3735 options = GPOINTER_TO_INT (callback_data)((gint) (glong) (callback_data));
3736
3737 return baul_file_should_show (file,
3738 options & SHOW_HIDDEN,
3739 TRUE(!(0)),
3740 options & SHOW_BACKUP);
3741}
3742
3743GList *
3744baul_file_list_filter_hidden (GList *files,
3745 gboolean show_hidden)
3746{
3747 GList *filtered_files;
3748 GList *removed_files;
3749
3750 /* FIXME bugzilla.gnome.org 40653:
3751 * Eventually this should become a generic filtering thingy.
3752 */
3753
3754 filtered_files = baul_file_list_copy (files);
3755 filtered_files = eel_g_list_partition (filtered_files,
3756 filter_hidden_partition_callback,
3757 GINT_TO_POINTER ((show_hidden ? SHOW_HIDDEN : 0))((gpointer) (glong) ((show_hidden ? SHOW_HIDDEN : 0))),
3758 &removed_files);
3759 baul_file_list_free (removed_files);
3760
3761 return filtered_files;
3762}
3763
3764char *
3765baul_file_get_metadata (BaulFile *file,
3766 const char *key,
3767 const char *default_metadata)
3768{
3769 guint id;
3770 char *value;
3771
3772 g_return_val_if_fail (key != NULL, g_strdup (default_metadata))do { if ((key != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(g_strdup_inline (default_metadata)); } } while (0)
;
3773 g_return_val_if_fail (key[0] != '\0', g_strdup (default_metadata))do { if ((key[0] != '\0')) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (g_strdup_inline (default_metadata)); } } while (0)
;
3774
3775 if (file == NULL((void*)0) ||
3776 file->details->metadata == NULL((void*)0)) {
3777 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3778 }
3779
3780 g_return_val_if_fail (BAUL_IS_FILE (file), g_strdup (default_metadata))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (g_strdup_inline
(default_metadata)); } } while (0)
;
3781
3782 id = baul_metadata_get_id (key);
3783 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3784
3785 if (value) {
3786 return g_strdup (value)g_strdup_inline (value);
3787 }
3788 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3789}
3790
3791GList *
3792baul_file_get_metadata_list (BaulFile *file,
3793 const char *key)
3794{
3795 guint id;
3796 char **value;
3797
3798 g_return_val_if_fail (key != NULL, NULL)do { if ((key != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(((void*)0)); } } while (0)
;
3799 g_return_val_if_fail (key[0] != '\0', NULL)do { if ((key[0] != '\0')) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (((void*)0)); } } while (0)
;
3800
3801 if (file == NULL((void*)0) ||
3802 file->details->metadata == NULL((void*)0)) {
3803 return NULL((void*)0);
3804 }
3805
3806 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
3807
3808 id = baul_metadata_get_id (key);
3809 id |= METADATA_ID_IS_LIST_MASK(1U<<31);
3810
3811 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3812
3813 if (value) {
3814 GList *res;
3815 int i;
3816
3817 res = NULL((void*)0);
3818 for (i = 0; value[i] != NULL((void*)0); i++) {
3819 res = g_list_prepend (res, g_strdup (value[i])g_strdup_inline (value[i]));
3820 }
3821 return g_list_reverse (res);
3822 }
3823
3824 return NULL((void*)0);
3825}
3826
3827void
3828baul_file_set_metadata (BaulFile *file,
3829 const char *key,
3830 const char *default_metadata,
3831 const char *metadata)
3832{
3833 const char *val;
3834
3835 g_return_if_fail (BAUL_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return; } } while (0)
;
3836 g_return_if_fail (key != NULL)do { if ((key != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
3837 g_return_if_fail (key[0] != '\0')do { if ((key[0] != '\0')) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
3838
3839 val = metadata;
3840 if (val == NULL((void*)0)) {
3841 val = default_metadata;
3842 }
3843
3844 EEL_CALL_METHODdo { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->set_metadata
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->set_metadata
) (file, key, val); } } while (0)
3845 (BAUL_FILE_CLASS, file,do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->set_metadata
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->set_metadata
) (file, key, val); } } while (0)
3846 set_metadata, (file, key, val))do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->set_metadata
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->set_metadata
) (file, key, val); } } while (0)
;
3847}
3848
3849void
3850baul_file_set_metadata_list (BaulFile *file,
3851 const char *key,
3852 GList *list)
3853{
3854 char **val;
3855 int len, i;
3856 GList *l;
3857
3858 g_return_if_fail (BAUL_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return; } } while (0)
;
3859 g_return_if_fail (key != NULL)do { if ((key != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
3860 g_return_if_fail (key[0] != '\0')do { if ((key[0] != '\0')) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
3861
3862 len = g_list_length (list);
3863 val = g_new (char *, len + 1)((char * *) g_malloc_n ((len + 1), sizeof (char *)));
3864 for (l = list, i = 0; l != NULL((void*)0); l = l->next, i++) {
3865 val[i] = l->data;
3866 }
3867 val[i] = NULL((void*)0);
3868
3869 EEL_CALL_METHODdo { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->set_metadata_as_list
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->set_metadata_as_list
) (file, key, val); } } while (0)
3870 (BAUL_FILE_CLASS, file,do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->set_metadata_as_list
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->set_metadata_as_list
) (file, key, val); } } while (0)
3871 set_metadata_as_list, (file, key, val))do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->set_metadata_as_list
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->set_metadata_as_list
) (file, key, val); } } while (0)
;
3872
3873 g_free (val);
3874}
3875
3876
3877gboolean
3878baul_file_get_boolean_metadata (BaulFile *file,
3879 const char *key,
3880 gboolean default_metadata)
3881{
3882 char *result_as_string;
3883 gboolean result;
3884
3885 g_return_val_if_fail (key != NULL, default_metadata)do { if ((key != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(default_metadata); } } while (0)
;
3886 g_return_val_if_fail (key[0] != '\0', default_metadata)do { if ((key[0] != '\0')) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (default_metadata); } } while (0)
;
3887
3888 if (file == NULL((void*)0)) {
3889 return default_metadata;
3890 }
3891
3892 g_return_val_if_fail (BAUL_IS_FILE (file), default_metadata)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (default_metadata
); } } while (0)
;
3893
3894 result_as_string = baul_file_get_metadata
3895 (file, key, default_metadata ? "true" : "false");
3896 g_assert (result_as_string != NULL)do { if (result_as_string != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 3896, ((const char*) (__func__
)), "result_as_string != NULL"); } while (0)
;
3897
3898 if (g_ascii_strcasecmp (result_as_string, "true") == 0) {
3899 result = TRUE(!(0));
3900 } else if (g_ascii_strcasecmp (result_as_string, "false") == 0) {
3901 result = FALSE(0);
3902 } else {
3903 g_error ("boolean metadata with value other than true or false");
3904 result = default_metadata;
3905 }
3906
3907 g_free (result_as_string);
3908 return result;
3909}
3910
3911int
3912baul_file_get_integer_metadata (BaulFile *file,
3913 const char *key,
3914 int default_metadata)
3915{
3916 char *result_as_string;
3917 char default_as_string[32];
3918 int result;
3919 char c;
3920
3921 g_return_val_if_fail (key != NULL, default_metadata)do { if ((key != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(default_metadata); } } while (0)
;
3922 g_return_val_if_fail (key[0] != '\0', default_metadata)do { if ((key[0] != '\0')) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (default_metadata); } } while (0)
;
3923
3924 if (file == NULL((void*)0)) {
3925 return default_metadata;
3926 }
3927 g_return_val_if_fail (BAUL_IS_FILE (file), default_metadata)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (default_metadata
); } } while (0)
;
3928
3929 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
3930 result_as_string = baul_file_get_metadata
3931 (file, key, default_as_string);
3932
3933 /* Normally we can't get a a NULL, but we check for it here to
3934 * handle the oddball case of a non-existent directory.
3935 */
3936 if (result_as_string == NULL((void*)0)) {
3937 result = default_metadata;
3938 } else {
3939 if (sscanf (result_as_string, " %d %c", &result, &c) != 1) {
3940 result = default_metadata;
3941 }
3942 g_free (result_as_string);
3943 }
3944
3945 return result;
3946}
3947
3948static gboolean
3949get_time_from_time_string (const char *time_string,
3950 time_t *time)
3951{
3952 long scanned_time;
3953 char c;
3954
3955 g_assert (time != NULL)do { if (time != ((void*)0)) ; else g_assertion_message_expr (
((gchar*) 0), "baul-file.c", 3955, ((const char*) (__func__))
, "time != NULL"); } while (0)
;
3956
3957 /* Only accept string if it has one integer with nothing
3958 * afterwards.
3959 */
3960 if (time_string == NULL((void*)0) ||
3961 sscanf (time_string, "%ld%c", &scanned_time, &c) != 1) {
3962 return FALSE(0);
3963 }
3964 *time = (time_t) scanned_time;
3965 return TRUE(!(0));
3966}
3967
3968time_t
3969baul_file_get_time_metadata (BaulFile *file,
3970 const char *key)
3971{
3972 time_t time;
3973 char *time_string;
3974
3975 time_string = baul_file_get_metadata (file, key, NULL((void*)0));
3976 if (!get_time_from_time_string (time_string, &time)) {
3977 time = UNDEFINED_TIME((time_t) (-1));
3978 }
3979 g_free (time_string);
3980
3981 return time;
3982}
3983
3984void
3985baul_file_set_time_metadata (BaulFile *file,
3986 const char *key,
3987 time_t time)
3988{
3989 char time_str[21];
3990 char *metadata;
3991
3992 if (time != UNDEFINED_TIME((time_t) (-1))) {
3993 /* 2^64 turns out to be 20 characters */
3994 g_snprintf (time_str, 20, "%ld", (long int)time);
3995 time_str[20] = '\0';
3996 metadata = time_str;
3997 } else {
3998 metadata = NULL((void*)0);
3999 }
4000
4001 baul_file_set_metadata (file, key, NULL((void*)0), metadata);
4002}
4003
4004
4005void
4006baul_file_set_boolean_metadata (BaulFile *file,
4007 const char *key,
4008 gboolean default_metadata,
4009 gboolean metadata)
4010{
4011 g_return_if_fail (BAUL_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return; } } while (0)
;
4012 g_return_if_fail (key != NULL)do { if ((key != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
4013 g_return_if_fail (key[0] != '\0')do { if ((key[0] != '\0')) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
4014
4015 baul_file_set_metadata (file, key,
4016 default_metadata ? "true" : "false",
4017 metadata ? "true" : "false");
4018}
4019
4020void
4021baul_file_set_integer_metadata (BaulFile *file,
4022 const char *key,
4023 int default_metadata,
4024 int metadata)
4025{
4026 char value_as_string[32];
4027 char default_as_string[32];
4028
4029 g_return_if_fail (BAUL_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return; } } while (0)
;
4030 g_return_if_fail (key != NULL)do { if ((key != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
4031 g_return_if_fail (key[0] != '\0')do { if ((key[0] != '\0')) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
4032
4033 g_snprintf (value_as_string, sizeof (value_as_string), "%d", metadata);
4034 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
4035
4036 baul_file_set_metadata (file, key,
4037 default_as_string, value_as_string);
4038}
4039
4040static const char *
4041baul_file_peek_display_name_collation_key (BaulFile *file)
4042{
4043 const char *res;
4044
4045 res = file->details->display_name_collation_key;
4046 if (res == NULL((void*)0))
4047 res = "";
4048
4049 return res;
4050}
4051
4052static const char *
4053baul_file_peek_display_name (BaulFile *file)
4054{
4055 /*
4056 stefano-k: Imported 15_nautilus_file_peek_crash.patch from debian nautilus
4057 Date: Thu, 27 Jan 2011 10:22:10 +0000
4058 Subject: Prevent a crash in nautilus_file_peek_display_name() on invalid NautilusFile
4059 This is more a workaround only, expect assert failures at other
4060 places when something bad happens. There's a race condition somewhere,
4061 this patch only prevents immediate crash.
4062 Patch by Marcus Husar <marcus.husar@rose.uni-heidelberg.de>
4063 https://bugzilla.gnome.org/show_bug.cgi?id=602500
4064 */
4065 if (file == NULL((void*)0) || baul_file_is_gone (file))
4066 return "";
4067
4068 /* Default to display name based on filename if its not set yet */
4069
4070 if (file->details->display_name == NULL((void*)0)) {
4071 const char *name;
4072
4073 name = file->details->name;
4074 if (g_utf8_validate (name, -1, NULL((void*)0))) {
4075 baul_file_set_display_name (file,
4076 name,
4077 NULL((void*)0),
4078 FALSE(0));
4079 } else {
4080 char *escaped_name;
4081
4082 escaped_name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
4083 baul_file_set_display_name (file,
4084 escaped_name,
4085 NULL((void*)0),
4086 FALSE(0));
4087 g_free (escaped_name);
4088 }
4089 }
4090
4091 return file->details->display_name;
4092}
4093
4094char *
4095baul_file_get_display_name (BaulFile *file)
4096{
4097 return g_strdup (baul_file_peek_display_name (file))g_strdup_inline (baul_file_peek_display_name (file));
4098}
4099
4100char *
4101baul_file_get_edit_name (BaulFile *file)
4102{
4103 const char *res;
4104
4105 res = file->details->edit_name;
4106 if (res == NULL((void*)0))
4107 res = "";
4108
4109 return g_strdup (res)g_strdup_inline (res);
4110}
4111
4112char *
4113baul_file_get_name (BaulFile *file)
4114{
4115 return g_strdup (file->details->name)g_strdup_inline (file->details->name);
4116}
4117
4118/**
4119 * baul_file_get_description:
4120 * @file: a #BaulFile.
4121 *
4122 * Gets the standard::description key from @file, if
4123 * it has been cached.
4124 *
4125 * Returns: a string containing the value of the standard::description
4126 * key, or %NULL.
4127 */
4128char *
4129baul_file_get_description (BaulFile *file)
4130{
4131 return g_strdup (file->details->description)g_strdup_inline (file->details->description);
4132}
4133
4134void
4135baul_file_monitor_add (BaulFile *file,
4136 gconstpointer client,
4137 BaulFileAttributes attributes)
4138{
4139 g_return_if_fail (BAUL_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return; } } while (0)
;
4140 g_return_if_fail (client != NULL)do { if ((client != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "client != NULL")
; return; } } while (0)
;
4141
4142 EEL_CALL_METHODdo { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->monitor_add
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->monitor_add
) (file, client, attributes); } } while (0)
4143 (BAUL_FILE_CLASS, file,do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->monitor_add
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->monitor_add
) (file, client, attributes); } } while (0)
4144 monitor_add, (file, client, attributes))do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->monitor_add
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->monitor_add
) (file, client, attributes); } } while (0)
;
4145}
4146
4147void
4148baul_file_monitor_remove (BaulFile *file,
4149 gconstpointer client)
4150{
4151 g_return_if_fail (BAUL_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return; } } while (0)
;
4152 g_return_if_fail (client != NULL)do { if ((client != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "client != NULL")
; return; } } while (0)
;
4153
4154 EEL_CALL_METHODdo { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->monitor_remove
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->monitor_remove
) (file, client); } } while (0)
4155 (BAUL_FILE_CLASS, file,do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->monitor_remove
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->monitor_remove
) (file, client); } } while (0)
4156 monitor_remove, (file, client))do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->monitor_remove
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->monitor_remove
) (file, client); } } while (0)
;
4157}
4158
4159gboolean
4160baul_file_is_launcher (BaulFile *file)
4161{
4162 return file->details->is_launcher;
4163}
4164
4165gboolean
4166baul_file_is_foreign_link (BaulFile *file)
4167{
4168 return file->details->is_foreign_link;
4169}
4170
4171gboolean
4172baul_file_is_trusted_link (BaulFile *file)
4173{
4174 return file->details->is_trusted_link;
4175}
4176
4177gboolean
4178baul_file_has_activation_uri (BaulFile *file)
4179{
4180 return file->details->activation_uri != NULL((void*)0);
4181}
4182
4183
4184/* Return the uri associated with the passed-in file, which may not be
4185 * the actual uri if the file is an desktop file or a baul
4186 * xml link file.
4187 */
4188char *
4189baul_file_get_activation_uri (BaulFile *file)
4190{
4191 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
4192
4193 if (file->details->activation_uri != NULL((void*)0)) {
4194 return g_strdup (file->details->activation_uri)g_strdup_inline (file->details->activation_uri);
4195 }
4196
4197 return baul_file_get_uri (file);
4198}
4199
4200GFile *
4201baul_file_get_activation_location (BaulFile *file)
4202{
4203 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
4204
4205 if (file->details->activation_uri != NULL((void*)0)) {
4206 return g_file_new_for_uri (file->details->activation_uri);
4207 }
4208
4209 return baul_file_get_location (file);
4210}
4211
4212
4213char *
4214baul_file_get_drop_target_uri (BaulFile *file)
4215{
4216 char *uri, *target_uri;
4217 GFile *location;
4218
4219 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
4220
4221 if (BAUL_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (baul_desktop_icon_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; }))))
) {
4222 BaulDesktopLink *link;
4223
4224 link = baul_desktop_icon_file_get_link (BAUL_DESKTOP_ICON_FILE (file)((((BaulDesktopIconFile*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((file)), (baul_desktop_icon_file_get_type
())))))
);
4225
4226 if (link != NULL((void*)0)) {
4227 location = baul_desktop_link_get_activation_location (link);
4228 g_object_unref (link);
4229 if (location != NULL((void*)0)) {
4230 uri = g_file_get_uri (location);
4231 g_object_unref (location);
4232 return uri;
4233 }
4234 }
4235 }
4236
4237 uri = baul_file_get_uri (file);
4238
4239 /* Check for Baul link */
4240 if (baul_file_is_baul_link (file)) {
4241 location = baul_file_get_location (file);
4242 /* FIXME bugzilla.gnome.org 43020: This does sync. I/O and works only locally. */
4243 if (g_file_is_native (location)) {
4244 target_uri = baul_link_local_get_link_uri (uri);
4245 if (target_uri != NULL((void*)0)) {
4246 g_free (uri);
4247 uri = target_uri;
4248 }
4249 }
4250 g_object_unref (location);
4251 }
4252
4253 return uri;
4254}
4255
4256static gboolean
4257is_uri_relative (const char *uri)
4258{
4259 char *scheme;
4260 gboolean ret;
4261
4262 scheme = g_uri_parse_scheme (uri);
4263 ret = (scheme == NULL((void*)0));
4264 g_free (scheme);
4265 return ret;
4266}
4267
4268static char *
4269get_custom_icon_metadata_uri (BaulFile *file)
4270{
4271 char *custom_icon_uri;
4272 char *uri;
4273
4274 uri = baul_file_get_metadata (file, BAUL_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0));
4275 if (uri != NULL((void*)0) &&
4276 baul_file_is_directory (file) &&
4277 is_uri_relative (uri)) {
4278 char *dir_uri;
4279
4280 dir_uri = baul_file_get_uri (file);
4281 custom_icon_uri = g_build_filename (dir_uri, uri, NULL((void*)0));
4282 g_free (dir_uri);
4283 g_free (uri);
4284 } else {
4285 custom_icon_uri = uri;
4286 }
4287 return custom_icon_uri;
4288}
4289
4290static GIcon *
4291get_custom_icon (BaulFile *file)
4292{
4293 char *custom_icon_uri;
4294 GFile *icon_file;
4295 GIcon *icon;
4296
4297 if (file == NULL((void*)0)) {
4298 return NULL((void*)0);
4299 }
4300
4301 icon = NULL((void*)0);
4302
4303 /* Metadata takes precedence */
4304 custom_icon_uri = get_custom_icon_metadata_uri (file);
4305
4306 if (custom_icon_uri) {
4307 icon_file = g_file_new_for_uri (custom_icon_uri);
4308 icon = g_file_icon_new (icon_file);
4309 g_object_unref (icon_file);
4310 g_free (custom_icon_uri);
4311 }
4312
4313 if (icon == NULL((void*)0) && file->details->got_link_info && file->details->custom_icon != NULL((void*)0)) {
4314 if (g_path_is_absolute (file->details->custom_icon)) {
4315 icon_file = g_file_new_for_path (file->details->custom_icon);
4316 icon = g_file_icon_new (icon_file);
4317 g_object_unref (icon_file);
4318 } else {
4319 icon = g_themed_icon_new (file->details->custom_icon);
4320 }
4321 }
4322
4323 return icon;
4324}
4325
4326
4327static guint64 cached_thumbnail_limit;
4328int cached_thumbnail_size;
4329static int show_image_thumbs;
4330
4331GFilesystemPreviewType
4332baul_file_get_filesystem_use_preview (BaulFile *file)
4333{
4334 GFilesystemPreviewType use_preview;
4335 BaulFile *parent;
4336
4337 parent = baul_file_get_parent (file);
4338 if (parent != NULL((void*)0)) {
4339 use_preview = parent->details->filesystem_use_preview;
4340 g_object_unref (parent);
4341 } else {
4342 use_preview = 0;
4343 }
4344
4345 return use_preview;
4346}
4347
4348gboolean
4349baul_file_should_show_thumbnail (BaulFile *file)
4350{
4351 const char *mime_type;
4352 GFilesystemPreviewType use_preview;
4353
4354 use_preview = baul_file_get_filesystem_use_preview (file);
4355
4356 mime_type = file->details->mime_type;
4357 if (mime_type == NULL((void*)0)) {
4358 mime_type = "application/octet-stream";
4359 }
4360
4361 /* If the thumbnail has already been created, don't care about the size
4362 * of the original file.
4363 */
4364 if (baul_thumbnail_is_mimetype_limited_by_size (mime_type) &&
4365 file->details->thumbnail_path == NULL((void*)0) &&
4366 baul_file_get_size (file) > cached_thumbnail_limit) {
4367 return FALSE(0);
4368 }
4369
4370 if (show_image_thumbs == BAUL_SPEED_TRADEOFF_ALWAYS) {
4371 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4372 return FALSE(0);
4373 } else {
4374 return TRUE(!(0));
4375 }
4376 } else if (show_image_thumbs == BAUL_SPEED_TRADEOFF_NEVER) {
4377 return FALSE(0);
4378 } else {
4379 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4380 /* file system says to never thumbnail anything */
4381 return FALSE(0);
4382 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
4383 /* file system says we should treat file as if it's local */
4384 return TRUE(!(0));
4385 } else {
4386 /* only local files */
4387 return baul_file_is_local (file);
4388 }
4389 }
4390
4391 return FALSE(0);
4392}
4393
4394static void
4395prepend_icon_name (const char *name,
4396 GThemedIcon *icon)
4397{
4398 g_themed_icon_prepend_name(icon, name);
4399}
4400
4401GIcon *
4402baul_file_get_gicon (BaulFile *file,
4403 BaulFileIconFlags flags)
4404{
4405 const char * const * names;
4406 GIcon *icon, *mount_icon = NULL((void*)0), *emblemed_icon;
4407 gboolean is_folder = FALSE(0), is_preview = FALSE(0), is_inode_directory = FALSE(0);
4408
4409 if (file == NULL((void*)0)) {
4410 return NULL((void*)0);
4411 }
4412
4413 icon = get_custom_icon (file);
4414 if (icon != NULL((void*)0)) {
4415 return icon;
4416 }
4417
4418 if (file->details->icon) {
4419 icon = NULL((void*)0);
4420
4421 /* fetch the mount icon here, we'll use it later */
4422 if (flags & BAUL_FILE_ICON_FLAGS_USE_MOUNT_ICON ||
4423 flags & BAUL_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) {
4424 GMount *mount;
4425
4426 mount = baul_file_get_mount (file);
4427
4428 if (mount != NULL((void*)0)) {
4429 mount_icon = g_mount_get_icon (mount);
4430 g_object_unref (mount);
4431 }
4432 }
4433
4434 if (((flags & BAUL_FILE_ICON_FLAGS_EMBEDDING_TEXT) ||
4435 (flags & BAUL_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT) ||
4436 (flags & BAUL_FILE_ICON_FLAGS_FOR_OPEN_FOLDER) ||
4437 (flags & BAUL_FILE_ICON_FLAGS_USE_MOUNT_ICON) ||
4438 (flags & BAUL_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) ||
4439 ((flags & BAUL_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4440 baul_file_has_open_window (file))) &&
4441 G_IS_THEMED_ICON (file->details->icon)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file->details->icon)); GType __t = ((g_themed_icon_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; }))))
) {
4442 GPtrArray *prepend_array;
4443 int i;
4444
4445 names = g_themed_icon_get_names (G_THEMED_ICON (file->details->icon)((((GThemedIcon*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((file->details->icon)), ((g_themed_icon_get_type ()
))))))
);
4446 prepend_array = g_ptr_array_new ();
4447
4448 for (i = 0; names[i] != NULL((void*)0); i++) {
4449 const char *name;
4450
4451 name = names[i];
4452
4453 if (strcmp (name, "folder") == 0) {
4454 is_folder = TRUE(!(0));
4455 }
4456 if (strcmp (name, "inode-directory") == 0) {
4457 is_inode_directory = TRUE(!(0));
4458 }
4459 if (strcmp (name, "text-x-generic") == 0 &&
4460 (flags & BAUL_FILE_ICON_FLAGS_EMBEDDING_TEXT)) {
4461 is_preview = TRUE(!(0));
4462 }
4463 }
4464
4465 /* Here, we add icons in reverse order of precedence,
4466 * because they are later prepended */
4467 if (is_preview) {
4468 g_ptr_array_add (prepend_array, "text-x-preview");
4469 }
4470
4471 /* "folder" should override "inode-directory", not the other way around */
4472 if (is_inode_directory) {
4473 g_ptr_array_add (prepend_array, "folder");
4474 }
4475 if (is_folder && (flags & BAUL_FILE_ICON_FLAGS_FOR_OPEN_FOLDER)) {
4476 g_ptr_array_add (prepend_array, "folder-open");
4477 }
4478 if (is_folder &&
4479 (flags & BAUL_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4480 baul_file_has_open_window (file)) {
4481 g_ptr_array_add (prepend_array, "folder-visiting");
4482 }
4483 if (is_folder &&
4484 (flags & BAUL_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT)) {
4485 g_ptr_array_add (prepend_array, "folder-drag-accept");
4486 }
4487
4488 if (prepend_array->len) {
4489 /* When constructing GThemed Icon, pointers from the array
4490 * are reused, but not the array itself, so the cast is safe */
4491 icon = g_themed_icon_new_from_names ((char**) names, -1);
4492 g_ptr_array_foreach (prepend_array, (GFunc) prepend_icon_name, icon);
4493 }
4494
4495 g_ptr_array_free (prepend_array, TRUE(!(0)));
4496 }
4497
4498 if (icon == NULL((void*)0)) {
4499 icon = g_object_ref (file->details->icon)((__typeof__ (file->details->icon)) (g_object_ref) (file
->details->icon))
;
4500 }
4501
4502 if ((flags & BAUL_FILE_ICON_FLAGS_USE_MOUNT_ICON) &&
4503 mount_icon != NULL((void*)0)) {
4504 g_object_unref (icon);
4505 icon = mount_icon;
4506 } else if ((flags & BAUL_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) &&
4507 mount_icon != NULL((void*)0) && !g_icon_equal (mount_icon, icon)) {
4508 GEmblem *emblem;
4509
4510 emblem = g_emblem_new (mount_icon);
4511 emblemed_icon = g_emblemed_icon_new (icon, emblem);
4512
4513 g_object_unref (emblem);
4514 g_object_unref (icon);
4515 g_object_unref (mount_icon);
4516
4517 icon = emblemed_icon;
4518 } else if (mount_icon != NULL((void*)0)) {
4519 g_object_unref (mount_icon);
4520 }
4521
4522 return icon;
4523 }
4524
4525 return g_themed_icon_new ("text-x-generic");
4526}
4527
4528static GIcon *
4529get_default_file_icon (BaulFileIconFlags flags)
4530{
4531 static GIcon *fallback_icon = NULL((void*)0);
4532 static GIcon *fallback_icon_preview = NULL((void*)0);
4533 if (fallback_icon == NULL((void*)0)) {
4534 fallback_icon = g_themed_icon_new ("text-x-generic");
4535 fallback_icon_preview = g_themed_icon_new ("text-x-preview");
4536 g_themed_icon_append_name (G_THEMED_ICON (fallback_icon_preview)((((GThemedIcon*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fallback_icon_preview)), ((g_themed_icon_get_type ()))))
))
, "text-x-generic");
4537 }
4538 if (flags & BAUL_FILE_ICON_FLAGS_EMBEDDING_TEXT) {
4539 return fallback_icon_preview;
4540 } else {
4541 return fallback_icon;
4542 }
4543}
4544
4545BaulIconInfo *
4546baul_file_get_icon (BaulFile *file,
4547 int size,
4548 int scale,
4549 BaulFileIconFlags flags)
4550{
4551 BaulIconInfo *icon;
4552 GIcon *gicon;
4553 GdkPixbuf *scaled_pixbuf;
4554
4555 if (file == NULL((void*)0)) {
4556 return NULL((void*)0);
4557 }
4558
4559 gicon = get_custom_icon (file);
4560 if (gicon) {
4561 GdkPixbuf *pixbuf;
4562
4563 icon = baul_icon_info_lookup (gicon, size, scale);
4564 g_object_unref (gicon);
4565
4566 pixbuf = baul_icon_info_get_pixbuf (icon);
4567 if (pixbuf != NULL((void*)0)) {
4568 if (!file->details->is_launcher && !gdk_pixbuf_get_has_alpha (pixbuf)) {
4569 baul_ui_frame_image (&pixbuf);
4570 }
4571 g_object_unref (icon);
4572
4573 icon = baul_icon_info_new_for_pixbuf (pixbuf, scale);
4574 g_object_unref (pixbuf);
4575 }
4576
4577 return icon;
4578 }
4579
4580 if (flags & BAUL_FILE_ICON_FLAGS_USE_THUMBNAILS &&
4581 baul_file_should_show_thumbnail (file)) {
4582 int modified_size;
4583
4584 if (flags & BAUL_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE) {
4585 modified_size = size * scale;
4586 } else {
4587 modified_size = size * scale * cached_thumbnail_size / BAUL_ICON_SIZE_STANDARD48;
4588 }
4589
4590 if (file->details->thumbnail) {
4591 int w, h, s;
4592 double thumb_scale;
4593 GdkPixbuf *raw_pixbuf;
4594
4595 raw_pixbuf = g_object_ref (file->details->thumbnail)((__typeof__ (file->details->thumbnail)) (g_object_ref)
(file->details->thumbnail))
;
4596
4597 w = gdk_pixbuf_get_width (raw_pixbuf);
4598 h = gdk_pixbuf_get_height (raw_pixbuf);
4599
4600 s = MAX (w, h)(((w) > (h)) ? (w) : (h));
4601 /* Don't scale up small thumbnails in the standard view */
4602 if (s <= cached_thumbnail_size) {
4603 thumb_scale = (double)size / BAUL_ICON_SIZE_STANDARD48;
4604 }
4605 else {
4606 thumb_scale = (double)modified_size / s;
4607 }
4608 /* Make sure that icons don't get smaller than BAUL_ICON_SIZE_SMALLEST */
4609 if (s*thumb_scale <= BAUL_ICON_SIZE_SMALLEST16) {
4610 thumb_scale = (double) BAUL_ICON_SIZE_SMALLEST16 / s;
4611 }
4612
4613 scaled_pixbuf = gdk_pixbuf_scale_simple (raw_pixbuf,
4614 MAX (w * thumb_scale, 1)(((w * thumb_scale) > (1)) ? (w * thumb_scale) : (1)),
4615 MAX (h * thumb_scale, 1)(((h * thumb_scale) > (1)) ? (h * thumb_scale) : (1)),
4616 GDK_INTERP_BILINEAR);
4617
4618 /* Render frames only for thumbnails of non-image files
4619 and for images with no alpha channel. */
4620 gboolean is_image = file->details->mime_type &&
4621 (strncmp (file->details->mime_type, "image/", 6) == 0);
4622 if (!is_image || !gdk_pixbuf_get_has_alpha (raw_pixbuf)) {
4623 baul_ui_frame_image (&scaled_pixbuf);
4624 }
4625
4626 g_object_unref (raw_pixbuf);
4627
4628 /* Don't scale up if more than 25%, then read the original
4629 image instead. We don't want to compare to exactly 100%,
4630 since the zoom level 150% gives thumbnails at 144, which is
4631 ok to scale up from 128. */
4632 if (modified_size > 128 * 1.25 * scale &&
4633 !file->details->thumbnail_wants_original &&
4634 baul_can_thumbnail_internally (file)) {
4635 /* Invalidate if we resize upward */
4636 file->details->thumbnail_wants_original = TRUE(!(0));
4637 baul_file_invalidate_attributes (file, BAUL_FILE_ATTRIBUTE_THUMBNAIL);
4638 }
4639
4640 icon = baul_icon_info_new_for_pixbuf (scaled_pixbuf, scale);
4641 g_object_unref (scaled_pixbuf);
4642 return icon;
4643 } else if (file->details->thumbnail_path == NULL((void*)0) &&
4644 file->details->can_read &&
4645 !file->details->is_thumbnailing &&
4646 !file->details->thumbnailing_failed) {
4647 if (baul_can_thumbnail (file)) {
4648 baul_create_thumbnail (file);
4649 }
4650 }
4651 }
4652
4653 if (file->details->is_thumbnailing &&
4654 flags & BAUL_FILE_ICON_FLAGS_USE_THUMBNAILS)
4655 gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING"image-loading");
4656 else
4657 gicon = baul_file_get_gicon (file, flags);
4658
4659 if (gicon) {
4660 icon = baul_icon_info_lookup (gicon, size, scale);
4661 g_object_unref (gicon);
4662 return icon;
4663 } else {
4664 return baul_icon_info_lookup (get_default_file_icon (flags), size, scale);
4665 }
4666}
4667
4668cairo_surface_t *
4669baul_file_get_icon_surface (BaulFile *file,
4670 int size,
4671 gboolean force_size,
4672 int scale,
4673 BaulFileIconFlags flags)
4674{
4675 BaulIconInfo *info;
4676 cairo_surface_t *surface;
4677
4678 info = baul_file_get_icon (file, size, scale, flags);
4679 if (force_size) {
4680 surface = baul_icon_info_get_surface_at_size (info, size);
4681 } else {
4682 surface = baul_icon_info_get_surface (info);
4683 }
4684 g_object_unref (info);
4685
4686 return surface;
4687}
4688
4689char *
4690baul_file_get_custom_icon (BaulFile *file)
4691{
4692 char *custom_icon;
4693
4694 if (file == NULL((void*)0)) {
4695 return NULL((void*)0);
4696 }
4697
4698 /* Metadata takes precedence */
4699 custom_icon = get_custom_icon_metadata_uri (file);
4700
4701 if (custom_icon == NULL((void*)0) && file->details->got_link_info) {
4702 custom_icon = g_strdup (file->details->custom_icon)g_strdup_inline (file->details->custom_icon);
4703 }
4704
4705 return custom_icon;
4706}
4707
4708
4709gboolean
4710baul_file_get_date (BaulFile *file,
4711 BaulDateType date_type,
4712 time_t *date)
4713{
4714 if (date != NULL((void*)0)) {
4715 *date = 0;
4716 }
4717
4718 g_return_val_if_fail (date_type == BAUL_DATE_TYPE_CHANGEDdo { if ((date_type == BAUL_DATE_TYPE_CHANGED || date_type ==
BAUL_DATE_TYPE_ACCESSED || date_type == BAUL_DATE_TYPE_MODIFIED
|| date_type == BAUL_DATE_TYPE_TRASHED || date_type == BAUL_DATE_TYPE_PERMISSIONS_CHANGED
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "date_type == BAUL_DATE_TYPE_CHANGED || date_type == BAUL_DATE_TYPE_ACCESSED || date_type == BAUL_DATE_TYPE_MODIFIED || date_type == BAUL_DATE_TYPE_TRASHED || date_type == BAUL_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4719 || date_type == BAUL_DATE_TYPE_ACCESSEDdo { if ((date_type == BAUL_DATE_TYPE_CHANGED || date_type ==
BAUL_DATE_TYPE_ACCESSED || date_type == BAUL_DATE_TYPE_MODIFIED
|| date_type == BAUL_DATE_TYPE_TRASHED || date_type == BAUL_DATE_TYPE_PERMISSIONS_CHANGED
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "date_type == BAUL_DATE_TYPE_CHANGED || date_type == BAUL_DATE_TYPE_ACCESSED || date_type == BAUL_DATE_TYPE_MODIFIED || date_type == BAUL_DATE_TYPE_TRASHED || date_type == BAUL_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4720 || date_type == BAUL_DATE_TYPE_MODIFIEDdo { if ((date_type == BAUL_DATE_TYPE_CHANGED || date_type ==
BAUL_DATE_TYPE_ACCESSED || date_type == BAUL_DATE_TYPE_MODIFIED
|| date_type == BAUL_DATE_TYPE_TRASHED || date_type == BAUL_DATE_TYPE_PERMISSIONS_CHANGED
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "date_type == BAUL_DATE_TYPE_CHANGED || date_type == BAUL_DATE_TYPE_ACCESSED || date_type == BAUL_DATE_TYPE_MODIFIED || date_type == BAUL_DATE_TYPE_TRASHED || date_type == BAUL_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4721 || date_type == BAUL_DATE_TYPE_TRASHEDdo { if ((date_type == BAUL_DATE_TYPE_CHANGED || date_type ==
BAUL_DATE_TYPE_ACCESSED || date_type == BAUL_DATE_TYPE_MODIFIED
|| date_type == BAUL_DATE_TYPE_TRASHED || date_type == BAUL_DATE_TYPE_PERMISSIONS_CHANGED
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "date_type == BAUL_DATE_TYPE_CHANGED || date_type == BAUL_DATE_TYPE_ACCESSED || date_type == BAUL_DATE_TYPE_MODIFIED || date_type == BAUL_DATE_TYPE_TRASHED || date_type == BAUL_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4722 || date_type == BAUL_DATE_TYPE_PERMISSIONS_CHANGED, FALSE)do { if ((date_type == BAUL_DATE_TYPE_CHANGED || date_type ==
BAUL_DATE_TYPE_ACCESSED || date_type == BAUL_DATE_TYPE_MODIFIED
|| date_type == BAUL_DATE_TYPE_TRASHED || date_type == BAUL_DATE_TYPE_PERMISSIONS_CHANGED
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "date_type == BAUL_DATE_TYPE_CHANGED || date_type == BAUL_DATE_TYPE_ACCESSED || date_type == BAUL_DATE_TYPE_MODIFIED || date_type == BAUL_DATE_TYPE_TRASHED || date_type == BAUL_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
;
4723
4724 if (file == NULL((void*)0)) {
4725 return FALSE(0);
4726 }
4727
4728 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
4729
4730 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_date == ((void*)0)
) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_date
) (file, date_type, date))
4731 (BAUL_FILE_CLASS, file,(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_date == ((void*)0)
) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_date
) (file, date_type, date))
4732 get_date, (file, date_type, date))(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_date == ((void*)0)
) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_date
) (file, date_type, date))
;
4733}
4734
4735static char *
4736baul_file_get_where_string (BaulFile *file)
4737{
4738 if (file == NULL((void*)0)) {
4739 return NULL((void*)0);
4740 }
4741
4742 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
4743
4744 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_where_string == ((
void*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_where_string
) (file))
4745 (BAUL_FILE_CLASS, file,(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_where_string == ((
void*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_where_string
) (file))
4746 get_where_string, (file))(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_where_string == ((
void*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_where_string
) (file))
;
4747}
4748
4749static const char *TODAY_TIME_FORMATS [] = {
4750 /* Today, use special word.
4751 * strftime patterns preceeded with the widest
4752 * possible resulting string for that pattern.
4753 *
4754 * Note to localizers: You can look at man strftime
4755 * for details on the format, but you should only use
4756 * the specifiers from the C standard, not extensions.
4757 * These include "%" followed by one of
4758 * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions
4759 * in the Baul version of strftime that can be
4760 * used (and match GNU extensions). Putting a "-"
4761 * between the "%" and any numeric directive will turn
4762 * off zero padding, and putting a "_" there will use
4763 * space padding instead of zero padding.
4764 */
4765 N_("today at 00:00:00 PM")("today at 00:00:00 PM"),
4766 N_("today at %-I:%M:%S %p")("today at %-I:%M:%S %p"),
4767
4768 N_("today at 00:00 PM")("today at 00:00 PM"),
4769 N_("today at %-I:%M %p")("today at %-I:%M %p"),
4770
4771 N_("today, 00:00 PM")("today, 00:00 PM"),
4772 N_("today, %-I:%M %p")("today, %-I:%M %p"),
4773
4774 N_("today")("today"),
4775 N_("today")("today"),
4776
4777 NULL((void*)0)
4778};
4779
4780static const char *YESTERDAY_TIME_FORMATS [] = {
4781 /* Yesterday, use special word.
4782 * Note to localizers: Same issues as "today" string.
4783 */
4784 N_("yesterday at 00:00:00 PM")("yesterday at 00:00:00 PM"),
4785 N_("yesterday at %-I:%M:%S %p")("yesterday at %-I:%M:%S %p"),
4786
4787 N_("yesterday at 00:00 PM")("yesterday at 00:00 PM"),
4788 N_("yesterday at %-I:%M %p")("yesterday at %-I:%M %p"),
4789
4790 N_("yesterday, 00:00 PM")("yesterday, 00:00 PM"),
4791 N_("yesterday, %-I:%M %p")("yesterday, %-I:%M %p"),
4792
4793 N_("yesterday")("yesterday"),
4794 N_("yesterday")("yesterday"),
4795
4796 NULL((void*)0)
4797};
4798
4799static const char *CURRENT_WEEK_TIME_FORMATS [] = {
4800 /* Current week, include day of week.
4801 * Note to localizers: Same issues as "today" string.
4802 * The width measurement templates correspond to
4803 * the day/month name with the most letters.
4804 */
4805 N_("Wednesday, September 00 0000 at 00:00:00 PM")("Wednesday, September 00 0000 at 00:00:00 PM"),
4806 N_("%A, %B %-d %Y at %-I:%M:%S %p")("%A, %B %-d %Y at %-I:%M:%S %p"),
4807
4808 N_("Mon, Oct 00 0000 at 00:00:00 PM")("Mon, Oct 00 0000 at 00:00:00 PM"),
4809 N_("%a, %b %-d %Y at %-I:%M:%S %p")("%a, %b %-d %Y at %-I:%M:%S %p"),
4810
4811 N_("Mon, Oct 00 0000 at 00:00 PM")("Mon, Oct 00 0000 at 00:00 PM"),
4812 N_("%a, %b %-d %Y at %-I:%M %p")("%a, %b %-d %Y at %-I:%M %p"),
4813
4814 N_("Oct 00 0000 at 00:00 PM")("Oct 00 0000 at 00:00 PM"),
4815 N_("%b %-d %Y at %-I:%M %p")("%b %-d %Y at %-I:%M %p"),
4816
4817 N_("Oct 00 0000, 00:00 PM")("Oct 00 0000, 00:00 PM"),
4818 N_("%b %-d %Y, %-I:%M %p")("%b %-d %Y, %-I:%M %p"),
4819
4820 N_("00/00/00, 00:00 PM")("00/00/00, 00:00 PM"),
4821 N_("%m/%-d/%y, %-I:%M %p")("%m/%-d/%y, %-I:%M %p"),
4822
4823 N_("00/00/00")("00/00/00"),
4824 N_("%m/%d/%y")("%m/%d/%y"),
4825
4826 NULL((void*)0)
4827};
4828
4829static char *
4830baul_file_fit_date_as_string (BaulFile *file,
4831 BaulDateType date_type,
4832 int width,
4833 BaulWidthMeasureCallback measure_callback,
4834 BaulTruncateCallback truncate_callback,
4835 void *measure_context)
4836{
4837 time_t file_time_raw;
4838 const char **formats;
4839 const char *format;
4840 char *date_string;
4841 gchar *result = NULL((void*)0);
4842 int i;
4843 GDateTime *date_time, *today;
4844 GTimeSpan file_date_age;
4845
4846 if (!baul_file_get_date (file, date_type, &file_time_raw)) {
4847 return NULL((void*)0);
4848 }
4849
4850 date_time = g_date_time_new_from_unix_local (file_time_raw);
4851
4852 if (date_format_pref == BAUL_DATE_FORMAT_LOCALE) {
4853 result = g_date_time_format (date_time, "%c");
4854 goto out;
4855 } else if (date_format_pref == BAUL_DATE_FORMAT_ISO) {
4856 result = g_date_time_format (date_time, "%Y-%m-%d %H:%M:%S");
4857 goto out;
4858 }
4859
4860 today = g_date_time_new_now_local ();
4861 file_date_age = g_date_time_difference (today, date_time);
4862 g_date_time_unref (today);
4863
4864 /* Format varies depending on how old the date is. This minimizes
4865 * the length (and thus clutter & complication) of typical dates
4866 * while providing sufficient detail for recent dates to make
4867 * them maximally understandable at a glance. Keep all format
4868 * strings separate rather than combining bits & pieces for
4869 * internationalization's sake.
4870 */
4871
4872 if (file_date_age < G_TIME_SPAN_DAY((86400000000L))) {
4873 formats = TODAY_TIME_FORMATS;
4874 } else if (file_date_age < 2 * G_TIME_SPAN_DAY((86400000000L))) {
4875 formats = YESTERDAY_TIME_FORMATS;
4876 } else {
4877 formats = CURRENT_WEEK_TIME_FORMATS;
4878 }
4879
4880 /* Find the date format that just fits the required width. Instead of measuring
4881 * the resulting string width directly, measure the width of a template that represents
4882 * the widest possible version of a date in a given format. This is done by using M, m
4883 * and 0 for the variable letters/digits respectively.
4884 */
4885 format = NULL((void*)0);
4886
4887 for (i = 0; ; i += 2) {
4888 const char *width_template;
4889
4890 width_template = (formats [i] ? _(formats [i])gettext (formats [i]) : NULL((void*)0));
4891 if (width_template == NULL((void*)0)) {
4892 /* no more formats left */
4893 g_assert (format != NULL)do { if (format != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 4893, ((const char*) (__func__
)), "format != NULL"); } while (0)
;
4894
4895 /* Can't fit even the shortest format -- return an ellipsized form in the
4896 * shortest format
4897 */
4898
4899 date_string = g_date_time_format (date_time, format);
4900
4901 if (truncate_callback == NULL((void*)0)) {
4902 result = date_string;
4903 break;
4904 }
4905
4906 result = (* truncate_callback) (date_string, width, measure_context);
4907 g_free (date_string);
4908 break;
4909 }
4910
4911 format = _(formats [i + 1])gettext (formats [i + 1]);
4912
4913 if (measure_callback == NULL((void*)0)) {
4914 /* don't care about fitting the width */
4915 break;
4916 }
4917
4918 if ((* measure_callback) (width_template, measure_context) <= width) {
4919 /* The template fits, this is the format we can fit. */
4920 break;
4921 }
4922 }
4923
4924 if (result == NULL((void*)0)) {
4925 result = g_date_time_format (date_time, format);
4926 }
4927
4928out:
4929 g_date_time_unref (date_time);
4930 return result;
4931}
4932
4933/**
4934 * baul_file_fit_modified_date_as_string:
4935 *
4936 * Get a user-displayable string representing a file modification date,
4937 * truncated to @width using the measuring and truncating callbacks.
4938 * @file: BaulFile representing the file in question.
4939 * @width: The desired resulting string width.
4940 * @measure_callback: The callback used to measure the string width.
4941 * @truncate_callback: The callback used to truncate the string to a desired width.
4942 * @measure_context: Data neede when measuring and truncating.
4943 *
4944 * Returns: Newly allocated string ready to display to the user.
4945 *
4946 **/
4947char *
4948baul_file_fit_modified_date_as_string (BaulFile *file,
4949 int width,
4950 BaulWidthMeasureCallback measure_callback,
4951 BaulTruncateCallback truncate_callback,
4952 void *measure_context)
4953{
4954 return baul_file_fit_date_as_string (file, BAUL_DATE_TYPE_MODIFIED,
4955 width, measure_callback, truncate_callback, measure_context);
4956}
4957
4958static char *
4959baul_file_get_trash_original_file_parent_as_string (BaulFile *file)
4960{
4961 if (file->details->trash_orig_path != NULL((void*)0)) {
4962 BaulFile *orig_file, *parent;
4963 GFile *location;
4964 char *filename;
4965
4966 orig_file = baul_file_get_trash_original_file (file);
4967 parent = baul_file_get_parent (orig_file);
4968 location = baul_file_get_location (parent);
4969
4970 filename = g_file_get_parse_name (location);
4971
4972 g_object_unref (location);
4973 baul_file_unref (parent);
4974 baul_file_unref (orig_file);
4975
4976 return filename;
4977 }
4978
4979 return NULL((void*)0);
4980}
4981
4982/**
4983 * baul_file_get_date_as_string:
4984 *
4985 * Get a user-displayable string representing a file modification date.
4986 * The caller is responsible for g_free-ing this string.
4987 * @file: BaulFile representing the file in question.
4988 *
4989 * Returns: Newly allocated string ready to display to the user.
4990 *
4991 **/
4992static char *
4993baul_file_get_date_as_string (BaulFile *file, BaulDateType date_type)
4994{
4995 return baul_file_fit_date_as_string (file, date_type,
4996 0, NULL((void*)0), NULL((void*)0), NULL((void*)0));
4997}
4998
4999static BaulSpeedTradeoffValue show_directory_item_count;
5000static BaulSpeedTradeoffValue show_text_in_icons;
5001
5002static void
5003show_text_in_icons_changed_callback (gpointer callback_data G_GNUC_UNUSED__attribute__ ((__unused__)))
5004{
5005 show_text_in_icons = g_settings_get_enum (baul_preferences, BAUL_PREFERENCES_SHOW_TEXT_IN_ICONS"show-icon-text");
5006}
5007
5008static void
5009show_directory_item_count_changed_callback (gpointer callback_data G_GNUC_UNUSED__attribute__ ((__unused__)))
5010{
5011 show_directory_item_count = g_settings_get_enum (baul_preferences, BAUL_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS"show-directory-item-counts");
5012}
5013
5014static gboolean
5015get_speed_tradeoff_preference_for_file (BaulFile *file, BaulSpeedTradeoffValue value)
5016{
5017 GFilesystemPreviewType use_preview;
5018
5019 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
5020
5021 use_preview = baul_file_get_filesystem_use_preview (file);
5022
5023 if (value == BAUL_SPEED_TRADEOFF_ALWAYS) {
5024 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5025 return FALSE(0);
5026 } else {
5027 return TRUE(!(0));
5028 }
5029 }
5030
5031 if (value == BAUL_SPEED_TRADEOFF_NEVER) {
5032 return FALSE(0);
5033 }
5034
5035 g_assert (value == BAUL_SPEED_TRADEOFF_LOCAL_ONLY)do { if (value == BAUL_SPEED_TRADEOFF_LOCAL_ONLY) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 5035, ((const char*) (__func__
)), "value == BAUL_SPEED_TRADEOFF_LOCAL_ONLY"); } while (0)
;
5036
5037 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5038 /* file system says to never preview anything */
5039 return FALSE(0);
5040 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
5041 /* file system says we should treat file as if it's local */
5042 return TRUE(!(0));
5043 } else {
5044 /* only local files */
5045 return baul_file_is_local (file);
5046 }
5047}
5048
5049gboolean
5050baul_file_should_show_directory_item_count (BaulFile *file)
5051{
5052 static gboolean show_directory_item_count_callback_added = FALSE(0);
5053
5054 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
5055
5056 if (file->details->mime_type &&
5057 strcmp (file->details->mime_type, "x-directory/smb-share") == 0) {
5058 return FALSE(0);
5059 }
5060
5061 /* Add the callback once for the life of our process */
5062 if (!show_directory_item_count_callback_added) {
5063 g_signal_connect_swapped (baul_preferences,g_signal_connect_data ((baul_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5064 "changed::" BAUL_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS,g_signal_connect_data ((baul_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5065 G_CALLBACK(show_directory_item_count_changed_callback),g_signal_connect_data ((baul_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5066 NULL)g_signal_connect_data ((baul_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
5067 show_directory_item_count_callback_added = TRUE(!(0));
5068
5069 /* Peek for the first time */
5070 show_directory_item_count_changed_callback (NULL((void*)0));
5071 }
5072
5073 return get_speed_tradeoff_preference_for_file (file, show_directory_item_count);
5074}
5075
5076gboolean
5077baul_file_should_show_type (BaulFile *file)
5078{
5079 char *uri;
5080 gboolean ret;
5081
5082 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
5083
5084 uri = baul_file_get_uri (file);
5085 ret = ((strcmp (uri, "computer:///") != 0) &&
5086 (strcmp (uri, "network:///") != 0) &&
5087 (strcmp (uri, "smb:///") != 0));
5088 g_free (uri);
5089
5090 return ret;
5091}
5092
5093gboolean
5094baul_file_should_get_top_left_text (BaulFile *file)
5095{
5096 static gboolean show_text_in_icons_callback_added = FALSE(0);
5097
5098 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
5099
5100 /* Add the callback once for the life of our process */
5101 if (!show_text_in_icons_callback_added) {
5102 g_signal_connect_swapped (baul_preferences,g_signal_connect_data ((baul_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5103 "changed::" BAUL_PREFERENCES_SHOW_TEXT_IN_ICONS,g_signal_connect_data ((baul_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5104 G_CALLBACK (show_text_in_icons_changed_callback),g_signal_connect_data ((baul_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5105 NULL)g_signal_connect_data ((baul_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
5106 show_text_in_icons_callback_added = TRUE(!(0));
5107
5108 /* Peek for the first time */
5109 show_text_in_icons_changed_callback (NULL((void*)0));
5110 }
5111
5112 if (show_text_in_icons == BAUL_SPEED_TRADEOFF_ALWAYS) {
5113 return TRUE(!(0));
5114 }
5115
5116 if (show_text_in_icons == BAUL_SPEED_TRADEOFF_NEVER) {
5117 return FALSE(0);
5118 }
5119
5120 return get_speed_tradeoff_preference_for_file (file, show_text_in_icons);
5121}
5122
5123/**
5124 * baul_file_get_directory_item_count
5125 *
5126 * Get the number of items in a directory.
5127 * @file: BaulFile representing a directory.
5128 * @count: Place to put count.
5129 * @count_unreadable: Set to TRUE (if non-NULL) if permissions prevent
5130 * the item count from being read on this directory. Otherwise set to FALSE.
5131 *
5132 * Returns: TRUE if count is available.
5133 *
5134 **/
5135gboolean
5136baul_file_get_directory_item_count (BaulFile *file,
5137 guint *count,
5138 gboolean *count_unreadable)
5139{
5140 if (count != NULL((void*)0)) {
5141 *count = 0;
5142 }
5143 if (count_unreadable != NULL((void*)0)) {
5144 *count_unreadable = FALSE(0);
5145 }
5146
5147 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
5148
5149 if (!baul_file_is_directory (file)) {
5150 return FALSE(0);
5151 }
5152
5153 if (!baul_file_should_show_directory_item_count (file)) {
5154 return FALSE(0);
5155 }
5156
5157 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_item_count
) (file, count, count_unreadable))
5158 (BAUL_FILE_CLASS, file,(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_item_count
) (file, count, count_unreadable))
5159 get_item_count, (file, count, count_unreadable))(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_item_count
) (file, count, count_unreadable))
;
5160}
5161
5162/**
5163 * baul_file_get_deep_counts
5164 *
5165 * Get the statistics about items inside a directory.
5166 * @file: BaulFile representing a directory or file.
5167 * @directory_count: Place to put count of directories inside.
5168 * @files_count: Place to put count of files inside.
5169 * @unreadable_directory_count: Number of directories encountered
5170 * that were unreadable.
5171 * @total_size: Total size of all files and directories visited.
5172 * @total_size_on_disk: Total size on disk of all files and directories visited.
5173 * @force: Whether the deep counts should even be collected if
5174 * baul_file_should_show_directory_item_count returns FALSE
5175 * for this file.
5176 *
5177 * Returns: Status to indicate whether sizes are available.
5178 *
5179 **/
5180BaulRequestStatus
5181baul_file_get_deep_counts (BaulFile *file,
5182 guint *directory_count,
5183 guint *file_count,
5184 guint *unreadable_directory_count,
5185 goffset *total_size,
5186 goffset *total_size_on_disk,
5187 gboolean force)
5188{
5189 if (directory_count != NULL((void*)0)) {
5190 *directory_count = 0;
5191 }
5192 if (file_count != NULL((void*)0)) {
5193 *file_count = 0;
5194 }
5195 if (unreadable_directory_count != NULL((void*)0)) {
5196 *unreadable_directory_count = 0;
5197 }
5198 if (total_size != NULL((void*)0)) {
5199 *total_size = 0;
5200 }
5201 if (total_size_on_disk != NULL((void*)0)) {
5202 *total_size_on_disk = 0;
5203 }
5204
5205 g_return_val_if_fail (BAUL_IS_FILE (file), BAUL_REQUEST_DONE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (BAUL_REQUEST_DONE
); } } while (0)
;
5206
5207 if (!force && !baul_file_should_show_directory_item_count (file)) {
5208 /* Set field so an existing value isn't treated as up-to-date
5209 * when preference changes later.
5210 */
5211 file->details->deep_counts_status = BAUL_REQUEST_NOT_STARTED;
5212 return file->details->deep_counts_status;
5213 }
5214
5215 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5216 (BAUL_FILE_CLASS, file,(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5217 get_deep_counts, (file,(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5218 directory_count,(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5219 file_count,(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5220 unreadable_directory_count,(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5221 total_size,(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5222 total_size_on_disk))(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
;
5223}
5224
5225void
5226baul_file_recompute_deep_counts (BaulFile *file)
5227{
5228 if (file->details->deep_counts_status != BAUL_REQUEST_IN_PROGRESS) {
5229 file->details->deep_counts_status = BAUL_REQUEST_NOT_STARTED;
5230 if (file->details->directory != NULL((void*)0)) {
5231 baul_directory_add_file_to_work_queue (file->details->directory, file);
5232 baul_directory_async_state_changed (file->details->directory);
5233 }
5234 }
5235}
5236
5237gboolean
5238baul_file_can_get_size (BaulFile *file)
5239{
5240 return file->details->size == -1;
5241}
5242
5243
5244/**
5245 * baul_file_get_size
5246 *
5247 * Get the file size.
5248 * @file: BaulFile representing the file in question.
5249 *
5250 * Returns: Size in bytes.
5251 *
5252 **/
5253goffset
5254baul_file_get_size (BaulFile *file)
5255{
5256 /* Before we have info on the file, we don't know the size. */
5257 if (file->details->size == -1)
5258 return 0;
5259 return file->details->size;
5260}
5261
5262/**
5263 * baul_file_get_size_on_disk
5264 *
5265 * Get the file size on disk (how many bytes is using on the filesystem).
5266 * e.g.: usually files with 1 byte will use a whole inode so it will return the
5267 * size of 1 inode. If the file is sparse the size on disk will be equal or less
5268 * than the size of the file.
5269 * @file: BaulFile representing the file in question.
5270 *
5271 * Returns: Size in bytes.
5272 *
5273 **/
5274goffset
5275baul_file_get_size_on_disk (BaulFile *file)
5276{
5277 /* Before we have info on the file, we don't know the size. */
5278 if (file->details->size_on_disk == -1)
5279 return 0;
5280 return file->details->size_on_disk;
5281}
5282
5283time_t
5284baul_file_get_mtime (BaulFile *file)
5285{
5286 return file->details->mtime;
5287}
5288
5289
5290static void
5291set_attributes_get_info_callback (GObject *source_object,
5292 GAsyncResult *res,
5293 gpointer callback_data)
5294{
5295 BaulFileOperation *op;
5296 GFileInfo *new_info;
5297 GError *error;
5298
5299 op = callback_data;
5300
5301 error = NULL((void*)0);
5302 new_info = g_file_query_info_finish (G_FILE (source_object)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_file_get_type ()))))))
, res, &error);
5303 if (new_info != NULL((void*)0)) {
5304 if (baul_file_update_info (op->file, new_info)) {
5305 baul_file_changed (op->file);
5306 }
5307 g_object_unref (new_info);
5308 }
5309 baul_file_operation_complete (op, NULL((void*)0), error);
5310 if (error) {
5311 g_error_free (error);
5312 }
5313}
5314
5315
5316static void
5317set_attributes_callback (GObject *source_object,
5318 GAsyncResult *result,
5319 gpointer callback_data)
5320{
5321 BaulFileOperation *op;
5322 GError *error;
5323 gboolean res;
5324
5325 op = callback_data;
5326
5327 error = NULL((void*)0);
5328 res = g_file_set_attributes_finish (G_FILE (source_object)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_file_get_type ()))))))
,
5329 result,
5330 NULL((void*)0),
5331 &error);
5332
5333 if (res) {
5334 g_file_query_info_async (G_FILE (source_object)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_file_get_type ()))))))
,
5335 BAUL_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
5336 0,
5337 G_PRIORITY_DEFAULT0,
5338 op->cancellable,
5339 set_attributes_get_info_callback, op);
5340 } else {
5341 baul_file_operation_complete (op, NULL((void*)0), error);
5342 g_error_free (error);
5343 }
5344}
5345
5346void
5347baul_file_set_attributes (BaulFile *file,
5348 GFileInfo *attributes,
5349 BaulFileOperationCallback callback,
5350 gpointer callback_data)
5351{
5352 BaulFileOperation *op;
5353 GFile *location;
5354
5355 op = baul_file_operation_new (file, callback, callback_data);
5356
5357 location = baul_file_get_location (file);
5358 g_file_set_attributes_async (location,
5359 attributes,
5360 0,
5361 G_PRIORITY_DEFAULT0,
5362 op->cancellable,
5363 set_attributes_callback,
5364 op);
5365 g_object_unref (location);
5366}
5367
5368
5369/**
5370 * baul_file_can_get_permissions:
5371 *
5372 * Check whether the permissions for a file are determinable.
5373 * This might not be the case for files on non-UNIX file systems.
5374 *
5375 * @file: The file in question.
5376 *
5377 * Return value: TRUE if the permissions are valid.
5378 */
5379gboolean
5380baul_file_can_get_permissions (BaulFile *file)
5381{
5382 return file->details->has_permissions;
5383}
5384
5385/**
5386 * baul_file_can_set_permissions:
5387 *
5388 * Check whether the current user is allowed to change
5389 * the permissions of a file.
5390 *
5391 * @file: The file in question.
5392 *
5393 * Return value: TRUE if the current user can change the
5394 * permissions of @file, FALSE otherwise. It's always possible
5395 * that when you actually try to do it, you will fail.
5396 */
5397gboolean
5398baul_file_can_set_permissions (BaulFile *file)
5399{
5400 uid_t user_id;
5401
5402 if (file->details->uid != -1 &&
5403 baul_file_is_local (file)) {
5404 /* Check the user. */
5405 user_id = geteuid();
5406
5407 /* Owner is allowed to set permissions. */
5408 if (user_id == (uid_t) file->details->uid) {
5409 return TRUE(!(0));
5410 }
5411
5412 /* Root is also allowed to set permissions. */
5413 if (user_id == 0) {
5414 return TRUE(!(0));
5415 }
5416
5417 /* Nobody else is allowed. */
5418 return FALSE(0);
5419 }
5420
5421 /* pretend to have full chmod rights when no info is available, relevant when
5422 * the FS can't provide ownership info, for instance for FTP */
5423 return TRUE(!(0));
5424}
5425
5426guint
5427baul_file_get_permissions (BaulFile *file)
5428{
5429 g_return_val_if_fail (baul_file_can_get_permissions (file), 0)do { if ((baul_file_can_get_permissions (file))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "baul_file_can_get_permissions (file)"
); return (0); } } while (0)
;
5430
5431 return file->details->permissions;
5432}
5433
5434/**
5435 * baul_file_set_permissions:
5436 *
5437 * Change a file's permissions. This should only be called if
5438 * baul_file_can_set_permissions returned TRUE.
5439 *
5440 * @file: BaulFile representing the file in question.
5441 * @new_permissions: New permissions value. This is the whole
5442 * set of permissions, not a delta.
5443 **/
5444void
5445baul_file_set_permissions (BaulFile *file,
5446 guint32 new_permissions,
5447 BaulFileOperationCallback callback,
5448 gpointer callback_data)
5449{
5450 GFileInfo *info;
5451
5452 if (!baul_file_can_set_permissions (file)) {
5453 GError *error;
5454
5455 /* Claim that something changed even if the permission change failed.
5456 * This makes it easier for some clients who see the "reverting"
5457 * to the old permissions as "changing back".
5458 */
5459 baul_file_changed (file);
5460 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5461 _("Not allowed to set permissions")gettext ("Not allowed to set permissions"));
5462 (* callback) (file, NULL((void*)0), error, callback_data);
5463 g_error_free (error);
5464 return;
5465 }
5466
5467 /* Test the permissions-haven't-changed case explicitly
5468 * because we don't want to send the file-changed signal if
5469 * nothing changed.
5470 */
5471 if (new_permissions == file->details->permissions) {
5472 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5473 return;
5474 }
5475
5476 // Start UNDO-REDO
5477 if (!baul_undostack_manager_is_undo_redo(baul_undostack_manager_instance())) {
5478 BaulUndoStackActionData* undo_redo_data = baul_undostack_manager_data_new (BAUL_UNDOSTACK_SETPERMISSIONS, 1);
5479 baul_undostack_manager_data_set_file_permissions(undo_redo_data, baul_file_get_uri(file), file->details->permissions, new_permissions);
5480 baul_undostack_manager_add_action (baul_undostack_manager_instance(),
5481 undo_redo_data);
5482 }
5483 // End UNDO-REDO
5484
5485 info = g_file_info_new ();
5486 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode", new_permissions);
5487 baul_file_set_attributes (file, info, callback, callback_data);
5488 g_object_unref (info);
5489}
5490
5491/**
5492 * baul_file_can_get_selinux_context:
5493 *
5494 * Check whether the selinux context for a file are determinable.
5495 * This might not be the case for files on non-UNIX file systems,
5496 * files without a context or systems that don't support selinux.
5497 *
5498 * @file: The file in question.
5499 *
5500 * Return value: TRUE if the permissions are valid.
5501 */
5502gboolean
5503baul_file_can_get_selinux_context (BaulFile *file)
5504{
5505 return file->details->selinux_context != NULL((void*)0);
5506}
5507
5508
5509/**
5510 * baul_file_get_selinux_context:
5511 *
5512 * Get a user-displayable string representing a file's selinux
5513 * context
5514 * @file: BaulFile representing the file in question.
5515 *
5516 * Returns: Newly allocated string ready to display to the user.
5517 *
5518 **/
5519char *
5520baul_file_get_selinux_context (BaulFile *file)
5521{
5522 char *translated;
5523 char *raw;
5524
5525 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
5526
5527 if (!baul_file_can_get_selinux_context (file)) {
5528 return NULL((void*)0);
5529 }
5530
5531 raw = file->details->selinux_context;
5532
5533#ifdef HAVE_SELINUX1
5534 if (selinux_raw_to_trans_context (raw, &translated) == 0) {
5535 char *tmp;
5536 tmp = g_strdup (translated)g_strdup_inline (translated);
5537 freecon (translated);
5538 translated = tmp;
5539 }
5540 else
5541#endif
5542 {
5543 translated = g_strdup (raw)g_strdup_inline (raw);
5544 }
5545
5546 return translated;
5547}
5548
5549static char *
5550get_real_name (const char *name, const char *gecos)
5551{
5552 char *locale_string, *part_before_comma, *capitalized_login_name, *real_name;
5553
5554 if (gecos == NULL((void*)0)) {
5555 return NULL((void*)0);
5556 }
5557
5558 locale_string = eel_str_strip_substring_and_after (gecos, ",");
5559 if (!g_utf8_validate (locale_string, -1, NULL((void*)0))) {
5560 part_before_comma = g_locale_to_utf8 (locale_string, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5561 g_free (locale_string);
5562 } else {
5563 part_before_comma = locale_string;
5564 }
5565
5566 if (!g_utf8_validate (name, -1, NULL((void*)0))) {
5567 locale_string = g_locale_to_utf8 (name, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5568 } else {
5569 locale_string = g_strdup (name)g_strdup_inline (name);
5570 }
5571
5572 capitalized_login_name = eel_str_capitalize (locale_string);
5573 g_free (locale_string);
5574
5575 if (capitalized_login_name == NULL((void*)0)) {
5576 real_name = part_before_comma;
5577 } else {
5578 real_name = eel_str_replace_substring
5579 (part_before_comma, "&", capitalized_login_name);
5580 g_free (part_before_comma);
5581 }
5582
5583
5584 if (eel_str_is_empty (real_name)
5585 || eel_strcmp (name, real_name) == 0
5586 || eel_strcmp (capitalized_login_name, real_name) == 0) {
5587 g_free (real_name);
5588 real_name = NULL((void*)0);
5589 }
5590
5591 g_free (capitalized_login_name);
5592
5593 return real_name;
5594}
5595
5596static gboolean
5597get_group_id_from_group_name (const char *group_name, uid_t *gid)
5598{
5599 struct group *group;
5600
5601 g_assert (gid != NULL)do { if (gid != ((void*)0)) ; else g_assertion_message_expr (
((gchar*) 0), "baul-file.c", 5601, ((const char*) (__func__))
, "gid != NULL"); } while (0)
;
5602
5603 group = getgrnam (group_name);
5604
5605 if (group == NULL((void*)0)) {
5606 return FALSE(0);
5607 }
5608
5609 *gid = group->gr_gid;
5610
5611 return TRUE(!(0));
5612}
5613
5614static gboolean
5615get_ids_from_user_name (const char *user_name, uid_t *uid, uid_t *gid)
5616{
5617 struct passwd *password_info;
5618
5619 g_assert (uid != NULL || gid != NULL)do { if (uid != ((void*)0) || gid != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 5619, ((const char*) (__func__
)), "uid != NULL || gid != NULL"); } while (0)
;
5620
5621 password_info = getpwnam (user_name);
5622
5623 if (password_info == NULL((void*)0)) {
5624 return FALSE(0);
5625 }
5626
5627 if (uid != NULL((void*)0)) {
5628 *uid = password_info->pw_uid;
5629 }
5630
5631 if (gid != NULL((void*)0)) {
5632 *gid = password_info->pw_gid;
5633 }
5634
5635 return TRUE(!(0));
5636}
5637
5638static gboolean
5639get_user_id_from_user_name (const char *user_name, uid_t *id)
5640{
5641 return get_ids_from_user_name (user_name, id, NULL((void*)0));
5642}
5643
5644static gboolean
5645get_id_from_digit_string (const char *digit_string, uid_t *id)
5646{
5647 long scanned_id;
5648 char c;
5649
5650 g_assert (id != NULL)do { if (id != ((void*)0)) ; else g_assertion_message_expr ((
(gchar*) 0), "baul-file.c", 5650, ((const char*) (__func__)),
"id != NULL"); } while (0)
;
5651
5652 /* Only accept string if it has one integer with nothing
5653 * afterwards.
5654 */
5655 if (sscanf (digit_string, "%ld%c", &scanned_id, &c) != 1) {
5656 return FALSE(0);
5657 }
5658 *id = scanned_id;
5659 return TRUE(!(0));
5660}
5661
5662/**
5663 * baul_file_can_get_owner:
5664 *
5665 * Check whether the owner a file is determinable.
5666 * This might not be the case for files on non-UNIX file systems.
5667 *
5668 * @file: The file in question.
5669 *
5670 * Return value: TRUE if the owner is valid.
5671 */
5672gboolean
5673baul_file_can_get_owner (BaulFile *file)
5674{
5675 /* Before we have info on a file, the owner is unknown. */
5676 return file->details->uid != -1;
5677}
5678
5679/**
5680 * baul_file_get_owner_name:
5681 *
5682 * Get the user name of the file's owner. If the owner has no
5683 * name, returns the userid as a string. The caller is responsible
5684 * for g_free-ing this string.
5685 *
5686 * @file: The file in question.
5687 *
5688 * Return value: A newly-allocated string.
5689 */
5690char *
5691baul_file_get_owner_name (BaulFile *file)
5692{
5693 return baul_file_get_owner_as_string (file, FALSE(0));
5694}
5695
5696/**
5697 * baul_file_can_set_owner:
5698 *
5699 * Check whether the current user is allowed to change
5700 * the owner of a file.
5701 *
5702 * @file: The file in question.
5703 *
5704 * Return value: TRUE if the current user can change the
5705 * owner of @file, FALSE otherwise. It's always possible
5706 * that when you actually try to do it, you will fail.
5707 */
5708gboolean
5709baul_file_can_set_owner (BaulFile *file)
5710{
5711 /* Not allowed to set the owner if we can't
5712 * even read it. This can happen on non-UNIX file
5713 * systems.
5714 */
5715 if (!baul_file_can_get_owner (file)) {
5716 return FALSE(0);
5717 }
5718
5719 /* Only root is also allowed to set the owner. */
5720 return geteuid() == 0;
5721}
5722
5723/**
5724 * baul_file_set_owner:
5725 *
5726 * Set the owner of a file. This will only have any effect if
5727 * baul_file_can_set_owner returns TRUE.
5728 *
5729 * @file: The file in question.
5730 * @user_name_or_id: The user name to set the owner to.
5731 * If the string does not match any user name, and the
5732 * string is an integer, the owner will be set to the
5733 * userid represented by that integer.
5734 * @callback: Function called when asynch owner change succeeds or fails.
5735 * @callback_data: Parameter passed back with callback function.
5736 */
5737void
5738baul_file_set_owner (BaulFile *file,
5739 const char *user_name_or_id,
5740 BaulFileOperationCallback callback,
5741 gpointer callback_data)
5742{
5743 GError *error;
5744 GFileInfo *info;
5745 uid_t new_id;
5746
5747 if (!baul_file_can_set_owner (file)) {
5748 /* Claim that something changed even if the permission
5749 * change failed. This makes it easier for some
5750 * clients who see the "reverting" to the old owner as
5751 * "changing back".
5752 */
5753 baul_file_changed (file);
5754 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5755 _("Not allowed to set owner")gettext ("Not allowed to set owner"));
5756 (* callback) (file, NULL((void*)0), error, callback_data);
5757 g_error_free (error);
5758 return;
5759 }
5760
5761 /* If no match treating user_name_or_id as name, try treating
5762 * it as id.
5763 */
5764 if (!get_user_id_from_user_name (user_name_or_id, &new_id)
5765 && !get_id_from_digit_string (user_name_or_id, &new_id)) {
5766 /* Claim that something changed even if the permission
5767 * change failed. This makes it easier for some
5768 * clients who see the "reverting" to the old owner as
5769 * "changing back".
5770 */
5771 baul_file_changed (file);
5772 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
5773 _("Specified owner '%s' doesn't exist")gettext ("Specified owner '%s' doesn't exist"), user_name_or_id);
5774 (* callback) (file, NULL((void*)0), error, callback_data);
5775 g_error_free (error);
5776 return;
5777 }
5778
5779 /* Test the owner-hasn't-changed case explicitly because we
5780 * don't want to send the file-changed signal if nothing
5781 * changed.
5782 */
5783 if (new_id == (uid_t) file->details->uid) {
5784 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5785 return;
5786 }
5787
5788 // Start UNDO-REDO
5789 if (!baul_undostack_manager_is_undo_redo(baul_undostack_manager_instance())) {
5790 char* current_owner = baul_file_get_owner_as_string (file, FALSE(0));
5791 BaulUndoStackActionData* undo_redo_data = baul_undostack_manager_data_new (BAUL_UNDOSTACK_CHANGEOWNER, 1);
5792 baul_undostack_manager_data_set_owner_change_information(undo_redo_data, baul_file_get_uri(file), current_owner, user_name_or_id);
5793 baul_undostack_manager_add_action (baul_undostack_manager_instance(),
5794 undo_redo_data);
5795 g_free(current_owner);
5796 }
5797 // End UNDO-REDO
5798
5799 info = g_file_info_new ();
5800 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid", new_id);
5801 baul_file_set_attributes (file, info, callback, callback_data);
5802 g_object_unref (info);
5803}
5804
5805/**
5806 * baul_get_user_names:
5807 *
5808 * Get a list of user names. For users with a different associated
5809 * "real name", the real name follows the standard user name, separated
5810 * by a carriage return. The caller is responsible for freeing this list
5811 * and its contents.
5812 */
5813GList *
5814baul_get_user_names (void)
5815{
5816 GList *list;
5817 char *name;
5818 struct passwd *user;
5819
5820 list = NULL((void*)0);
5821
5822 setpwent ();
5823
5824 while ((user = getpwent ()) != NULL((void*)0)) {
5825 char *real_name;
5826
5827 real_name = get_real_name (user->pw_name, user->pw_gecos);
5828 if (real_name != NULL((void*)0)) {
5829 name = g_strconcat (user->pw_name, "\n", real_name, NULL((void*)0));
5830 } else {
5831 name = g_strdup (user->pw_name)g_strdup_inline (user->pw_name);
5832 }
5833 g_free (real_name);
5834 list = g_list_prepend (list, name);
5835 }
5836
5837 endpwent ();
5838
5839 return eel_g_str_list_alphabetize (list);
5840}
5841
5842/**
5843 * baul_file_can_get_group:
5844 *
5845 * Check whether the group a file is determinable.
5846 * This might not be the case for files on non-UNIX file systems.
5847 *
5848 * @file: The file in question.
5849 *
5850 * Return value: TRUE if the group is valid.
5851 */
5852gboolean
5853baul_file_can_get_group (BaulFile *file)
5854{
5855 /* Before we have info on a file, the group is unknown. */
5856 return file->details->gid != -1;
5857}
5858
5859/**
5860 * baul_file_get_group_name:
5861 *
5862 * Get the name of the file's group. If the group has no
5863 * name, returns the groupid as a string. The caller is responsible
5864 * for g_free-ing this string.
5865 *
5866 * @file: The file in question.
5867 *
5868 * Return value: A newly-allocated string.
5869 **/
5870char *
5871baul_file_get_group_name (BaulFile *file)
5872{
5873 return g_strdup (file->details->group)g_strdup_inline (file->details->group);
5874}
5875
5876/**
5877 * baul_file_can_set_group:
5878 *
5879 * Check whether the current user is allowed to change
5880 * the group of a file.
5881 *
5882 * @file: The file in question.
5883 *
5884 * Return value: TRUE if the current user can change the
5885 * group of @file, FALSE otherwise. It's always possible
5886 * that when you actually try to do it, you will fail.
5887 */
5888gboolean
5889baul_file_can_set_group (BaulFile *file)
5890{
5891 uid_t user_id;
5892
5893 /* Not allowed to set the permissions if we can't
5894 * even read them. This can happen on non-UNIX file
5895 * systems.
5896 */
5897 if (!baul_file_can_get_group (file)) {
5898 return FALSE(0);
5899 }
5900
5901 /* Check the user. */
5902 user_id = geteuid();
5903
5904 /* Owner is allowed to set group (with restrictions). */
5905 if (user_id == (uid_t) file->details->uid) {
5906 return TRUE(!(0));
5907 }
5908
5909 /* Root is also allowed to set group. */
5910 if (user_id == 0) {
5911 return TRUE(!(0));
5912 }
5913
5914 /* Nobody else is allowed. */
5915 return FALSE(0);
5916}
5917
5918/* Get a list of group names, filtered to only the ones
5919 * that contain the given username. If the username is
5920 * NULL, returns a list of all group names.
5921 */
5922static GList *
5923baul_get_group_names_for_user (void)
5924{
5925 GList *list;
5926 int count, i;
5927 gid_t gid_list[NGROUPS_MAX65536 + 1];
5928 struct group *group = NULL((void*)0);
5929
5930
5931 list = NULL((void*)0);
5932
5933 count = getgroups (NGROUPS_MAX65536 + 1, gid_list);
5934 for (i = 0; i < count; i++) {
5935 group = getgrgid (gid_list[i]);
5936 if (group == NULL((void*)0))
5937 break;
5938
5939 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5940 }
5941
5942 return eel_g_str_list_alphabetize (list);
5943}
5944
5945/**
5946 * baul_get_group_names:
5947 *
5948 * Get a list of all group names.
5949 */
5950GList *
5951baul_get_all_group_names (void)
5952{
5953 GList *list;
5954 struct group *group;
5955
5956 list = NULL((void*)0);
5957
5958 setgrent ();
5959
5960 while ((group = getgrent ()) != NULL((void*)0))
5961 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5962
5963 endgrent ();
5964
5965 return eel_g_str_list_alphabetize (list);
5966}
5967
5968/**
5969 * baul_file_get_settable_group_names:
5970 *
5971 * Get a list of all group names that the current user
5972 * can set the group of a specific file to.
5973 *
5974 * @file: The BaulFile in question.
5975 */
5976GList *
5977baul_file_get_settable_group_names (BaulFile *file)
5978{
5979 uid_t user_id;
5980 GList *result;
5981
5982 if (!baul_file_can_set_group (file)) {
5983 return NULL((void*)0);
5984 }
5985
5986 /* Check the user. */
5987 user_id = geteuid();
5988
5989 if (user_id == 0) {
5990 /* Root is allowed to set group to anything. */
5991 result = baul_get_all_group_names ();
5992 } else if (user_id == (uid_t) file->details->uid) {
5993 /* Owner is allowed to set group to any that owner is member of. */
5994 result = baul_get_group_names_for_user ();
5995 } else {
5996 g_warning ("unhandled case in baul_get_settable_group_names");
5997 result = NULL((void*)0);
5998 }
5999
6000 return result;
6001}
6002
6003/**
6004 * baul_file_set_group:
6005 *
6006 * Set the group of a file. This will only have any effect if
6007 * baul_file_can_set_group returns TRUE.
6008 *
6009 * @file: The file in question.
6010 * @group_name_or_id: The group name to set the owner to.
6011 * If the string does not match any group name, and the
6012 * string is an integer, the group will be set to the
6013 * group id represented by that integer.
6014 * @callback: Function called when asynch group change succeeds or fails.
6015 * @callback_data: Parameter passed back with callback function.
6016 */
6017void
6018baul_file_set_group (BaulFile *file,
6019 const char *group_name_or_id,
6020 BaulFileOperationCallback callback,
6021 gpointer callback_data)
6022{
6023 GError *error;
6024 GFileInfo *info;
6025 uid_t new_id;
6026
6027 if (!baul_file_can_set_group (file)) {
6028 /* Claim that something changed even if the group
6029 * change failed. This makes it easier for some
6030 * clients who see the "reverting" to the old group as
6031 * "changing back".
6032 */
6033 baul_file_changed (file);
6034 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
6035 _("Not allowed to set group")gettext ("Not allowed to set group"));
6036 (* callback) (file, NULL((void*)0), error, callback_data);
6037 g_error_free (error);
6038 return;
6039 }
6040
6041 /* If no match treating group_name_or_id as name, try treating
6042 * it as id.
6043 */
6044 if (!get_group_id_from_group_name (group_name_or_id, &new_id)
6045 && !get_id_from_digit_string (group_name_or_id, &new_id)) {
6046 /* Claim that something changed even if the group
6047 * change failed. This makes it easier for some
6048 * clients who see the "reverting" to the old group as
6049 * "changing back".
6050 */
6051 baul_file_changed (file);
6052 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
6053 _("Specified group '%s' doesn't exist")gettext ("Specified group '%s' doesn't exist"), group_name_or_id);
6054 (* callback) (file, NULL((void*)0), error, callback_data);
6055 g_error_free (error);
6056 return;
6057 }
6058
6059 if (new_id == (gid_t) file->details->gid) {
6060 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
6061 return;
6062 }
6063
6064 // Start UNDO-REDO
6065 if (!baul_undostack_manager_is_undo_redo(baul_undostack_manager_instance())) {
6066 char* current_group = baul_file_get_group_name (file);
6067 BaulUndoStackActionData* undo_redo_data = baul_undostack_manager_data_new (BAUL_UNDOSTACK_CHANGEGROUP, 1);
6068 baul_undostack_manager_data_set_group_change_information(undo_redo_data, baul_file_get_uri(file), current_group, group_name_or_id);
6069 baul_undostack_manager_add_action (baul_undostack_manager_instance(),
6070 undo_redo_data);
6071 g_free(current_group);
6072 }
6073 // End UNDO-REDO
6074
6075 info = g_file_info_new ();
6076 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid", new_id);
6077 baul_file_set_attributes (file, info, callback, callback_data);
6078 g_object_unref (info);
6079}
6080
6081/**
6082 * baul_file_get_octal_permissions_as_string:
6083 *
6084 * Get a user-displayable string representing a file's permissions
6085 * as an octal number. The caller
6086 * is responsible for g_free-ing this string.
6087 * @file: BaulFile representing the file in question.
6088 *
6089 * Returns: Newly allocated string ready to display to the user.
6090 *
6091 **/
6092static char *
6093baul_file_get_octal_permissions_as_string (BaulFile *file)
6094{
6095 guint32 permissions;
6096
6097 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 6097,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
6098
6099 if (!baul_file_can_get_permissions (file)) {
6100 return NULL((void*)0);
6101 }
6102
6103 permissions = file->details->permissions;
6104 return g_strdup_printf ("%03o", permissions);
6105}
6106
6107/**
6108 * baul_file_get_permissions_as_string:
6109 *
6110 * Get a user-displayable string representing a file's permissions. The caller
6111 * is responsible for g_free-ing this string.
6112 * @file: BaulFile representing the file in question.
6113 *
6114 * Returns: Newly allocated string ready to display to the user.
6115 *
6116 **/
6117static char *
6118baul_file_get_permissions_as_string (BaulFile *file)
6119{
6120 guint32 permissions;
6121 gboolean is_directory;
6122 gboolean is_link;
6123 gboolean suid, sgid, sticky;
6124
6125 if (!baul_file_can_get_permissions (file)) {
6126 return NULL((void*)0);
6127 }
6128
6129 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 6129,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
6130
6131 permissions = file->details->permissions;
6132 is_directory = baul_file_is_directory (file);
6133 is_link = baul_file_is_symbolic_link (file);
6134
6135 /* We use ls conventions for displaying these three obscure flags */
6136 suid = permissions & S_ISUID04000;
6137 sgid = permissions & S_ISGID02000;
6138 sticky = permissions & S_ISVTX01000;
6139
6140 return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
6141 is_link ? 'l' : is_directory ? 'd' : '-',
6142 permissions & S_IRUSR0400 ? 'r' : '-',
6143 permissions & S_IWUSR0200 ? 'w' : '-',
6144 permissions & S_IXUSR0100
6145 ? (suid ? 's' : 'x')
6146 : (suid ? 'S' : '-'),
6147 permissions & S_IRGRP(0400 >> 3) ? 'r' : '-',
6148 permissions & S_IWGRP(0200 >> 3) ? 'w' : '-',
6149 permissions & S_IXGRP(0100 >> 3)
6150 ? (sgid ? 's' : 'x')
6151 : (sgid ? 'S' : '-'),
6152 permissions & S_IROTH((0400 >> 3) >> 3) ? 'r' : '-',
6153 permissions & S_IWOTH((0200 >> 3) >> 3) ? 'w' : '-',
6154 permissions & S_IXOTH((0100 >> 3) >> 3)
6155 ? (sticky ? 't' : 'x')
6156 : (sticky ? 'T' : '-'));
6157}
6158
6159/**
6160 * baul_file_get_owner_as_string:
6161 *
6162 * Get a user-displayable string representing a file's owner. The caller
6163 * is responsible for g_free-ing this string.
6164 * @file: BaulFile representing the file in question.
6165 * @include_real_name: Whether or not to append the real name (if any)
6166 * for this user after the user name.
6167 *
6168 * Returns: Newly allocated string ready to display to the user.
6169 *
6170 **/
6171static char *
6172baul_file_get_owner_as_string (BaulFile *file, gboolean include_real_name)
6173{
6174 char *user_name;
6175
6176 /* Before we have info on a file, the owner is unknown. */
6177 if (file->details->owner == NULL((void*)0) &&
6178 file->details->owner_real == NULL((void*)0)) {
6179 return NULL((void*)0);
6180 }
6181
6182 if (file->details->owner_real == NULL((void*)0)) {
6183 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6184 } else if (file->details->owner == NULL((void*)0)) {
6185 user_name = g_strdup (file->details->owner_real)g_strdup_inline (file->details->owner_real);
6186 } else if (include_real_name &&
6187 strcmp (file->details->owner, file->details->owner_real) != 0) {
6188 user_name = g_strdup_printf ("%s - %s",
6189 file->details->owner,
6190 file->details->owner_real);
6191 } else {
6192 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6193 }
6194
6195 return user_name;
6196}
6197
6198static char *
6199format_item_count_for_display (guint item_count,
6200 gboolean includes_directories,
6201 gboolean includes_files)
6202{
6203 g_assert (includes_directories || includes_files)do { if (includes_directories || includes_files) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 6203, ((const char*) (__func__
)), "includes_directories || includes_files"); } while (0)
;
6204
6205 return g_strdup_printf (includes_directories
6206 ? (includes_files
6207 ? ngettext ("%'u item", "%'u items", item_count)
6208 : ngettext ("%'u folder", "%'u folders", item_count))
6209 : ngettext ("%'u file", "%'u files", item_count), item_count);
6210}
6211
6212/**
6213 * baul_file_get_size_as_string:
6214 *
6215 * Get a user-displayable string representing a file size. The caller
6216 * is responsible for g_free-ing this string. The string is an item
6217 * count for directories.
6218 * @file: BaulFile representing the file in question.
6219 * @size_on_disk: If TRUE will return the size on disk. If FALSE return file size.
6220 *
6221 * Returns: Newly allocated string ready to display to the user.
6222 *
6223 **/
6224static char *
6225baul_file_get_size_as_string (BaulFile *file,
6226 gboolean size_on_disk)
6227{
6228 guint item_count;
6229 gboolean count_unreadable;
6230 goffset size;
6231
6232 if (file == NULL((void*)0)) {
6233 return NULL((void*)0);
6234 }
6235
6236 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 6236,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
6237
6238 if (baul_file_is_directory (file)) {
6239 if (!baul_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6240 return NULL((void*)0);
6241 }
6242 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6243 }
6244
6245 if (size_on_disk) {
6246 size = file->details->size_on_disk;
6247 } else {
6248 size = file->details->size;
6249 }
6250
6251 if (size == -1) {
6252 return NULL((void*)0);
6253 }
6254
6255 if (g_settings_get_boolean (baul_preferences, BAUL_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6256 return g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6257 else
6258 return g_format_size (size);
6259}
6260
6261/**
6262 * baul_file_get_size_as_string_with_real_size:
6263 *
6264 * Get a user-displayable string representing a file size. The caller
6265 * is responsible for g_free-ing this string. The string is an item
6266 * count for directories.
6267 * This function adds the real size in the string.
6268 * @file: BaulFile representing the file in question.
6269 *
6270 * Returns: Newly allocated string ready to display to the user.
6271 *
6272 **/
6273static char *
6274baul_file_get_size_as_string_with_real_size (BaulFile *file,
6275 gboolean size_on_disk)
6276{
6277 guint item_count;
6278 gboolean count_unreadable;
6279 goffset size;
6280 char * formatted;
6281 char * formatted_plus_real;
6282 char * real_size;
6283
6284 if (file == NULL((void*)0)) {
6285 return NULL((void*)0);
6286 }
6287
6288 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 6288,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
6289
6290 if (baul_file_is_directory (file)) {
6291 if (!baul_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6292 return NULL((void*)0);
6293 }
6294 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6295 }
6296
6297 if (size_on_disk) {
6298 size = file->details->size_on_disk;
6299 } else {
6300 size = file->details->size;
6301 }
6302
6303 if (size == -1) {
6304 return NULL((void*)0);
6305 }
6306
6307 if (g_settings_get_boolean (baul_preferences, BAUL_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6308 formatted = g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6309 else
6310 formatted = g_format_size(size);
6311
6312 /* Do this in a separate stage so that we don't have to put G_GUINT64_FORMAT in the translated string */
6313 real_size = g_strdup_printf (_("%"G_GUINT64_FORMAT)gettext ("%""lu"), (guint64) size);
6314 formatted_plus_real = g_strdup_printf (_("%s (%s bytes)")gettext ("%s (%s bytes)"), formatted, real_size);
6315 g_free (real_size);
6316 g_free (formatted);
6317 return formatted_plus_real;
6318}
6319
6320static char *
6321baul_file_get_deep_count_as_string_internal (BaulFile *file,
6322 gboolean report_size,
6323 gboolean report_size_on_disk,
6324 gboolean report_directory_count,
6325 gboolean report_file_count)
6326{
6327 BaulRequestStatus status;
6328 guint directory_count;
6329 guint file_count;
6330 guint unreadable_count;
6331 guint total_count;
6332 goffset total_size;
6333 goffset total_size_on_disk;
6334
6335 /* Can't ask for more than one of those: size, size on disk or (directory and/or file count) */
6336 g_assert (!(report_size && report_size_on_disk))do { if (!(report_size && report_size_on_disk)) ; else
g_assertion_message_expr (((gchar*) 0), "baul-file.c", 6336,
((const char*) (__func__)), "!(report_size && report_size_on_disk)"
); } while (0)
;
6337 g_assert (!(report_size && (report_directory_count || report_file_count)))do { if (!(report_size && (report_directory_count || report_file_count
))) ; else g_assertion_message_expr (((gchar*) 0), "baul-file.c"
, 6337, ((const char*) (__func__)), "!(report_size && (report_directory_count || report_file_count))"
); } while (0)
;
6338 g_assert (!(report_size_on_disk && (report_directory_count || report_file_count)))do { if (!(report_size_on_disk && (report_directory_count
|| report_file_count))) ; else g_assertion_message_expr (((gchar
*) 0), "baul-file.c", 6338, ((const char*) (__func__)), "!(report_size_on_disk && (report_directory_count || report_file_count))"
); } while (0)
;
6339
6340 /* Must ask for something */
6341 g_assert (report_size || report_size_on_disk || report_directory_count || report_file_count)do { if (report_size || report_size_on_disk || report_directory_count
|| report_file_count) ; else g_assertion_message_expr (((gchar
*) 0), "baul-file.c", 6341, ((const char*) (__func__)), "report_size || report_size_on_disk || report_directory_count || report_file_count"
); } while (0)
;
6342
6343 if (file == NULL((void*)0)) {
6344 return NULL((void*)0);
6345 }
6346
6347 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 6347,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
6348 g_assert (baul_file_is_directory (file))do { if (baul_file_is_directory (file)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 6348, ((const char*) (__func__
)), "baul_file_is_directory (file)"); } while (0)
;
6349
6350 status = baul_file_get_deep_counts (file,
6351 &directory_count,
6352 &file_count,
6353 &unreadable_count,
6354 &total_size,
6355 &total_size_on_disk,
6356 FALSE(0));
6357
6358 /* Check whether any info is available. */
6359 if (status == BAUL_REQUEST_NOT_STARTED) {
6360 return NULL((void*)0);
6361 }
6362
6363 total_count = file_count + directory_count;
6364
6365 if (total_count == 0) {
6366 switch (status) {
6367 case BAUL_REQUEST_IN_PROGRESS:
6368 /* Don't return confident "zero" until we're finished looking,
6369 * because of next case.
6370 */
6371 return NULL((void*)0);
6372 case BAUL_REQUEST_DONE:
6373 /* Don't return "zero" if we there were contents but we couldn't read them. */
6374 if (unreadable_count != 0) {
6375 return NULL((void*)0);
6376 }
6377 default: break;
6378 }
6379 }
6380
6381 /* Note that we don't distinguish the "everything was readable" case
6382 * from the "some things but not everything was readable" case here.
6383 * Callers can distinguish them using baul_file_get_deep_counts
6384 * directly if desired.
6385 */
6386 if (report_size)
6387 {
6388 if (g_settings_get_boolean (baul_preferences, BAUL_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6389 return g_format_size_full (total_size, G_FORMAT_SIZE_IEC_UNITS);
6390 else
6391 return g_format_size(total_size);
6392 }
6393
6394 if (report_size_on_disk)
6395 {
6396 if (g_settings_get_boolean (baul_preferences, BAUL_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6397 return g_format_size_full (total_size_on_disk, G_FORMAT_SIZE_IEC_UNITS);
6398 else
6399 return g_format_size (total_size_on_disk);
6400 }
6401
6402 return format_item_count_for_display (report_directory_count
6403 ? (report_file_count ? total_count : directory_count)
6404 : file_count,
6405 report_directory_count, report_file_count);
6406}
6407
6408/**
6409 * baul_file_get_deep_size_as_string:
6410 *
6411 * Get a user-displayable string representing the size of all contained
6412 * items (only makes sense for directories). The caller
6413 * is responsible for g_free-ing this string.
6414 * @file: BaulFile representing the file in question.
6415 * @size_on_disk: if TRUE will return the size on disk, else return size of file.
6416 *
6417 * Returns: Newly allocated string ready to display to the user.
6418 *
6419 **/
6420static char *
6421baul_file_get_deep_size_as_string (BaulFile *file, gboolean size_on_disk)
6422{
6423 if (size_on_disk) {
6424 return baul_file_get_deep_count_as_string_internal (file, FALSE(0), TRUE(!(0)), FALSE(0), FALSE(0));
6425 } else {
6426 return baul_file_get_deep_count_as_string_internal (file, TRUE(!(0)), FALSE(0), FALSE(0), FALSE(0));
6427 }
6428}
6429
6430/**
6431 * baul_file_get_deep_total_count_as_string:
6432 *
6433 * Get a user-displayable string representing the count of all contained
6434 * items (only makes sense for directories). The caller
6435 * is responsible for g_free-ing this string.
6436 * @file: BaulFile representing the file in question.
6437 *
6438 * Returns: Newly allocated string ready to display to the user.
6439 *
6440 **/
6441static char *
6442baul_file_get_deep_total_count_as_string (BaulFile *file)
6443{
6444 return baul_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), TRUE(!(0)));
6445}
6446
6447/**
6448 * baul_file_get_deep_file_count_as_string:
6449 *
6450 * Get a user-displayable string representing the count of all contained
6451 * items, not including directories. It only makes sense to call this
6452 * function on a directory. The caller
6453 * is responsible for g_free-ing this string.
6454 * @file: BaulFile representing the file in question.
6455 *
6456 * Returns: Newly allocated string ready to display to the user.
6457 *
6458 **/
6459static char *
6460baul_file_get_deep_file_count_as_string (BaulFile *file)
6461{
6462 return baul_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), FALSE(0), TRUE(!(0)));
6463}
6464
6465/**
6466 * baul_file_get_deep_directory_count_as_string:
6467 *
6468 * Get a user-displayable string representing the count of all contained
6469 * directories. It only makes sense to call this
6470 * function on a directory. The caller
6471 * is responsible for g_free-ing this string.
6472 * @file: BaulFile representing the file in question.
6473 *
6474 * Returns: Newly allocated string ready to display to the user.
6475 *
6476 **/
6477static char *
6478baul_file_get_deep_directory_count_as_string (BaulFile *file)
6479{
6480 return baul_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), FALSE(0));
6481}
6482
6483/**
6484 * baul_file_get_string_attribute:
6485 *
6486 * Get a user-displayable string from a named attribute. Use g_free to
6487 * free this string. If the value is unknown, returns NULL. You can call
6488 * baul_file_get_string_attribute_with_default if you want a non-NULL
6489 * default.
6490 *
6491 * @file: BaulFile representing the file in question.
6492 * @attribute_name: The name of the desired attribute. The currently supported
6493 * set includes "name", "type", "mime_type", "size", "size_on_disk", "deep_size", "deep_size_on_disk",
6494 * "deep_directory_count", "deep_file_count", "deep_total_count", "date_modified", "date_changed",
6495 * "date_accessed", "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where",
6496 * "link_target", "volume", "free_space", "selinux_context", "trashed_on", "trashed_orig_path"
6497 *
6498 * Returns: Newly allocated string ready to display to the user, or NULL
6499 * if the value is unknown or @attribute_name is not supported.
6500 *
6501 **/
6502char *
6503baul_file_get_string_attribute_q (BaulFile *file, GQuark attribute_q)
6504{
6505 char *extension_attribute;
6506
6507 if (attribute_q == attribute_name_q) {
6508 return baul_file_get_display_name (file);
6509 }
6510 if (attribute_q == attribute_type_q) {
6511 return baul_file_get_type_as_string (file);
6512 }
6513 if (attribute_q == attribute_mime_type_q) {
6514 return baul_file_get_mime_type (file);
6515 }
6516 if (attribute_q == attribute_size_q) {
6517 return baul_file_get_size_as_string (file, FALSE(0));
6518 }
6519 if (attribute_q == attribute_size_on_disk_q) {
6520 return baul_file_get_size_as_string (file, TRUE(!(0)));
6521 }
6522 if (attribute_q == attribute_size_detail_q) {
6523 return baul_file_get_size_as_string_with_real_size (file, FALSE(0));
6524 }
6525 if (attribute_q == attribute_size_on_disk_detail_q) {
6526 return baul_file_get_size_as_string_with_real_size (file, TRUE(!(0)));
6527 }
6528 if (attribute_q == attribute_deep_size_q) {
6529 return baul_file_get_deep_size_as_string (file, FALSE(0));
6530 }
6531 if (attribute_q == attribute_deep_size_on_disk_q) {
6532 return baul_file_get_deep_size_as_string (file, TRUE(!(0)));
6533 }
6534 if (attribute_q == attribute_deep_file_count_q) {
6535 return baul_file_get_deep_file_count_as_string (file);
6536 }
6537 if (attribute_q == attribute_deep_directory_count_q) {
6538 return baul_file_get_deep_directory_count_as_string (file);
6539 }
6540 if (attribute_q == attribute_deep_total_count_q) {
6541 return baul_file_get_deep_total_count_as_string (file);
6542 }
6543 if (attribute_q == attribute_trash_orig_path_q) {
6544 return baul_file_get_trash_original_file_parent_as_string (file);
6545 }
6546 if (attribute_q == attribute_date_modified_q) {
6547 return baul_file_get_date_as_string (file,
6548 BAUL_DATE_TYPE_MODIFIED);
6549 }
6550 if (attribute_q == attribute_date_changed_q) {
6551 return baul_file_get_date_as_string (file,
6552 BAUL_DATE_TYPE_CHANGED);
6553 }
6554 if (attribute_q == attribute_date_accessed_q) {
6555 return baul_file_get_date_as_string (file,
6556 BAUL_DATE_TYPE_ACCESSED);
6557 }
6558 if (attribute_q == attribute_trashed_on_q) {
6559 return baul_file_get_date_as_string (file,
6560 BAUL_DATE_TYPE_TRASHED);
6561 }
6562 if (attribute_q == attribute_date_permissions_q) {
6563 return baul_file_get_date_as_string (file,
6564 BAUL_DATE_TYPE_PERMISSIONS_CHANGED);
6565 }
6566 if (attribute_q == attribute_extension_q) {
6567 return baul_file_get_extension_as_string (file);
6568 }
6569 if (attribute_q == attribute_permissions_q) {
6570 return baul_file_get_permissions_as_string (file);
6571 }
6572 if (attribute_q == attribute_selinux_context_q) {
6573 return baul_file_get_selinux_context (file);
6574 }
6575 if (attribute_q == attribute_octal_permissions_q) {
6576 return baul_file_get_octal_permissions_as_string (file);
6577 }
6578 if (attribute_q == attribute_owner_q) {
6579 return baul_file_get_owner_as_string (file, TRUE(!(0)));
6580 }
6581 if (attribute_q == attribute_group_q) {
6582 return baul_file_get_group_name (file);
6583 }
6584 if (attribute_q == attribute_uri_q) {
6585 return baul_file_get_uri (file);
6586 }
6587 if (attribute_q == attribute_where_q) {
6588 return baul_file_get_where_string (file);
6589 }
6590 if (attribute_q == attribute_link_target_q) {
6591 return baul_file_get_symbolic_link_target_path (file);
6592 }
6593 if (attribute_q == attribute_volume_q) {
6594 return baul_file_get_volume_name (file);
6595 }
6596 if (attribute_q == attribute_free_space_q) {
6597 return baul_file_get_volume_free_space (file);
6598 }
6599
6600 extension_attribute = NULL((void*)0);
6601
6602 if (file->details->pending_extension_attributes) {
6603 extension_attribute = g_hash_table_lookup (file->details->pending_extension_attributes,
6604 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6605 }
6606
6607 if (extension_attribute == NULL((void*)0) && file->details->extension_attributes) {
6608 extension_attribute = g_hash_table_lookup (file->details->extension_attributes,
6609 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6610 }
6611
6612 return g_strdup (extension_attribute)g_strdup_inline (extension_attribute);
6613}
6614
6615char *
6616baul_file_get_string_attribute (BaulFile *file, const char *attribute_name)
6617{
6618 return baul_file_get_string_attribute_q (file, g_quark_from_string (attribute_name));
6619}
6620
6621
6622/**
6623 * baul_file_get_string_attribute_with_default:
6624 *
6625 * Get a user-displayable string from a named attribute. Use g_free to
6626 * free this string. If the value is unknown, returns a string representing
6627 * the unknown value, which varies with attribute. You can call
6628 * baul_file_get_string_attribute if you want NULL instead of a default
6629 * result.
6630 *
6631 * @file: BaulFile representing the file in question.
6632 * @attribute_name: The name of the desired attribute. See the description of
6633 * baul_file_get_string for the set of available attributes.
6634 *
6635 * Returns: Newly allocated string ready to display to the user, or a string
6636 * such as "unknown" if the value is unknown or @attribute_name is not supported.
6637 *
6638 **/
6639char *
6640baul_file_get_string_attribute_with_default_q (BaulFile *file, GQuark attribute_q)
6641{
6642 char *result;
6643 guint item_count;
6644 gboolean count_unreadable;
6645 BaulRequestStatus status;
6646
6647 result = baul_file_get_string_attribute_q (file, attribute_q);
6648 if (result != NULL((void*)0)) {
6649 return result;
6650 }
6651
6652 /* Supply default values for the ones we know about. */
6653 /* FIXME bugzilla.gnome.org 40646:
6654 * Use hash table and switch statement or function pointers for speed?
6655 */
6656 if (attribute_q == attribute_size_q) {
6657 if (!baul_file_should_show_directory_item_count (file)) {
6658 return g_strdup ("--")g_strdup_inline ("--");
6659 }
6660 count_unreadable = FALSE(0);
6661 if (baul_file_is_directory (file)) {
6662 baul_file_get_directory_item_count (file, &item_count, &count_unreadable);
6663 }
6664 return g_strdup (count_unreadable ? _("? items") : "...")g_strdup_inline (count_unreadable ? gettext ("? items") : "..."
)
;
6665 }
6666 if (attribute_q == attribute_deep_size_q) {
6667 status = baul_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6668 if (status == BAUL_REQUEST_DONE) {
6669 /* This means no contents at all were readable */
6670 return g_strdup (_("? bytes"))g_strdup_inline (gettext ("? bytes"));
6671 }
6672 return g_strdup ("...")g_strdup_inline ("...");
6673 }
6674 if (attribute_q == attribute_deep_size_on_disk_q) {
6675 status = baul_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6676 if (status == BAUL_REQUEST_DONE) {
6677 /* This means no contents at all were readable */
6678 return g_strdup (_("? bytes"))g_strdup_inline (gettext ("? bytes"));
6679 }
6680 return g_strdup ("...")g_strdup_inline ("...");
6681 }
6682 if (attribute_q == attribute_deep_file_count_q
6683 || attribute_q == attribute_deep_directory_count_q
6684 || attribute_q == attribute_deep_total_count_q) {
6685 status = baul_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6686 if (status == BAUL_REQUEST_DONE) {
6687 /* This means no contents at all were readable */
6688 return g_strdup (_("? items"))g_strdup_inline (gettext ("? items"));
6689 }
6690 return g_strdup ("...")g_strdup_inline ("...");
6691 }
6692 if (attribute_q == attribute_type_q) {
6693 return g_strdup (_("unknown type"))g_strdup_inline (gettext ("unknown type"));
6694 }
6695 if (attribute_q == attribute_mime_type_q) {
6696 return g_strdup (_("unknown MIME type"))g_strdup_inline (gettext ("unknown MIME type"));
6697 }
6698 if (attribute_q == attribute_trashed_on_q) {
6699 /* If n/a */
6700 return g_strdup ("")g_strdup_inline ("");
6701 }
6702 if (attribute_q == attribute_trash_orig_path_q) {
6703 /* If n/a */
6704 return g_strdup ("")g_strdup_inline ("");
6705 }
6706
6707 /* Fallback, use for both unknown attributes and attributes
6708 * for which we have no more appropriate default.
6709 */
6710 return g_strdup (_("unknown"))g_strdup_inline (gettext ("unknown"));
6711}
6712
6713char *
6714baul_file_get_string_attribute_with_default (BaulFile *file, const char *attribute_name)
6715{
6716 return baul_file_get_string_attribute_with_default_q (file, g_quark_from_string (attribute_name));
6717}
6718
6719gboolean
6720baul_file_is_date_sort_attribute_q (GQuark attribute_q)
6721{
6722 if (attribute_q == attribute_modification_date_q ||
6723 attribute_q == attribute_date_modified_q ||
6724 attribute_q == attribute_accessed_date_q ||
6725 attribute_q == attribute_date_accessed_q ||
6726 attribute_q == attribute_date_changed_q ||
6727 attribute_q == attribute_trashed_on_q ||
6728 attribute_q == attribute_date_permissions_q) {
6729 return TRUE(!(0));
6730 }
6731
6732 return FALSE(0);
6733}
6734
6735/**
6736 * get_description:
6737 *
6738 * Get a user-displayable string representing a file type. The caller
6739 * is responsible for g_free-ing this string.
6740 * @file: BaulFile representing the file in question.
6741 *
6742 * Returns: Newly allocated string ready to display to the user.
6743 *
6744 **/
6745static char *
6746get_description (BaulFile *file)
6747{
6748 const char *mime_type;
6749 char *description;
6750
6751 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 6751,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
6752
6753 mime_type = file->details->mime_type;
6754 if (eel_str_is_empty (mime_type)) {
6755 return NULL((void*)0);
6756 }
6757
6758 if (g_content_type_is_unknown (mime_type) &&
6759 baul_file_is_executable (file)) {
6760 return g_strdup (_("program"))g_strdup_inline (gettext ("program"));
6761 }
6762
6763 description = g_content_type_get_description (mime_type);
6764 if (!eel_str_is_empty (description)) {
6765 return description;
6766 }
6767
6768 return g_strdup (mime_type)g_strdup_inline (mime_type);
6769}
6770
6771/* Takes ownership of string */
6772static char *
6773update_description_for_link (BaulFile *file, char *string)
6774{
6775 if (baul_file_is_symbolic_link (file)) {
6776 char *res;
6777
6778 g_assert (!baul_file_is_broken_symbolic_link (file))do { if (!baul_file_is_broken_symbolic_link (file)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 6778, ((const char*) (__func__
)), "!baul_file_is_broken_symbolic_link (file)"); } while (0)
;
6779 if (string == NULL((void*)0)) {
6780 return g_strdup (_("link"))g_strdup_inline (gettext ("link"));
6781 }
6782 /* Note to localizers: convert file type string for file
6783 * (e.g. "folder", "plain text") to file type for symbolic link
6784 * to that kind of file (e.g. "link to folder").
6785 */
6786 res = g_strdup_printf (_("Link to %s")gettext ("Link to %s"), string);
6787 g_free (string);
6788 return res;
6789 }
6790
6791 return string;
6792}
6793
6794static char *
6795baul_file_get_type_as_string (BaulFile *file)
6796{
6797 if (file == NULL((void*)0)) {
6798 return NULL((void*)0);
6799 }
6800
6801 if (baul_file_is_broken_symbolic_link (file)) {
6802 return g_strdup (_("link (broken)"))g_strdup_inline (gettext ("link (broken)"));
6803 }
6804
6805 return update_description_for_link (file, get_description (file));
6806}
6807
6808/**
6809 * baul_file_get_file_type
6810 *
6811 * Return this file's type.
6812 * @file: BaulFile representing the file in question.
6813 *
6814 * Returns: The type.
6815 *
6816 **/
6817GFileType
6818baul_file_get_file_type (BaulFile *file)
6819{
6820 if (file == NULL((void*)0)) {
6821 return G_FILE_TYPE_UNKNOWN;
6822 }
6823
6824 return file->details->type;
6825}
6826
6827/**
6828 * baul_file_get_mime_type
6829 *
6830 * Return this file's default mime type.
6831 * @file: BaulFile representing the file in question.
6832 *
6833 * Returns: The mime type.
6834 *
6835 **/
6836char *
6837baul_file_get_mime_type (BaulFile *file)
6838{
6839 if (file != NULL((void*)0)) {
6840 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
6841 if (file->details->mime_type != NULL((void*)0)) {
6842 return g_strdup (file->details->mime_type)g_strdup_inline (file->details->mime_type);
6843 }
6844 }
6845 return g_strdup ("application/octet-stream")g_strdup_inline ("application/octet-stream");
6846}
6847
6848/**
6849 * baul_file_is_mime_type
6850 *
6851 * Check whether a file is of a particular MIME type, or inherited
6852 * from it.
6853 * @file: BaulFile representing the file in question.
6854 * @mime_type: The MIME-type string to test (e.g. "text/plain")
6855 *
6856 * Return value: TRUE if @mime_type exactly matches the
6857 * file's MIME type.
6858 *
6859 **/
6860gboolean
6861baul_file_is_mime_type (BaulFile *file, const char *mime_type)
6862{
6863 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
6864 g_return_val_if_fail (mime_type != NULL, FALSE)do { if ((mime_type != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "mime_type != NULL"
); return ((0)); } } while (0)
;
6865
6866 if (file->details->mime_type == NULL((void*)0)) {
6867 return FALSE(0);
6868 }
6869 return g_content_type_is_a (file->details->mime_type,
6870 mime_type);
6871}
6872
6873gboolean
6874baul_file_is_launchable (BaulFile *file)
6875{
6876 gboolean type_can_be_executable;
6877
6878 type_can_be_executable = FALSE(0);
6879 if (file->details->mime_type != NULL((void*)0)) {
6880 type_can_be_executable =
6881 g_content_type_can_be_executable (file->details->mime_type);
6882 }
6883
6884 return type_can_be_executable &&
6885 baul_file_can_get_permissions (file) &&
6886 baul_file_can_execute (file) &&
6887 baul_file_is_executable (file) &&
6888 !baul_file_is_directory (file);
6889}
6890
6891
6892/**
6893 * baul_file_get_emblem_icons
6894 *
6895 * Return the list of names of emblems that this file should display,
6896 * in canonical order.
6897 * @file: BaulFile representing the file in question.
6898 *
6899 * Returns: A list of emblem names.
6900 *
6901 **/
6902GList *
6903baul_file_get_emblem_icons (BaulFile *file,
6904 char **exclude)
6905{
6906 GList *keywords, *l;
6907 GList *icons;
6908 char *icon_names[2];
6909 char *keyword;
6910 int i;
6911 GIcon *icon;
6912
6913 if (file == NULL((void*)0)) {
6914 return NULL((void*)0);
6915 }
6916
6917 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
6918
6919 keywords = baul_file_get_keywords (file);
6920 keywords = prepend_automatic_keywords (file, keywords);
6921
6922 icons = NULL((void*)0);
6923 for (l = keywords; l != NULL((void*)0); l = l->next) {
6924 keyword = l->data;
6925
6926#ifdef TRASH_IS_FAST_ENOUGH
6927 if (strcmp (keyword, BAUL_FILE_EMBLEM_NAME_TRASH"trash") == 0) {
6928 char *uri;
6929 gboolean file_is_trash;
6930 /* Leave out the trash emblem for the trash itself, since
6931 * putting a trash emblem on a trash icon is gilding the
6932 * lily.
6933 */
6934 uri = baul_file_get_uri (file);
6935 file_is_trash = strcmp (uri, EEL_TRASH_URI"trash:") == 0;
6936 g_free (uri);
6937 if (file_is_trash) {
6938 continue;
6939 }
6940 }
6941#endif
6942 if (exclude) {
6943 for (i = 0; exclude[i] != NULL((void*)0); i++) {
6944 if (strcmp (exclude[i], keyword) == 0) {
6945 continue;
6946 }
6947 }
6948 }
6949
6950
6951 icon_names[0] = g_strconcat ("emblem-", keyword, NULL((void*)0));
6952 icon_names[1] = keyword;
6953 icon = g_themed_icon_new_from_names (icon_names, 2);
6954 g_free (icon_names[0]);
6955
6956 icons = g_list_prepend (icons, icon);
6957 }
6958
6959 g_list_free_full (keywords, g_free);
6960
6961 return icons;
6962}
6963
6964GList *
6965baul_file_get_emblem_pixbufs (BaulFile *file,
6966 int size,
6967 gboolean force_size,
6968 char **exclude)
6969{
6970 GList *icons, *l;
6971 GList *pixbufs;
6972 GdkPixbuf *pixbuf;
6973 GIcon *icon = NULL((void*)0);
6974 BaulIconInfo *icon_info = NULL((void*)0);
6975
6976 icons = baul_file_get_emblem_icons (file, exclude);
6977 pixbufs = NULL((void*)0);
6978
6979 for (l = icons; l != NULL((void*)0); l = l->next) {
6980 icon = l->data;
6981
6982 icon_info = baul_icon_info_lookup (icon, size, 1);
6983 if (force_size) {
6984 pixbuf = baul_icon_info_get_pixbuf_nodefault_at_size (icon_info, size);
6985 } else {
6986 pixbuf = baul_icon_info_get_pixbuf_nodefault (icon_info);
6987 }
6988
6989 if (pixbuf) {
6990 pixbufs = g_list_prepend (pixbufs, pixbuf);
6991 }
6992
6993
6994 g_object_unref (icon_info);
6995 g_object_unref (icon);
6996 }
6997 g_list_free (icons);
6998
6999 return g_list_reverse (pixbufs);
7000
7001
7002}
7003
7004static GList *
7005sort_keyword_list_and_remove_duplicates (GList *keywords)
7006{
7007 GList *p;
7008
7009 if (keywords != NULL((void*)0)) {
7010 GList *duplicate_link = NULL((void*)0);
7011
7012 keywords = eel_g_str_list_alphabetize (keywords);
7013
7014 p = keywords;
7015 while (p->next != NULL((void*)0)) {
7016 if (strcmp ((const char *) p->data, (const char *) p->next->data) == 0) {
7017 duplicate_link = p->next;
7018 keywords = g_list_remove_link (keywords, duplicate_link);
7019 g_list_free_full (duplicate_link, g_free);
7020 } else {
7021 p = p->next;
7022 }
7023 }
7024 }
7025
7026 return keywords;
7027}
7028
7029/**
7030 * baul_file_get_keywords
7031 *
7032 * Return this file's keywords.
7033 * @file: BaulFile representing the file in question.
7034 *
7035 * Returns: A list of keywords.
7036 *
7037 **/
7038GList *
7039baul_file_get_keywords (BaulFile *file)
7040{
7041 GList *keywords;
7042
7043 if (file == NULL((void*)0)) {
7044 return NULL((void*)0);
7045 }
7046
7047 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
7048
7049 /* Put all the keywords into a list. */
7050 keywords = baul_file_get_metadata_list
7051 (file, BAUL_METADATA_KEY_EMBLEMS"emblems");
7052
7053 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7054 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->pending_extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7055
7056 return sort_keyword_list_and_remove_duplicates (keywords);
7057}
7058
7059/**
7060 * baul_file_set_keywords
7061 *
7062 * Change this file's keywords.
7063 * @file: BaulFile representing the file in question.
7064 * @keywords: New set of keywords (a GList of strings).
7065 *
7066 **/
7067void
7068baul_file_set_keywords (BaulFile *file, GList *keywords)
7069{
7070 GList *canonical_keywords;
7071
7072 /* Invalidate the emblem compare cache */
7073 g_free (file->details->compare_by_emblem_cache);
7074 file->details->compare_by_emblem_cache = NULL((void*)0);
7075
7076 g_return_if_fail (BAUL_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return; } } while (0)
;
7077
7078 canonical_keywords = sort_keyword_list_and_remove_duplicates
7079 (g_list_copy (keywords));
7080 baul_file_set_metadata_list
7081 (file, BAUL_METADATA_KEY_EMBLEMS"emblems", canonical_keywords);
7082 g_list_free (canonical_keywords);
7083}
7084
7085/**
7086 * baul_file_is_symbolic_link
7087 *
7088 * Check if this file is a symbolic link.
7089 * @file: BaulFile representing the file in question.
7090 *
7091 * Returns: True if the file is a symbolic link.
7092 *
7093 **/
7094gboolean
7095baul_file_is_symbolic_link (BaulFile *file)
7096{
7097 return file->details->is_symlink;
7098}
7099
7100gboolean
7101baul_file_is_mountpoint (BaulFile *file)
7102{
7103 return file->details->is_mountpoint;
7104}
7105
7106GMount *
7107baul_file_get_mount (BaulFile *file)
7108{
7109 if (file->details->mount) {
7110 return g_object_ref (file->details->mount)((__typeof__ (file->details->mount)) (g_object_ref) (file
->details->mount))
;
7111 }
7112 return NULL((void*)0);
7113}
7114
7115static void
7116file_mount_unmounted (GMount *mount G_GNUC_UNUSED__attribute__ ((__unused__)),
7117 gpointer data)
7118{
7119 BaulFile *file;
7120
7121 file = BAUL_FILE (data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), (baul_file_get_type())))))
;
7122
7123 baul_file_invalidate_attributes (file, BAUL_FILE_ATTRIBUTE_MOUNT);
7124}
7125
7126void
7127baul_file_set_mount (BaulFile *file,
7128 GMount *mount)
7129{
7130 if (file->details->mount) {
7131 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file)g_signal_handlers_disconnect_matched ((file->details->mount
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (file_mount_unmounted), (file))
;
7132 g_object_unref (file->details->mount);
7133 file->details->mount = NULL((void*)0);
7134 }
7135
7136 if (mount) {
7137 file->details->mount = g_object_ref (mount)((__typeof__ (mount)) (g_object_ref) (mount));
7138 g_signal_connect (mount, "unmounted",g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
7139 G_CALLBACK (file_mount_unmounted), file)g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
;
7140 }
7141}
7142
7143/**
7144 * baul_file_is_broken_symbolic_link
7145 *
7146 * Check if this file is a symbolic link with a missing target.
7147 * @file: BaulFile representing the file in question.
7148 *
7149 * Returns: True if the file is a symbolic link with a missing target.
7150 *
7151 **/
7152gboolean
7153baul_file_is_broken_symbolic_link (BaulFile *file)
7154{
7155 if (file == NULL((void*)0)) {
7156 return FALSE(0);
7157 }
7158
7159 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
7160
7161 /* Non-broken symbolic links return the target's type for get_file_type. */
7162 return baul_file_get_file_type (file) == G_FILE_TYPE_SYMBOLIC_LINK;
7163}
7164
7165static void
7166get_fs_free_cb (GObject *source_object,
7167 GAsyncResult *res,
7168 gpointer user_data)
7169{
7170 BaulDirectory *directory;
7171 guint64 free_space;
7172 GFileInfo *info;
7173
7174 directory = BAUL_DIRECTORY (user_data)((((BaulDirectory*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), (baul_directory_get_type())))))
;
7175
7176 free_space = (guint64)-1;
7177 info = g_file_query_filesystem_info_finish (G_FILE (source_object)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_file_get_type ()))))))
,
7178 res, NULL((void*)0));
7179 if (info) {
7180 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free")) {
7181 free_space = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
7182 }
7183 g_object_unref (info);
7184 }
7185
7186 if (directory->details->free_space != free_space) {
7187 BaulFile *file;
7188
7189 directory->details->free_space = free_space;
7190 file = baul_directory_get_existing_corresponding_file (directory);
7191 if (file) {
7192 baul_file_emit_changed (file);
7193 baul_file_unref (file);
7194 }
7195 }
7196 baul_directory_unref (directory);
7197}
7198
7199/**
7200 * baul_file_get_volume_free_space
7201 * Get a nicely formatted char with free space on the file's volume
7202 * @file: BaulFile representing the file in question.
7203 *
7204 * Returns: newly-allocated copy of file size in a formatted string
7205 */
7206char *
7207baul_file_get_volume_free_space (BaulFile *file)
7208{
7209 BaulDirectory *directory;
7210 char *res;
7211 time_t now;
7212
7213 directory = baul_directory_get_for_file (file);
7214
7215 now = time (NULL((void*)0));
7216 /* Update first time and then every 2 seconds */
7217 if (directory->details->free_space_read == 0 ||
7218 (now - directory->details->free_space_read) > 2) {
7219 GFile *location;
7220
7221 directory->details->free_space_read = now;
7222 location = baul_file_get_location (file);
7223 g_file_query_filesystem_info_async (location,
7224 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free",
7225 0, NULL((void*)0),
7226 get_fs_free_cb,
7227 directory); /* Inherits ref */
7228 g_object_unref (location);
7229 } else {
7230 baul_directory_unref (directory);
7231 }
7232
7233
7234 res = NULL((void*)0);
7235
7236 if (directory->details->free_space != (guint64) -1)
7237 {
7238 if (g_settings_get_boolean (baul_preferences, BAUL_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
7239 res = g_format_size_full (directory->details->free_space, G_FORMAT_SIZE_IEC_UNITS);
7240 else
7241 res = g_format_size(directory->details->free_space);
7242 }
7243
7244 return res;
7245}
7246
7247/**
7248 * baul_file_get_volume_name
7249 * Get the path of the volume the file resides on
7250 * @file: BaulFile representing the file in question.
7251 *
7252 * Returns: newly-allocated copy of the volume name of the target file,
7253 * if the volume name isn't set, it returns the mount path of the volume
7254 */
7255char *
7256baul_file_get_volume_name (BaulFile *file)
7257{
7258 GFile *location;
7259 char *res;
7260 GMount *mount;
7261
7262 res = NULL((void*)0);
7263
7264 location = baul_file_get_location (file);
7265 mount = g_file_find_enclosing_mount (location, NULL((void*)0), NULL((void*)0));
7266 if (mount) {
7267 res = g_strdup (g_mount_get_name (mount))g_strdup_inline (g_mount_get_name (mount));
7268 g_object_unref (mount);
7269 }
7270 g_object_unref (location);
7271
7272 return res;
7273}
7274
7275/**
7276 * baul_file_get_symbolic_link_target_path
7277 *
7278 * Get the file path of the target of a symbolic link. It is an error
7279 * to call this function on a file that isn't a symbolic link.
7280 * @file: BaulFile representing the symbolic link in question.
7281 *
7282 * Returns: newly-allocated copy of the file path of the target of the symbolic link.
7283 */
7284char *
7285baul_file_get_symbolic_link_target_path (BaulFile *file)
7286{
7287 if (!baul_file_is_symbolic_link (file)) {
7288 g_warning ("File has symlink target, but is not marked as symlink");
7289 }
7290
7291 return g_strdup (file->details->symlink_name)g_strdup_inline (file->details->symlink_name);
7292}
7293
7294/**
7295 * baul_file_get_symbolic_link_target_uri
7296 *
7297 * Get the uri of the target of a symbolic link. It is an error
7298 * to call this function on a file that isn't a symbolic link.
7299 * @file: BaulFile representing the symbolic link in question.
7300 *
7301 * Returns: newly-allocated copy of the uri of the target of the symbolic link.
7302 */
7303char *
7304baul_file_get_symbolic_link_target_uri (BaulFile *file)
7305{
7306 if (!baul_file_is_symbolic_link (file)) {
7307 g_warning ("File has symlink target, but is not marked as symlink");
7308 }
7309
7310 if (file->details->symlink_name == NULL((void*)0)) {
7311 return NULL((void*)0);
7312 } else {
7313 GFile *location, *parent, *target;
7314 char *target_uri;
7315
7316 target = NULL((void*)0);
7317
7318 location = baul_file_get_location (file);
7319 parent = g_file_get_parent (location);
7320 g_object_unref (location);
7321 if (parent) {
7322 target = g_file_resolve_relative_path (parent, file->details->symlink_name);
7323 g_object_unref (parent);
7324 }
7325
7326 target_uri = NULL((void*)0);
7327 if (target) {
7328 target_uri = g_file_get_uri (target);
7329 g_object_unref (target);
7330 }
7331 return target_uri;
7332 }
7333}
7334
7335/**
7336 * baul_file_is_baul_link
7337 *
7338 * Check if this file is a "baul link", meaning a historical
7339 * baul xml link file or a desktop file.
7340 * @file: BaulFile representing the file in question.
7341 *
7342 * Returns: True if the file is a baul link.
7343 *
7344 **/
7345gboolean
7346baul_file_is_baul_link (BaulFile *file)
7347{
7348 if (file->details->mime_type == NULL((void*)0))
7349 {
7350 return FALSE(0);
7351 }
7352 return g_content_type_equals (file->details->mime_type,
7353 "application/x-desktop");
7354}
7355
7356/**
7357 * baul_file_is_directory
7358 *
7359 * Check if this file is a directory.
7360 * @file: BaulFile representing the file in question.
7361 *
7362 * Returns: TRUE if @file is a directory.
7363 *
7364 **/
7365gboolean
7366baul_file_is_directory (BaulFile *file)
7367{
7368 return baul_file_get_file_type (file) == G_FILE_TYPE_DIRECTORY;
7369}
7370
7371/**
7372 * baul_file_is_user_special_directory
7373 *
7374 * Check if this file is a special platform directory.
7375 * @file: BaulFile representing the file in question.
7376 * @special_directory: GUserDirectory representing the type to test for
7377 *
7378 * Returns: TRUE if @file is a special directory of the given kind.
7379 */
7380gboolean
7381baul_file_is_user_special_directory (BaulFile *file,
7382 GUserDirectory special_directory)
7383{
7384 gboolean is_special_dir;
7385 const gchar *special_dir;
7386
7387 special_dir = g_get_user_special_dir (special_directory);
7388 is_special_dir = FALSE(0);
7389
7390 if (special_dir) {
7391 GFile *loc;
7392 GFile *special_gfile;
7393
7394 loc = baul_file_get_location (file);
7395 special_gfile = g_file_new_for_path (special_dir);
7396 is_special_dir = g_file_equal (loc, special_gfile);
7397 g_object_unref (special_gfile);
7398 g_object_unref (loc);
7399 }
7400
7401 return is_special_dir;
7402}
7403
7404gboolean
7405baul_file_is_archive (BaulFile *file)
7406{
7407 char *mime_type;
7408 int i;
7409 static const char * archive_mime_types[] = { "application/x-gtar",
7410 "application/x-zip",
7411 "application/x-zip-compressed",
7412 "application/zip",
7413 "application/x-zip",
7414 "application/x-tar",
7415 "application/x-7z-compressed",
7416 "application/x-rar",
7417 "application/x-rar-compressed",
7418 "application/x-jar",
7419 "application/x-java-archive",
7420 "application/x-war",
7421 "application/x-ear",
7422 "application/x-arj",
7423 "application/x-gzip",
7424 "application/x-bzip-compressed-tar",
7425 "application/x-compressed-tar" };
7426
7427 g_return_val_if_fail (file != NULL, FALSE)do { if ((file != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "file != NULL"); return
((0)); } } while (0)
;
7428
7429 mime_type = baul_file_get_mime_type (file);
7430 for (i = 0; i < G_N_ELEMENTS (archive_mime_types)(sizeof (archive_mime_types) / sizeof ((archive_mime_types)[0
]))
; i++) {
7431 if (!strcmp (mime_type, archive_mime_types[i])) {
7432 g_free (mime_type);
7433 return TRUE(!(0));
7434 }
7435 }
7436 g_free (mime_type);
7437
7438 return FALSE(0);
7439}
7440
7441
7442/**
7443 * baul_file_is_in_trash
7444 *
7445 * Check if this file is a file in trash.
7446 * @file: BaulFile representing the file in question.
7447 *
7448 * Returns: TRUE if @file is in a trash.
7449 *
7450 **/
7451gboolean
7452baul_file_is_in_trash (BaulFile *file)
7453{
7454 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 7454,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
7455
7456 return baul_directory_is_in_trash (file->details->directory);
7457}
7458
7459GError *
7460baul_file_get_file_info_error (BaulFile *file)
7461{
7462 if (!file->details->get_info_failed) {
7463 return NULL((void*)0);
7464 }
7465
7466 return file->details->get_info_error;
7467}
7468
7469/**
7470 * baul_file_contains_text
7471 *
7472 * Check if this file contains text.
7473 * This is private and is used to decide whether or not to read the top left text.
7474 * @file: BaulFile representing the file in question.
7475 *
7476 * Returns: TRUE if @file has a text MIME type.
7477 *
7478 **/
7479gboolean
7480baul_file_contains_text (BaulFile *file)
7481{
7482 if (file == NULL((void*)0)) {
7483 return FALSE(0);
7484 }
7485
7486 /* All text files inherit from text/plain */
7487 return baul_file_is_mime_type (file, "text/plain");
7488}
7489
7490/**
7491 * baul_file_is_binary
7492 *
7493 * Check if this file is a binary file.
7494 * This is private and is used to decide whether or not to show the diff
7495 * button in the file conflict dialog.
7496 * @file: BaulFile representing the file in question.
7497 *
7498 * Returns: TRUE if @file is a binary file.
7499 *
7500 **/
7501gboolean
7502baul_file_is_binary (BaulFile *file)
7503{
7504 if (!baul_file_can_read(file))
7505 {
7506 return FALSE(0);
7507 }
7508
7509 gboolean is_binary = FALSE(0);
7510 int i = 0;
7511 FILE *fp;
7512
7513 /* Check the first 4096 bytes of the files. If these contains a 0,
7514 * we can assume the file is binary.
7515 * This idea is taken from python code of meld.
7516 */
7517
7518 fp = g_fopenfopen (g_file_get_path (baul_file_get_location (file)), "r");
7519 if (fp == NULL((void*)0))
7520 {
7521 return FALSE(0);
7522 }
7523
7524 while (!feof (fp)) {
7525 int c;
7526
7527 if (i > 4096) {
7528 break;
7529 }
7530 c = fgetc(fp);
7531 if (c == 0) {
7532 is_binary = TRUE(!(0));
7533 break;
7534 }
7535 i++;
7536 }
7537 fclose(fp);
7538
7539 return is_binary;
7540}
7541
7542/**
7543 * baul_file_is_executable
7544 *
7545 * Check if this file is executable at all.
7546 * @file: BaulFile representing the file in question.
7547 *
7548 * Returns: TRUE if any of the execute bits are set. FALSE if
7549 * not, or if the permissions are unknown.
7550 *
7551 **/
7552gboolean
7553baul_file_is_executable (BaulFile *file)
7554{
7555 if (!file->details->has_permissions) {
7556 /* File's permissions field is not valid.
7557 * Can't access specific permissions, so return FALSE.
7558 */
7559 return FALSE(0);
7560 }
7561
7562 return file->details->can_execute;
7563}
7564
7565/**
7566 * baul_file_peek_top_left_text
7567 *
7568 * Peek at the text from the top left of the file.
7569 * @file: BaulFile representing the file in question.
7570 *
7571 * Returns: NULL if there is no text readable, otherwise, the text.
7572 * This string is owned by the file object and should not
7573 * be kept around or freed.
7574 *
7575 **/
7576char *
7577baul_file_peek_top_left_text (BaulFile *file,
7578 gboolean need_large_text,
7579 gboolean *needs_loading)
7580{
7581 g_return_val_if_fail (BAUL_IS_FILE (file), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return (((void*)0)); }
} while (0)
;
7582
7583 if (!baul_file_should_get_top_left_text (file)) {
7584 if (needs_loading) {
7585 *needs_loading = FALSE(0);
7586 }
7587 return NULL((void*)0);
7588 }
7589
7590 if (needs_loading) {
7591 *needs_loading = !file->details->top_left_text_is_up_to_date;
7592 if (need_large_text) {
7593 *needs_loading |= file->details->got_top_left_text != file->details->got_large_top_left_text;
7594 }
7595 }
7596
7597 /* Show " ..." in the file until we read the contents in. */
7598 if (!file->details->got_top_left_text) {
7599
7600 if (baul_file_contains_text (file)) {
7601 return " ...";
7602 }
7603 return NULL((void*)0);
7604 }
7605
7606 /* Show what we read in. */
7607 return file->details->top_left_text;
7608}
7609
7610/**
7611 * baul_file_get_top_left_text
7612 *
7613 * Get the text from the top left of the file.
7614 * @file: BaulFile representing the file in question.
7615 *
7616 * Returns: NULL if there is no text readable, otherwise, the text.
7617 *
7618 **/
7619char *
7620baul_file_get_top_left_text (BaulFile *file)
7621{
7622 return g_strdup (baul_file_peek_top_left_text (file, FALSE, NULL))g_strdup_inline (baul_file_peek_top_left_text (file, (0), ((void
*)0)))
;
7623}
7624
7625char *
7626baul_file_get_filesystem_id (BaulFile *file)
7627{
7628 return g_strdup (file->details->filesystem_id)g_strdup_inline (file->details->filesystem_id);
7629}
7630
7631BaulFile *
7632baul_file_get_trash_original_file (BaulFile *file)
7633{
7634 BaulFile *original_file;
7635
7636 original_file = NULL((void*)0);
7637
7638 if (file->details->trash_orig_path != NULL((void*)0)) {
7639 GFile *location;
7640
7641 location = g_file_new_for_path (file->details->trash_orig_path);
7642 original_file = baul_file_get (location);
7643 g_object_unref (location);
7644 }
7645
7646 return original_file;
7647
7648}
7649
7650void
7651baul_file_mark_gone (BaulFile *file)
7652{
7653 BaulDirectory *directory;
7654
7655 if (file->details->is_gone)
7656 return;
7657
7658 file->details->is_gone = TRUE(!(0));
7659
7660 update_links_if_target (file);
7661
7662 /* Drop it from the symlink hash ! */
7663 remove_from_link_hash_table (file);
7664
7665 /* Let the directory know it's gone. */
7666 directory = file->details->directory;
7667 if (!baul_file_is_self_owned (file)) {
7668 baul_directory_remove_file (directory, file);
7669 }
7670
7671 baul_file_clear_info (file);
7672
7673 /* FIXME bugzilla.gnome.org 42429:
7674 * Maybe we can get rid of the name too eventually, but
7675 * for now that would probably require too many if statements
7676 * everywhere anyone deals with the name. Maybe we can give it
7677 * a hard-coded "<deleted>" name or something.
7678 */
7679}
7680
7681/**
7682 * baul_file_changed
7683 *
7684 * Notify the user that this file has changed.
7685 * @file: BaulFile representing the file in question.
7686 **/
7687void
7688baul_file_changed (BaulFile *file)
7689{
7690 GList fake_list;
7691
7692 g_return_if_fail (BAUL_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return; } } while (0)
;
7693
7694 if (baul_file_is_self_owned (file)) {
7695 baul_file_emit_changed (file);
7696 } else {
7697 fake_list.data = file;
7698 fake_list.next = NULL((void*)0);
7699 fake_list.prev = NULL((void*)0);
7700 baul_directory_emit_change_signals
7701 (file->details->directory, &fake_list);
7702 }
7703}
7704
7705/**
7706 * baul_file_updated_deep_count_in_progress
7707 *
7708 * Notify clients that a newer deep count is available for
7709 * the directory in question.
7710 */
7711void
7712baul_file_updated_deep_count_in_progress (BaulFile *file) {
7713 GList *link_files, *node;
7714
7715 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 7715,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
7716 g_assert (baul_file_is_directory (file))do { if (baul_file_is_directory (file)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 7716, ((const char*) (__func__
)), "baul_file_is_directory (file)"); } while (0)
;
7717
7718 /* Send out a signal. */
7719 g_signal_emit (file, signals[UPDATED_DEEP_COUNT_IN_PROGRESS], 0, file);
7720
7721 /* Tell link files pointing to this object about the change. */
7722 link_files = get_link_files (file);
7723 for (node = link_files; node != NULL((void*)0); node = node->next) {
7724 baul_file_updated_deep_count_in_progress (BAUL_FILE (node->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((node->data)), (baul_file_get_type())))))
);
7725 }
7726 baul_file_list_free (link_files);
7727}
7728
7729/**
7730 * baul_file_emit_changed
7731 *
7732 * Emit a file changed signal.
7733 * This can only be called by the directory, since the directory
7734 * also has to emit a files_changed signal.
7735 *
7736 * @file: BaulFile representing the file in question.
7737 **/
7738void
7739baul_file_emit_changed (BaulFile *file)
7740{
7741 GList *link_files, *p;
7742
7743 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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_assertion_message_expr (((gchar*) 0), "baul-file.c", 7743,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
7744
7745
7746 /* Invalidate the emblem compare cache. -- This is not the cleanest
7747 * place to do it but it is the one guaranteed bottleneck through
7748 * which all change notifications pass.
7749 */
7750 g_free (file->details->compare_by_emblem_cache);
7751 file->details->compare_by_emblem_cache = NULL((void*)0);
7752
7753 /* Send out a signal. */
7754 g_signal_emit (file, signals[CHANGED], 0, file);
7755
7756 /* Tell link files pointing to this object about the change. */
7757 link_files = get_link_files (file);
7758 for (p = link_files; p != NULL((void*)0); p = p->next) {
7759 if (p->data != file) {
7760 baul_file_changed (BAUL_FILE (p->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((p->data)), (baul_file_get_type())))))
);
7761 }
7762 }
7763 baul_file_list_free (link_files);
7764}
7765
7766/**
7767 * baul_file_is_gone
7768 *
7769 * Check if a file has already been deleted.
7770 * @file: BaulFile representing the file in question.
7771 *
7772 * Returns: TRUE if the file is already gone.
7773 **/
7774gboolean
7775baul_file_is_gone (BaulFile *file)
7776{
7777 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
7778
7779 return file->details->is_gone;
7780}
7781
7782/**
7783 * baul_file_is_not_yet_confirmed
7784 *
7785 * Check if we're in a state where we don't know if a file really
7786 * exists or not, before the initial I/O is complete.
7787 * @file: BaulFile representing the file in question.
7788 *
7789 * Returns: TRUE if the file is already gone.
7790 **/
7791gboolean
7792baul_file_is_not_yet_confirmed (BaulFile *file)
7793{
7794 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
7795
7796 return !file->details->got_file_info;
7797}
7798
7799/**
7800 * baul_file_check_if_ready
7801 *
7802 * Check whether the values for a set of file attributes are
7803 * currently available, without doing any additional work. This
7804 * is useful for callers that want to reflect updated information
7805 * when it is ready but don't want to force the work required to
7806 * obtain the information, which might be slow network calls, e.g.
7807 *
7808 * @file: The file being queried.
7809 * @file_attributes: A bit-mask with the desired information.
7810 *
7811 * Return value: TRUE if all of the specified attributes are currently readable.
7812 */
7813gboolean
7814baul_file_check_if_ready (BaulFile *file,
7815 BaulFileAttributes file_attributes)
7816{
7817 /* To be parallel with call_when_ready, return
7818 * TRUE for NULL file.
7819 */
7820 if (file == NULL((void*)0)) {
7821 return TRUE(!(0));
7822 }
7823
7824 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
7825
7826 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->check_if_ready
) (file, file_attributes))
7827 (BAUL_FILE_CLASS, file,(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->check_if_ready
) (file, file_attributes))
7828 check_if_ready, (file, file_attributes))(((((BaulFileClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((((((GObjectClass*) (((GTypeInstance*) ((file)))->g_class
)))))), (baul_file_get_type())))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->check_if_ready
) (file, file_attributes))
;
7829}
7830
7831void
7832baul_file_call_when_ready (BaulFile *file,
7833 BaulFileAttributes file_attributes,
7834 BaulFileCallback callback,
7835 gpointer callback_data)
7836
7837{
7838 if (file == NULL((void*)0)) {
7839 (* callback) (file, callback_data);
7840 return;
7841 }
7842
7843 g_return_if_fail (BAUL_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return; } } while (0)
;
7844
7845 EEL_CALL_METHODdo { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->call_when_ready
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7846 (BAUL_FILE_CLASS, file,do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->call_when_ready
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7847 call_when_ready, (file, file_attributes,do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->call_when_ready
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7848 callback, callback_data))do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->call_when_ready
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
;
7849}
7850
7851void
7852baul_file_cancel_call_when_ready (BaulFile *file,
7853 BaulFileCallback callback,
7854 gpointer callback_data)
7855{
7856 g_return_if_fail (callback != NULL)do { if ((callback != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "callback != NULL"
); return; } } while (0)
;
7857
7858 if (file == NULL((void*)0)) {
7859 return;
7860 }
7861
7862 g_return_if_fail (BAUL_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return; } } while (0)
;
7863
7864 EEL_CALL_METHODdo { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
7865 (BAUL_FILE_CLASS, file,do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
7866 cancel_call_when_ready, (file, callback, callback_data))do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
;
7867}
7868
7869static void
7870invalidate_directory_count (BaulFile *file)
7871{
7872 file->details->directory_count_is_up_to_date = FALSE(0);
7873}
7874
7875static void
7876invalidate_deep_counts (BaulFile *file)
7877{
7878 file->details->deep_counts_status = BAUL_REQUEST_NOT_STARTED;
7879}
7880
7881static void
7882invalidate_mime_list (BaulFile *file)
7883{
7884 file->details->mime_list_is_up_to_date = FALSE(0);
7885}
7886
7887static void
7888invalidate_top_left_text (BaulFile *file)
7889{
7890 file->details->top_left_text_is_up_to_date = FALSE(0);
7891}
7892
7893static void
7894invalidate_file_info (BaulFile *file)
7895{
7896 file->details->file_info_is_up_to_date = FALSE(0);
7897}
7898
7899static void
7900invalidate_link_info (BaulFile *file)
7901{
7902 file->details->link_info_is_up_to_date = FALSE(0);
7903}
7904
7905static void
7906invalidate_thumbnail (BaulFile *file)
7907{
7908 file->details->thumbnail_is_up_to_date = FALSE(0);
7909}
7910
7911static void
7912invalidate_mount (BaulFile *file)
7913{
7914 file->details->mount_is_up_to_date = FALSE(0);
7915}
7916
7917void
7918baul_file_invalidate_extension_info_internal (BaulFile *file)
7919{
7920 if (file->details->pending_info_providers)
7921 g_list_free_full (file->details->pending_info_providers, g_object_unref);
7922
7923 file->details->pending_info_providers =
7924 baul_extensions_get_for_type (BAUL_TYPE_INFO_PROVIDER(baul_info_provider_get_type ()));
7925}
7926
7927void
7928baul_file_invalidate_attributes_internal (BaulFile *file,
7929 BaulFileAttributes file_attributes)
7930{
7931 Request request;
7932
7933 if (file == NULL((void*)0)) {
7934 return;
7935 }
7936
7937 if (BAUL_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (baul_desktop_icon_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; }))))
) {
7938 /* Desktop icon files are always up to date.
7939 * If we invalidate their attributes they
7940 * will lose data, so we just ignore them.
7941 */
7942 return;
7943 }
7944
7945 request = baul_directory_set_up_request (file_attributes);
7946
7947 if (REQUEST_WANTS_TYPE (request, REQUEST_DIRECTORY_COUNT)((request) & (1<<(REQUEST_DIRECTORY_COUNT)))) {
7948 invalidate_directory_count (file);
7949 }
7950 if (REQUEST_WANTS_TYPE (request, REQUEST_DEEP_COUNT)((request) & (1<<(REQUEST_DEEP_COUNT)))) {
7951 invalidate_deep_counts (file);
7952 }
7953 if (REQUEST_WANTS_TYPE (request, REQUEST_MIME_LIST)((request) & (1<<(REQUEST_MIME_LIST)))) {
7954 invalidate_mime_list (file);
7955 }
7956 if (REQUEST_WANTS_TYPE (request, REQUEST_FILE_INFO)((request) & (1<<(REQUEST_FILE_INFO)))) {
7957 invalidate_file_info (file);
7958 }
7959 if (REQUEST_WANTS_TYPE (request, REQUEST_TOP_LEFT_TEXT)((request) & (1<<(REQUEST_TOP_LEFT_TEXT)))) {
7960 invalidate_top_left_text (file);
7961 }
7962 if (REQUEST_WANTS_TYPE (request, REQUEST_LINK_INFO)((request) & (1<<(REQUEST_LINK_INFO)))) {
7963 invalidate_link_info (file);
7964 }
7965 if (REQUEST_WANTS_TYPE (request, REQUEST_EXTENSION_INFO)((request) & (1<<(REQUEST_EXTENSION_INFO)))) {
7966 baul_file_invalidate_extension_info_internal (file);
7967 }
7968 if (REQUEST_WANTS_TYPE (request, REQUEST_THUMBNAIL)((request) & (1<<(REQUEST_THUMBNAIL)))) {
7969 invalidate_thumbnail (file);
7970 }
7971 if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)((request) & (1<<(REQUEST_MOUNT)))) {
7972 invalidate_mount (file);
7973 }
7974
7975 /* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */
7976}
7977
7978gboolean
7979baul_file_has_open_window (BaulFile *file)
7980{
7981 return file->details->has_open_window;
7982}
7983
7984void
7985baul_file_set_has_open_window (BaulFile *file,
7986 gboolean has_open_window)
7987{
7988 has_open_window = (has_open_window != FALSE(0));
7989
7990 if (file->details->has_open_window != has_open_window) {
7991 file->details->has_open_window = has_open_window;
7992 baul_file_changed (file);
7993 }
7994}
7995
7996
7997gboolean
7998baul_file_is_thumbnailing (BaulFile *file)
7999{
8000 g_return_val_if_fail (BAUL_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return ((0)); } } while
(0)
;
8001
8002 return file->details->is_thumbnailing;
8003}
8004
8005void
8006baul_file_set_is_thumbnailing (BaulFile *file,
8007 gboolean is_thumbnailing)
8008{
8009 g_return_if_fail (BAUL_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_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 (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_FILE (file)"); return; } } while (0)
;
8010
8011 file->details->is_thumbnailing = is_thumbnailing;
8012}
8013
8014
8015/**
8016 * baul_file_invalidate_attributes
8017 *
8018 * Invalidate the specified attributes and force a reload.
8019 * @file: BaulFile representing the file in question.
8020 * @file_attributes: attributes to froget.
8021 **/
8022
8023void
8024baul_file_invalidate_attributes (BaulFile *file,
8025 BaulFileAttributes file_attributes)
8026{
8027 /* Cancel possible in-progress loads of any of these attributes */
8028 baul_directory_cancel_loading_file_attributes (file->details->directory,
8029 file,
8030 file_attributes);
8031
8032 /* Actually invalidate the values */
8033 baul_file_invalidate_attributes_internal (file, file_attributes);
8034
8035 baul_directory_add_file_to_work_queue (file->details->directory, file);
8036
8037 /* Kick off I/O if necessary */
8038 baul_directory_async_state_changed (file->details->directory);
8039}
8040
8041BaulFileAttributes
8042baul_file_get_all_attributes (void)
8043{
8044 return BAUL_FILE_ATTRIBUTE_INFO |
8045 BAUL_FILE_ATTRIBUTE_LINK_INFO |
8046 BAUL_FILE_ATTRIBUTE_DEEP_COUNTS |
8047 BAUL_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
8048 BAUL_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES |
8049 BAUL_FILE_ATTRIBUTE_TOP_LEFT_TEXT |
8050 BAUL_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT |
8051 BAUL_FILE_ATTRIBUTE_EXTENSION_INFO |
8052 BAUL_FILE_ATTRIBUTE_THUMBNAIL |
8053 BAUL_FILE_ATTRIBUTE_MOUNT;
8054}
8055
8056void
8057baul_file_invalidate_all_attributes (BaulFile *file)
8058{
8059 BaulFileAttributes all_attributes;
8060
8061 all_attributes = baul_file_get_all_attributes ();
8062 baul_file_invalidate_attributes (file, all_attributes);
8063}
8064
8065
8066/**
8067 * baul_file_dump
8068 *
8069 * Debugging call, prints out the contents of the file
8070 * fields.
8071 *
8072 * @file: file to dump.
8073 **/
8074void
8075baul_file_dump (BaulFile *file)
8076{
8077 long size = file->details->deep_size;
8078 long size_on_disk = file->details->deep_size_on_disk;
8079 char *uri;
8080 const char *file_kind;
8081
8082 uri = baul_file_get_uri (file);
8083 g_print ("uri: %s \n", uri);
8084 if (!file->details->got_file_info) {
8085 g_print ("no file info \n");
8086 } else if (file->details->get_info_failed) {
8087 g_print ("failed to get file info \n");
8088 } else {
8089 g_print ("size: %ld \n", size);
8090 g_print ("disk size: %ld \n", size_on_disk);
8091 switch (file->details->type) {
8092 case G_FILE_TYPE_REGULAR:
8093 file_kind = "regular file";
8094 break;
8095 case G_FILE_TYPE_DIRECTORY:
8096 file_kind = "folder";
8097 break;
8098 case G_FILE_TYPE_SPECIAL:
8099 file_kind = "special";
8100 break;
8101 case G_FILE_TYPE_SYMBOLIC_LINK:
8102 file_kind = "symbolic link";
8103 break;
8104 case G_FILE_TYPE_UNKNOWN:
8105 default:
8106 file_kind = "unknown";
8107 break;
8108 }
8109 g_print ("kind: %s \n", file_kind);
8110 if (file->details->type == G_FILE_TYPE_SYMBOLIC_LINK) {
8111 g_print ("link to %s \n", file->details->symlink_name);
8112 /* FIXME bugzilla.gnome.org 42430: add following of symlinks here */
8113 }
8114 /* FIXME bugzilla.gnome.org 42431: add permissions and other useful stuff here */
8115 }
8116 g_free (uri);
8117}
8118
8119/**
8120 * baul_file_list_ref
8121 *
8122 * Ref all the files in a list.
8123 * @list: GList of files.
8124 **/
8125GList *
8126baul_file_list_ref (GList *list)
8127{
8128 g_list_foreach (list, (GFunc) baul_file_ref, NULL((void*)0));
8129 return list;
8130}
8131
8132/**
8133 * baul_file_list_unref
8134 *
8135 * Unref all the files in a list.
8136 * @list: GList of files.
8137 **/
8138void
8139baul_file_list_unref (GList *list)
8140{
8141 g_list_foreach (list, (GFunc) baul_file_unref, NULL((void*)0));
8142}
8143
8144/**
8145 * baul_file_list_free
8146 *
8147 * Free a list of files after unrefing them.
8148 * @list: GList of files.
8149 **/
8150void
8151baul_file_list_free (GList *list)
8152{
8153 baul_file_list_unref (list);
8154 g_list_free (list);
8155}
8156
8157/**
8158 * baul_file_list_copy
8159 *
8160 * Copy the list of files, making a new ref of each,
8161 * @list: GList of files.
8162 **/
8163GList *
8164baul_file_list_copy (GList *list)
8165{
8166 return g_list_copy (baul_file_list_ref (list));
8167}
8168
8169static gboolean
8170get_attributes_for_default_sort_type (BaulFile *file,
8171 gboolean *is_download,
8172 gboolean *is_trash)
8173{
8174 gboolean is_download_dir, is_desktop_dir, is_trash_dir, retval;
8175
8176 *is_download = FALSE(0);
8177 *is_trash = FALSE(0);
8178 retval = FALSE(0);
8179
8180 /* special handling for certain directories */
8181 if (file && baul_file_is_directory (file)) {
8182 is_download_dir =
8183 baul_file_is_user_special_directory (file, G_USER_DIRECTORY_DOWNLOAD);
8184 is_desktop_dir =
8185 baul_file_is_user_special_directory (file, G_USER_DIRECTORY_DESKTOP);
8186 is_trash_dir =
8187 baul_file_is_in_trash (file);
8188
8189 if (is_download_dir && !is_desktop_dir) {
8190 *is_download = TRUE(!(0));
8191 retval = TRUE(!(0));
8192 } else if (is_trash_dir) {
8193 *is_trash = TRUE(!(0));
8194 retval = TRUE(!(0));
8195 }
8196 }
8197
8198 return retval;
8199}
8200
8201BaulFileSortType
8202baul_file_get_default_sort_type (BaulFile *file,
8203 gboolean *reversed)
8204{
8205 BaulFileSortType retval;
8206 gboolean is_download, is_trash, res;
8207
8208 retval = BAUL_FILE_SORT_NONE;
8209 is_download = is_trash = FALSE(0);
8210 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8211
8212 if (res) {
8213 if (is_download) {
8214 retval = BAUL_FILE_SORT_BY_MTIME;
8215 } else if (is_trash) {
8216 retval = BAUL_FILE_SORT_BY_TRASHED_TIME;
8217 }
8218
8219 if (reversed != NULL((void*)0)) {
8220 *reversed = res;
8221 }
8222 }
8223
8224 return retval;
8225}
8226
8227const gchar *
8228baul_file_get_default_sort_attribute (BaulFile *file,
8229 gboolean *reversed)
8230{
8231 const gchar *retval;
8232 gboolean is_download, is_trash, res;
8233
8234 retval = NULL((void*)0);
8235 is_download = is_trash = FALSE(0);
8236 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8237
8238 if (res) {
8239 if (is_download) {
8240 retval = g_quark_to_string (attribute_date_modified_q);
8241 } else if (is_trash) {
8242 retval = g_quark_to_string (attribute_trashed_on_q);
8243 }
8244
8245 if (reversed != NULL((void*)0)) {
8246 *reversed = res;
8247 }
8248 }
8249
8250 return retval;
8251}
8252
8253static int
8254compare_by_display_name_cover (gconstpointer a, gconstpointer b)
8255{
8256 return compare_by_display_name (BAUL_FILE (a)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((a)), (baul_file_get_type())))))
, BAUL_FILE (b)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((b)), (baul_file_get_type())))))
);
8257}
8258
8259/**
8260 * baul_file_list_sort_by_display_name
8261 *
8262 * Sort the list of files by file name.
8263 * @list: GList of files.
8264 **/
8265GList *
8266baul_file_list_sort_by_display_name (GList *list)
8267{
8268 return g_list_sort (list, compare_by_display_name_cover);
8269}
8270
8271static GList *ready_data_list = NULL((void*)0);
8272
8273typedef struct
8274{
8275 GList *file_list;
8276 GList *remaining_files;
8277 BaulFileListCallback callback;
8278 gpointer callback_data;
8279} FileListReadyData;
8280
8281static void
8282file_list_ready_data_free (FileListReadyData *data)
8283{
8284 GList *l;
8285
8286 l = g_list_find (ready_data_list, data);
8287 if (l != NULL((void*)0)) {
8288 ready_data_list = g_list_delete_link (ready_data_list, l);
8289
8290 baul_file_list_free (data->file_list);
8291 g_list_free (data->remaining_files);
8292 g_free (data);
8293 }
8294}
8295
8296static FileListReadyData *
8297file_list_ready_data_new (GList *file_list,
8298 BaulFileListCallback callback,
8299 gpointer callback_data)
8300{
8301 FileListReadyData *data;
8302
8303 data = g_new0 (FileListReadyData, 1)((FileListReadyData *) g_malloc0_n ((1), sizeof (FileListReadyData
)))
;
8304 data->file_list = baul_file_list_copy (file_list);
8305 data->remaining_files = g_list_copy (file_list);
8306 data->callback = callback;
8307 data->callback_data = callback_data;
8308
8309 ready_data_list = g_list_prepend (ready_data_list, data);
8310
8311 return data;
8312}
8313
8314static void
8315file_list_file_ready_callback (BaulFile *file,
8316 gpointer user_data)
8317{
8318 FileListReadyData *data;
8319
8320 data = user_data;
8321 data->remaining_files = g_list_remove (data->remaining_files, file);
8322
8323 if (data->remaining_files == NULL((void*)0)) {
8324 if (data->callback) {
8325 (*data->callback) (data->file_list, data->callback_data);
8326 }
8327
8328 file_list_ready_data_free (data);
8329 }
8330}
8331
8332void
8333baul_file_list_call_when_ready (GList *file_list,
8334 BaulFileAttributes attributes,
8335 BaulFileListHandle **handle,
8336 BaulFileListCallback callback,
8337 gpointer callback_data)
8338{
8339 GList *l;
8340 FileListReadyData *data;
8341 BaulFile *file = NULL((void*)0);
8342
8343 g_return_if_fail (file_list != NULL)do { if ((file_list != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "file_list != NULL"
); return; } } while (0)
;
8344
8345 data = file_list_ready_data_new
8346 (file_list, callback, callback_data);
8347
8348 if (handle) {
8349 *handle = (BaulFileListHandle *) data;
8350 }
8351
8352
8353 l = file_list;
8354 while (l != NULL((void*)0)) {
8355 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
8356 /* Need to do this here, as the list can be modified by this call */
8357 l = l->next;
8358
8359 if (file)
8360 baul_file_call_when_ready (file,
8361 attributes,
8362 file_list_file_ready_callback,
8363 data);
8364 }
8365}
8366
8367void
8368baul_file_list_cancel_call_when_ready (BaulFileListHandle *handle)
8369{
8370 GList *l;
8371 FileListReadyData *data;
8372
8373 g_return_if_fail (handle != NULL)do { if ((handle != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "handle != NULL")
; return; } } while (0)
;
8374
8375 data = (FileListReadyData *) handle;
8376
8377 l = g_list_find (ready_data_list, data);
8378 if (l != NULL((void*)0)) {
8379 BaulFile *file = NULL((void*)0);
8380
8381 for (l = data->remaining_files; l != NULL((void*)0); l = l->next) {
8382 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
8383
8384 EEL_CALL_METHODdo { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
8385 (BAUL_FILE_CLASS, file,do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
8386 cancel_call_when_ready, (file, file_list_file_ready_callback, data))do { if (((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((BaulFileClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((((((GObjectClass*) (((GTypeInstance*) ((file
)))->g_class)))))), (baul_file_get_type())))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
;
8387 }
8388
8389 file_list_ready_data_free (data);
8390 }
8391}
8392
8393static char *
8394try_to_make_utf8 (const char *text, int *length)
8395{
8396 static const char *encodings_to_try[2];
8397 static int n_encodings_to_try = 0;
8398 gsize converted_length;
8399 GError *conversion_error;
8400 char *utf8_text;
8401 int i;
8402
8403 if (n_encodings_to_try == 0) {
8404 const char *charset;
8405 gboolean charset_is_utf8;
8406
8407 charset_is_utf8 = g_get_charset (&charset);
8408 if (!charset_is_utf8) {
8409 encodings_to_try[n_encodings_to_try++] = charset;
8410 }
8411
8412 if (g_ascii_strcasecmp (charset, "ISO-8859-1") != 0) {
8413 encodings_to_try[n_encodings_to_try++] = "ISO-8859-1";
8414 }
8415 }
8416
8417 utf8_text = NULL((void*)0);
8418 for (i = 0; i < n_encodings_to_try; i++) {
8419 conversion_error = NULL((void*)0);
8420 utf8_text = g_convert (text, *length,
8421 "UTF-8", encodings_to_try[i],
8422 NULL((void*)0), &converted_length, &conversion_error);
8423 if (utf8_text != NULL((void*)0)) {
8424 *length = converted_length;
8425 break;
8426 }
8427 g_error_free (conversion_error);
8428 }
8429
8430 return utf8_text;
8431}
8432
8433
8434
8435/* Extract the top left part of the read-in text. */
8436char *
8437baul_extract_top_left_text (const char *text,
8438 gboolean large,
8439 int length)
8440{
8441 GString* buffer;
8442 const gchar *in;
8443 const gchar *end;
8444 int line, i;
8445 gunichar c;
8446 char *text_copy;
8447 const char *utf8_end;
8448 gboolean validated;
8449 int max_bytes, max_lines, max_cols;
8450
8451 if (large) {
8452 max_bytes = BAUL_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_BYTES10000;
8453 max_lines = BAUL_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_LINES24;
8454 max_cols = BAUL_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE80;
8455 } else {
8456 max_bytes = BAUL_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES1024;
8457 max_lines = BAUL_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES5;
8458 max_cols = BAUL_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE10;
8459 }
8460
8461
8462
8463 text_copy = NULL((void*)0);
8464 if (text != NULL((void*)0)) {
8465 /* Might be a partial utf8 character at the end if we didn't read whole file */
8466 validated = g_utf8_validate (text, length, &utf8_end);
8467 if (!validated &&
8468 !(length >= max_bytes &&
8469 text + length - utf8_end < 6)) {
8470 text_copy = try_to_make_utf8 (text, &length);
8471 text = text_copy;
8472 } else if (!validated) {
8473 length = utf8_end - text;
8474 }
8475 }
8476
8477 if (text == NULL((void*)0) || length == 0) {
8478 return NULL((void*)0);
8479 }
8480
8481 buffer = g_string_new ("");
8482 end = text + length; in = text;
8483
8484 for (line = 0; line < max_lines; line++) {
8485 /* Extract one line. */
8486 for (i = 0; i < max_cols; ) {
8487 if (*in == '\n') {
8488 break;
8489 }
8490
8491 c = g_utf8_get_char (in);
8492
8493 if (g_unichar_isprint (c)) {
8494 g_string_append_unichar (buffer, c);
8495 i++;
8496 }
8497
8498 in = g_utf8_next_char (in)((in) + g_utf8_skip[*(const guchar *)(in)]);
8499 if (in == end) {
8500 goto done;
8501 }
8502 }
8503
8504 /* Skip the rest of the line. */
8505 while (*in != '\n') {
8506 if (++in == end) {
8507 goto done;
8508 }
8509 }
8510 if (++in == end) {
8511 goto done;
8512 }
8513
8514 /* Put a new-line separator in. */
8515 g_string_append_c(buffer, '\n')g_string_append_c_inline (buffer, '\n');
8516 }
8517 done:
8518 g_free (text_copy);
8519
8520 return g_string_free(buffer, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((buffer
), ((0))) : g_string_free_and_steal (buffer)) : (g_string_free
) ((buffer), ((0))))
;
8521}
8522
8523static void
8524thumbnail_limit_changed_callback (gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
8525{
8526 g_settings_get (baul_preferences,
8527 BAUL_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT"thumbnail-limit",
8528 "t", &cached_thumbnail_limit);
8529
8530 /* Tell the world that icons might have changed. We could invent a narrower-scope
8531 * signal to mean only "thumbnails might have changed" if this ends up being slow
8532 * for some reason.
8533 */
8534 emit_change_signals_for_all_files_in_all_directories ();
8535}
8536
8537static void
8538thumbnail_size_changed_callback (gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
8539{
8540 cached_thumbnail_size = g_settings_get_int (baul_icon_view_preferences, BAUL_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE"thumbnail-size");
8541
8542 /* Tell the world that icons might have changed. We could invent a narrower-scope
8543 * signal to mean only "thumbnails might have changed" if this ends up being slow
8544 * for some reason.
8545 */
8546 emit_change_signals_for_all_files_in_all_directories ();
8547}
8548
8549static void
8550show_thumbnails_changed_callback (gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
8551{
8552 show_image_thumbs = g_settings_get_enum (baul_preferences, BAUL_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS"show-image-thumbnails");
8553
8554 /* Tell the world that icons might have changed. We could invent a narrower-scope
8555 * signal to mean only "thumbnails might have changed" if this ends up being slow
8556 * for some reason.
8557 */
8558 emit_change_signals_for_all_files_in_all_directories ();
8559}
8560
8561static void
8562mime_type_data_changed_callback (GObject *signaller G_GNUC_UNUSED__attribute__ ((__unused__)),
8563 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
8564{
8565 /* Tell the world that icons might have changed. We could invent a narrower-scope
8566 * signal to mean only "thumbnails might have changed" if this ends up being slow
8567 * for some reason.
8568 */
8569 emit_change_signals_for_all_files_in_all_directories ();
8570}
8571
8572static void
8573icon_theme_changed_callback (CtkIconTheme *icon_theme G_GNUC_UNUSED__attribute__ ((__unused__)),
8574 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
8575{
8576 /* Clear all pixmap caches as the icon => pixmap lookup changed */
8577 baul_icon_info_clear_caches ();
8578
8579 /* Tell the world that icons might have changed. We could invent a narrower-scope
8580 * signal to mean only "thumbnails might have changed" if this ends up being slow
8581 * for some reason.
8582 */
8583 emit_change_signals_for_all_files_in_all_directories ();
8584}
8585
8586static void
8587baul_file_class_init (BaulFileClass *class)
8588{
8589 CtkIconTheme *icon_theme;
8590
8591 baul_file_info_getter = baul_file_get_internal;
8592
8593 attribute_name_q = g_quark_from_static_string ("name");
8594 attribute_size_q = g_quark_from_static_string ("size");
8595 attribute_size_on_disk_q = g_quark_from_static_string ("size_on_disk");
8596 attribute_type_q = g_quark_from_static_string ("type");
8597 attribute_modification_date_q = g_quark_from_static_string ("modification_date");
8598 attribute_date_modified_q = g_quark_from_static_string ("date_modified");
8599 attribute_accessed_date_q = g_quark_from_static_string ("accessed_date");
8600 attribute_date_accessed_q = g_quark_from_static_string ("date_accessed");
8601 attribute_emblems_q = g_quark_from_static_string ("emblems");
8602 attribute_extension_q = g_quark_from_static_string ("extension");
8603 attribute_mime_type_q = g_quark_from_static_string ("mime_type");
8604 attribute_size_detail_q = g_quark_from_static_string ("size_detail");
8605 attribute_size_on_disk_detail_q = g_quark_from_static_string ("size_on_disk_detail");
8606 attribute_deep_size_q = g_quark_from_static_string ("deep_size");
8607 attribute_deep_size_on_disk_q = g_quark_from_static_string ("deep_size_on_disk");
8608 attribute_deep_file_count_q = g_quark_from_static_string ("deep_file_count");
8609 attribute_deep_directory_count_q = g_quark_from_static_string ("deep_directory_count");
8610 attribute_deep_total_count_q = g_quark_from_static_string ("deep_total_count");
8611 attribute_date_changed_q = g_quark_from_static_string ("date_changed");
8612 attribute_trashed_on_q = g_quark_from_static_string ("trashed_on");
8613 attribute_trash_orig_path_q = g_quark_from_static_string ("trash_orig_path");
8614 attribute_date_permissions_q = g_quark_from_static_string ("date_permissions");
8615 attribute_permissions_q = g_quark_from_static_string ("permissions");
8616 attribute_selinux_context_q = g_quark_from_static_string ("selinux_context");
8617 attribute_octal_permissions_q = g_quark_from_static_string ("octal_permissions");
8618 attribute_owner_q = g_quark_from_static_string ("owner");
8619 attribute_group_q = g_quark_from_static_string ("group");
8620 attribute_uri_q = g_quark_from_static_string ("uri");
8621 attribute_where_q = g_quark_from_static_string ("where");
8622 attribute_link_target_q = g_quark_from_static_string ("link_target");
8623 attribute_volume_q = g_quark_from_static_string ("volume");
8624 attribute_free_space_q = g_quark_from_static_string ("free_space");
8625
8626 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
->finalize = finalize;
8627 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
->constructor = baul_file_constructor;
8628
8629 signals[CHANGED] =
8630 g_signal_new ("changed",
8631 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8632 G_SIGNAL_RUN_LAST,
8633 G_STRUCT_OFFSET (BaulFileClass, changed)((glong) __builtin_offsetof(BaulFileClass, changed)),
8634 NULL((void*)0), NULL((void*)0),
8635 g_cclosure_marshal_VOID__VOID,
8636 G_TYPE_NONE((GType) ((1) << (2))), 0);
8637
8638 signals[UPDATED_DEEP_COUNT_IN_PROGRESS] =
8639 g_signal_new ("updated_deep_count_in_progress",
8640 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8641 G_SIGNAL_RUN_LAST,
8642 G_STRUCT_OFFSET (BaulFileClass, updated_deep_count_in_progress)((glong) __builtin_offsetof(BaulFileClass, updated_deep_count_in_progress
))
,
8643 NULL((void*)0), NULL((void*)0),
8644 g_cclosure_marshal_VOID__VOID,
8645 G_TYPE_NONE((GType) ((1) << (2))), 0);
8646
8647 eel_g_settings_add_auto_enum (baul_preferences,
8648 BAUL_PREFERENCES_DATE_FORMAT"date-format",
8649 &date_format_pref);
8650
8651 thumbnail_limit_changed_callback (NULL((void*)0));
8652 g_signal_connect_swapped (baul_preferences,g_signal_connect_data ((baul_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8653 "changed::" BAUL_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT,g_signal_connect_data ((baul_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8654 G_CALLBACK (thumbnail_limit_changed_callback),g_signal_connect_data ((baul_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8655 NULL)g_signal_connect_data ((baul_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8656 thumbnail_size_changed_callback (NULL((void*)0));
8657 g_signal_connect_swapped (baul_icon_view_preferences,g_signal_connect_data ((baul_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8658 "changed::" BAUL_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE,g_signal_connect_data ((baul_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8659 G_CALLBACK (thumbnail_size_changed_callback),g_signal_connect_data ((baul_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8660 NULL)g_signal_connect_data ((baul_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8661 show_thumbnails_changed_callback (NULL((void*)0));
8662 g_signal_connect_swapped (baul_preferences,g_signal_connect_data ((baul_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8663 "changed::" BAUL_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS,g_signal_connect_data ((baul_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8664 G_CALLBACK (show_thumbnails_changed_callback),g_signal_connect_data ((baul_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8665 NULL)g_signal_connect_data ((baul_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8666
8667 icon_theme = ctk_icon_theme_get_default ();
8668 g_signal_connect_object (icon_theme,
8669 "changed",
8670 G_CALLBACK (icon_theme_changed_callback)((GCallback) (icon_theme_changed_callback)),
8671 NULL((void*)0), 0);
8672
8673 g_signal_connect (baul_signaller_get_current (),g_signal_connect_data ((baul_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8674 "mime_data_changed",g_signal_connect_data ((baul_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8675 G_CALLBACK (mime_type_data_changed_callback),g_signal_connect_data ((baul_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8676 NULL)g_signal_connect_data ((baul_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
;
8677}
8678
8679static void
8680baul_file_add_emblem (BaulFile *file,
8681 const char *emblem_name)
8682{
8683 if (file->details->pending_info_providers) {
8684 file->details->pending_extension_emblems = g_list_prepend (file->details->pending_extension_emblems,
8685 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8686 } else {
8687 file->details->extension_emblems = g_list_prepend (file->details->extension_emblems,
8688 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8689 }
8690
8691 baul_file_changed (file);
8692}
8693
8694static void
8695baul_file_add_string_attribute (BaulFile *file,
8696 const char *attribute_name,
8697 const char *value)
8698{
8699 if (file->details->pending_info_providers) {
8700 /* Lazily create hashtable */
8701 if (!file->details->pending_extension_attributes) {
8702 file->details->pending_extension_attributes =
8703 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8704 NULL((void*)0),
8705 (GDestroyNotify)g_free);
8706 }
8707 g_hash_table_insert (file->details->pending_extension_attributes,
8708 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8709 g_strdup (value)g_strdup_inline (value));
8710 } else {
8711 if (!file->details->extension_attributes) {
8712 file->details->extension_attributes =
8713 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8714 NULL((void*)0),
8715 (GDestroyNotify)g_free);
8716 }
8717 g_hash_table_insert (file->details->extension_attributes,
8718 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8719 g_strdup (value)g_strdup_inline (value));
8720 }
8721
8722 baul_file_changed (file);
8723}
8724
8725static void
8726baul_file_invalidate_extension_info (BaulFile *file)
8727{
8728 baul_file_invalidate_attributes (file, BAUL_FILE_ATTRIBUTE_EXTENSION_INFO);
8729}
8730
8731void
8732baul_file_info_providers_done (BaulFile *file)
8733{
8734 g_list_free_full (file->details->extension_emblems, g_free);
8735 file->details->extension_emblems = file->details->pending_extension_emblems;
8736 file->details->pending_extension_emblems = NULL((void*)0);
8737
8738 if (file->details->extension_attributes) {
8739 g_hash_table_destroy (file->details->extension_attributes);
8740 }
8741
8742 file->details->extension_attributes = file->details->pending_extension_attributes;
8743 file->details->pending_extension_attributes = NULL((void*)0);
8744
8745 baul_file_changed (file);
8746}
8747
8748static void
8749baul_file_info_iface_init (BaulFileInfoIface *iface)
8750{
8751 iface->is_gone = baul_file_is_gone;
8752 iface->get_name = baul_file_get_name;
8753 iface->get_file_type = baul_file_get_file_type;
8754 iface->get_location = baul_file_get_location;
8755 iface->get_uri = baul_file_get_uri;
8756 iface->get_parent_location = baul_file_get_parent_location;
8757 iface->get_parent_uri = baul_file_get_parent_uri;
8758 iface->get_parent_info = baul_file_get_parent;
8759 iface->get_mount = baul_file_get_mount;
8760 iface->get_uri_scheme = baul_file_get_uri_scheme;
8761 iface->get_activation_uri = baul_file_get_activation_uri;
8762 iface->get_mime_type = baul_file_get_mime_type;
8763 iface->is_mime_type = baul_file_is_mime_type;
8764 iface->is_directory = baul_file_is_directory;
8765 iface->can_write = baul_file_can_write;
8766 iface->add_emblem = baul_file_add_emblem;
8767 iface->get_string_attribute = baul_file_get_string_attribute;
8768 iface->add_string_attribute = baul_file_add_string_attribute;
8769 iface->invalidate_extension_info = baul_file_invalidate_extension_info;
8770}
8771
8772#if !defined (BAUL_OMIT_SELF_CHECK)
8773
8774void
8775baul_self_check_file (void)
8776{
8777 BaulFile *file_1;
8778 BaulFile *file_2;
8779 GList *list;
8780
8781 /* refcount checks */
8782
8783 EEL_CHECK_INTEGER_RESULT (baul_directory_number_outstanding (), 0)do { eel_before_check ("baul_directory_number_outstanding ()"
, "baul-file.c", 8783); eel_check_integer_result (baul_directory_number_outstanding
(), 0); } while (0)
;
8784
8785 file_1 = baul_file_get_by_uri ("file:///home/");
8786
8787 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1)), (((GType) ((20) << (2))))))))->ref_count"
, "baul-file.c", 8787); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1
)), (((GType) ((20) << (2))))))))->ref_count, 1); } while
(0)
;
8788 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1->details->directory)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1->details->directory)), (((GType) ((20) << (2))))))))->ref_count"
, "baul-file.c", 8788); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1
->details->directory)), (((GType) ((20) << (2))))
))))->ref_count, 1); } while (0)
;
8789 EEL_CHECK_INTEGER_RESULT (baul_directory_number_outstanding (), 1)do { eel_before_check ("baul_directory_number_outstanding ()"
, "baul-file.c", 8789); eel_check_integer_result (baul_directory_number_outstanding
(), 1); } while (0)
;
8790
8791 baul_file_unref (file_1);
8792
8793 EEL_CHECK_INTEGER_RESULT (baul_directory_number_outstanding (), 0)do { eel_before_check ("baul_directory_number_outstanding ()"
, "baul-file.c", 8793); eel_check_integer_result (baul_directory_number_outstanding
(), 0); } while (0)
;
8794
8795 file_1 = baul_file_get_by_uri ("file:///etc");
8796 file_2 = baul_file_get_by_uri ("file:///usr");
8797
8798 list = NULL((void*)0);
8799 list = g_list_prepend (list, file_1);
8800 list = g_list_prepend (list, file_2);
8801
8802 baul_file_list_ref (list);
8803
8804 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 2)do { eel_before_check ("((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1)), (((GType) ((20) << (2))))))))->ref_count"
, "baul-file.c", 8804); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1
)), (((GType) ((20) << (2))))))))->ref_count, 2); } while
(0)
;
8805 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 2)do { eel_before_check ("((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_2)), (((GType) ((20) << (2))))))))->ref_count"
, "baul-file.c", 8805); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_2
)), (((GType) ((20) << (2))))))))->ref_count, 2); } while
(0)
;
8806
8807 baul_file_list_unref (list);
8808
8809 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1)), (((GType) ((20) << (2))))))))->ref_count"
, "baul-file.c", 8809); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1
)), (((GType) ((20) << (2))))))))->ref_count, 1); } while
(0)
;
8810 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_2)), (((GType) ((20) << (2))))))))->ref_count"
, "baul-file.c", 8810); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_2
)), (((GType) ((20) << (2))))))))->ref_count, 1); } while
(0)
;
8811
8812 baul_file_list_free (list);
8813
8814 EEL_CHECK_INTEGER_RESULT (baul_directory_number_outstanding (), 0)do { eel_before_check ("baul_directory_number_outstanding ()"
, "baul-file.c", 8814); eel_check_integer_result (baul_directory_number_outstanding
(), 0); } while (0)
;
8815
8816
8817 /* name checks */
8818 file_1 = baul_file_get_by_uri ("file:///home/");
8819
8820 EEL_CHECK_STRING_RESULT (baul_file_get_name (file_1), "home")do { eel_before_check ("baul_file_get_name (file_1)", "baul-file.c"
, 8820); eel_check_string_result (baul_file_get_name (file_1)
, "home"); } while (0)
;
8821
8822 EEL_CHECK_BOOLEAN_RESULT (baul_file_get_by_uri ("file:///home/") == file_1, TRUE)do { eel_before_check ("baul_file_get_by_uri (\"file:///home/\") == file_1"
, "baul-file.c", 8822); eel_check_boolean_result (baul_file_get_by_uri
("file:///home/") == file_1, (!(0))); } while (0)
;
8823 baul_file_unref (file_1);
8824
8825 EEL_CHECK_BOOLEAN_RESULT (baul_file_get_by_uri ("file:///home") == file_1, TRUE)do { eel_before_check ("baul_file_get_by_uri (\"file:///home\") == file_1"
, "baul-file.c", 8825); eel_check_boolean_result (baul_file_get_by_uri
("file:///home") == file_1, (!(0))); } while (0)
;
8826 baul_file_unref (file_1);
8827
8828 baul_file_unref (file_1);
8829
8830 file_1 = baul_file_get_by_uri ("file:///home");
8831 EEL_CHECK_STRING_RESULT (baul_file_get_name (file_1), "home")do { eel_before_check ("baul_file_get_name (file_1)", "baul-file.c"
, 8831); eel_check_string_result (baul_file_get_name (file_1)
, "home"); } while (0)
;
8832 baul_file_unref (file_1);
8833
8834#if 0
8835 /* ALEX: I removed this, because it was breaking distchecks.
8836 * It used to work, but when canonical uris changed from
8837 * foo: to foo:/// it broke. I don't expect it to matter
8838 * in real life */
8839 file_1 = baul_file_get_by_uri (":");
8840 EEL_CHECK_STRING_RESULT (baul_file_get_name (file_1), ":")do { eel_before_check ("baul_file_get_name (file_1)", "baul-file.c"
, 8840); eel_check_string_result (baul_file_get_name (file_1)
, ":"); } while (0)
;
8841 baul_file_unref (file_1);
8842#endif
8843
8844 file_1 = baul_file_get_by_uri ("eazel:");
8845 EEL_CHECK_STRING_RESULT (baul_file_get_name (file_1), "eazel")do { eel_before_check ("baul_file_get_name (file_1)", "baul-file.c"
, 8845); eel_check_string_result (baul_file_get_name (file_1)
, "eazel"); } while (0)
;
8846 baul_file_unref (file_1);
8847
8848 /* sorting */
8849 file_1 = baul_file_get_by_uri ("file:///etc");
8850 file_2 = baul_file_get_by_uri ("file:///usr");
8851
8852 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1)), (((GType) ((20) << (2))))))))->ref_count"
, "baul-file.c", 8852); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1
)), (((GType) ((20) << (2))))))))->ref_count, 1); } while
(0)
;
8853 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_2)), (((GType) ((20) << (2))))))))->ref_count"
, "baul-file.c", 8853); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_2
)), (((GType) ((20) << (2))))))))->ref_count, 1); } while
(0)
;
8854
8855 EEL_CHECK_BOOLEAN_RESULT (baul_file_compare_for_sort (file_1, file_2, BAUL_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) < 0, TRUE)do { eel_before_check ("baul_file_compare_for_sort (file_1, file_2, BAUL_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) < 0"
, "baul-file.c", 8855); eel_check_boolean_result (baul_file_compare_for_sort
(file_1, file_2, BAUL_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) <
0, (!(0))); } while (0)
;
8856 EEL_CHECK_BOOLEAN_RESULT (baul_file_compare_for_sort (file_1, file_2, BAUL_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) > 0, TRUE)do { eel_before_check ("baul_file_compare_for_sort (file_1, file_2, BAUL_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))) > 0"
, "baul-file.c", 8856); eel_check_boolean_result (baul_file_compare_for_sort
(file_1, file_2, BAUL_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))
) > 0, (!(0))); } while (0)
;
8857 EEL_CHECK_BOOLEAN_RESULT (baul_file_compare_for_sort (file_1, file_1, BAUL_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) == 0, TRUE)do { eel_before_check ("baul_file_compare_for_sort (file_1, file_1, BAUL_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) == 0"
, "baul-file.c", 8857); eel_check_boolean_result (baul_file_compare_for_sort
(file_1, file_1, BAUL_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) ==
0, (!(0))); } while (0)
;
8858 EEL_CHECK_BOOLEAN_RESULT (baul_file_compare_for_sort (file_1, file_1, BAUL_FILE_SORT_BY_DISPLAY_NAME, TRUE, FALSE) == 0, TRUE)do { eel_before_check ("baul_file_compare_for_sort (file_1, file_1, BAUL_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (0)) == 0"
, "baul-file.c", 8858); eel_check_boolean_result (baul_file_compare_for_sort
(file_1, file_1, BAUL_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (0)
) == 0, (!(0))); } while (0)
;
8859 EEL_CHECK_BOOLEAN_RESULT (baul_file_compare_for_sort (file_1, file_1, BAUL_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) == 0, TRUE)do { eel_before_check ("baul_file_compare_for_sort (file_1, file_1, BAUL_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))) == 0"
, "baul-file.c", 8859); eel_check_boolean_result (baul_file_compare_for_sort
(file_1, file_1, BAUL_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))
) == 0, (!(0))); } while (0)
;
8860 EEL_CHECK_BOOLEAN_RESULT (baul_file_compare_for_sort (file_1, file_1, BAUL_FILE_SORT_BY_DISPLAY_NAME, TRUE, TRUE) == 0, TRUE)do { eel_before_check ("baul_file_compare_for_sort (file_1, file_1, BAUL_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (!(0))) == 0"
, "baul-file.c", 8860); eel_check_boolean_result (baul_file_compare_for_sort
(file_1, file_1, BAUL_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (!(
0))) == 0, (!(0))); } while (0)
;
8861
8862 baul_file_unref (file_1);
8863 baul_file_unref (file_2);
8864}
8865
8866#endif /* !BAUL_OMIT_SELF_CHECK */