Bug Summary

File:libbaul-private/baul-file.c
Warning:line 3898, column 12
This statement is never executed

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 -fcoverage-compilation-dir=/rootdir/libbaul-private -resource-dir /usr/lib/llvm-16/lib/clang/16 -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/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-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/libbaul-private -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-01-21-115427-28355-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 gsize 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 (&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 ((&static_g_define_type_id
), (gsize) (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 gsize 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 (&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 ((&static_g_define_type_id
), (gsize) (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 gsize 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 (&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 ((&static_g_define_type_id
), (gsize) (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 gsize 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 (&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 ((&static_g_define_type_id
), (gsize) (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)
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;
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 GTimeVal g_trash_time;
2117 const char * time_string;
2118 const char *symlink_name, *mime_type, *selinux_context, *thumbnail_path;
2119 GFileType file_type;
2120 GIcon *icon;
2121 const char *description;
2122 const char *filesystem_id;
2123 const char *trash_orig_path;
2124 const char *group, *owner, *owner_real;
2125 gboolean free_owner, free_group;
2126
2127 if (file->details->is_gone) {
2128 return FALSE(0);
2129 }
2130
2131 if (info == NULL((void*)0)) {
2132 baul_file_mark_gone (file);
2133 return TRUE(!(0));
2134 }
2135
2136 file->details->file_info_is_up_to_date = TRUE(!(0));
2137
2138 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2139 * point to the old name know that the file has been renamed.
2140 */
2141
2142 remove_from_link_hash_table (file);
2143
2144 changed = FALSE(0);
2145
2146 if (!file->details->got_file_info) {
2147 changed = TRUE(!(0));
2148 }
2149 file->details->got_file_info = TRUE(!(0));
2150
2151 changed |= baul_file_set_display_name (file,
2152 g_file_info_get_display_name (info),
2153 g_file_info_get_edit_name (info),
2154 FALSE(0));
2155
2156 file_type = g_file_info_get_file_type (info);
2157 if (file->details->type != file_type) {
2158 changed = TRUE(!(0));
2159 }
2160 file->details->type = file_type;
2161
2162 if (!file->details->got_custom_activation_uri) {
2163 const char *activation_uri;
2164
2165 activation_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI"standard::target-uri");
2166 if (activation_uri == NULL((void*)0)) {
2167 if (file->details->activation_uri) {
2168 g_free (file->details->activation_uri);
2169 file->details->activation_uri = NULL((void*)0);
2170 changed = TRUE(!(0));
2171 }
2172 } else {
2173 char *old_activation_uri;
2174
2175 old_activation_uri = file->details->activation_uri;
2176 file->details->activation_uri = g_strdup (activation_uri)g_strdup_inline (activation_uri);
2177
2178 if (old_activation_uri) {
2179 if (strcmp (old_activation_uri,
2180 file->details->activation_uri) != 0) {
2181 changed = TRUE(!(0));
2182 }
2183 g_free (old_activation_uri);
2184 } else {
2185 changed = TRUE(!(0));
2186 }
2187 }
2188 }
2189
2190 is_symlink = g_file_info_get_is_symlink (info);
2191 if (file->details->is_symlink != is_symlink) {
2192 changed = TRUE(!(0));
2193 }
2194 file->details->is_symlink = is_symlink;
2195
2196 is_hidden = g_file_info_get_is_hidden (info);
2197 is_backup = g_file_info_get_is_backup (info);
2198 if (file->details->is_hidden != is_hidden ||
2199 file->details->is_backup != is_backup) {
2200 changed = TRUE(!(0));
2201 }
2202 file->details->is_hidden = is_hidden;
2203 file->details->is_backup = is_backup;
2204
2205 is_mountpoint = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT"unix::is-mountpoint");
2206 if (file->details->is_mountpoint != is_mountpoint) {
2207 changed = TRUE(!(0));
2208 }
2209 file->details->is_mountpoint = is_mountpoint;
2210
2211 has_permissions = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
2212 permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");;
2213 if (file->details->has_permissions != has_permissions ||
2214 file->details->permissions != permissions) {
2215 changed = TRUE(!(0));
2216 }
2217 file->details->has_permissions = has_permissions;
2218 file->details->permissions = permissions;
2219
2220 /* We default to TRUE for this if we can't know */
2221 can_read = TRUE(!(0));
2222 can_write = TRUE(!(0));
2223 can_execute = TRUE(!(0));
2224 can_delete = TRUE(!(0));
2225 can_trash = TRUE(!(0));
2226 can_rename = TRUE(!(0));
2227 can_mount = FALSE(0);
2228 can_unmount = FALSE(0);
2229 can_eject = FALSE(0);
2230 can_start = FALSE(0);
2231 can_start_degraded = FALSE(0);
2232 can_stop = FALSE(0);
2233 can_poll_for_media = FALSE(0);
2234 is_media_check_automatic = FALSE(0);
2235 start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
2236 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read")) {
2237 can_read = g_file_info_get_attribute_boolean (info,
2238 G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read");
2239 }
2240 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write")) {
2241 can_write = g_file_info_get_attribute_boolean (info,
2242 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write");
2243 }
2244 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute")) {
2245 can_execute = g_file_info_get_attribute_boolean (info,
2246 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute");
2247 }
2248 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete")) {
2249 can_delete = g_file_info_get_attribute_boolean (info,
2250 G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete");
2251 }
2252 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash")) {
2253 can_trash = g_file_info_get_attribute_boolean (info,
2254 G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash");
2255 }
2256 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename")) {
2257 can_rename = g_file_info_get_attribute_boolean (info,
2258 G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename");
2259 }
2260 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount")) {
2261 can_mount = g_file_info_get_attribute_boolean (info,
2262 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount");
2263 }
2264 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount")) {
2265 can_unmount = g_file_info_get_attribute_boolean (info,
2266 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount");
2267 }
2268 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject")) {
2269 can_eject = g_file_info_get_attribute_boolean (info,
2270 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject");
2271 }
2272 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start")) {
2273 can_start = g_file_info_get_attribute_boolean (info,
2274 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start");
2275 }
2276 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded")) {
2277 can_start_degraded = g_file_info_get_attribute_boolean (info,
2278 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded");
2279 }
2280 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop")) {
2281 can_stop = g_file_info_get_attribute_boolean (info,
2282 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop");
2283 }
2284 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type")) {
2285 start_stop_type = g_file_info_get_attribute_uint32 (info,
2286 G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type");
2287 }
2288 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll")) {
2289 can_poll_for_media = g_file_info_get_attribute_boolean (info,
2290 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll");
2291 }
2292 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic")) {
2293 is_media_check_automatic = g_file_info_get_attribute_boolean (info,
2294 G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic");
2295 }
2296 if (file->details->can_read != can_read ||
2297 file->details->can_write != can_write ||
2298 file->details->can_execute != can_execute ||
2299 file->details->can_delete != can_delete ||
2300 file->details->can_trash != can_trash ||
2301 file->details->can_rename != can_rename ||
2302 file->details->can_mount != can_mount ||
2303 file->details->can_unmount != can_unmount ||
2304 file->details->can_eject != can_eject ||
2305 file->details->can_start != can_start ||
2306 file->details->can_start_degraded != can_start_degraded ||
2307 file->details->can_stop != can_stop ||
2308 file->details->start_stop_type != start_stop_type ||
2309 file->details->can_poll_for_media != can_poll_for_media ||
2310 file->details->is_media_check_automatic != is_media_check_automatic) {
2311 changed = TRUE(!(0));
2312 }
2313
2314 file->details->can_read = can_read;
2315 file->details->can_write = can_write;
2316 file->details->can_execute = can_execute;
2317 file->details->can_delete = can_delete;
2318 file->details->can_trash = can_trash;
2319 file->details->can_rename = can_rename;
2320 file->details->can_mount = can_mount;
2321 file->details->can_unmount = can_unmount;
2322 file->details->can_eject = can_eject;
2323 file->details->can_start = can_start;
2324 file->details->can_start_degraded = can_start_degraded;
2325 file->details->can_stop = can_stop;
2326 file->details->start_stop_type = start_stop_type;
2327 file->details->can_poll_for_media = can_poll_for_media;
2328 file->details->is_media_check_automatic = is_media_check_automatic;
2329
2330 free_owner = FALSE(0);
2331 owner = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER"owner::user");
2332 owner_real = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER_REAL"owner::user-real");
2333 free_group = FALSE(0);
2334 group = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP"owner::group");
2335
2336 uid = -1;
2337 gid = -1;
2338 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid")) {
2339 uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid");
2340 if (owner == NULL((void*)0)) {
2341 free_owner = TRUE(!(0));
2342 owner = g_strdup_printf ("%d", uid);
2343 }
2344 }
2345 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid")) {
2346 gid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid");
2347 if (group == NULL((void*)0)) {
2348 free_group = TRUE(!(0));
2349 group = g_strdup_printf ("%d", gid);
2350 }
2351 }
2352 if (file->details->uid != uid ||
2353 file->details->gid != gid) {
2354 changed = TRUE(!(0));
2355 }
2356 file->details->uid = uid;
2357 file->details->gid = gid;
2358
2359 if (eel_strcmp (file->details->owner, owner) != 0) {
2360 changed = TRUE(!(0));
2361 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)
;
2362 file->details->owner = g_ref_string_new_intern (owner);
2363 }
2364
2365 if (eel_strcmp (file->details->owner_real, owner_real) != 0) {
2366 changed = TRUE(!(0));
2367 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)
;
2368 file->details->owner_real = g_ref_string_new_intern (owner_real);
2369 }
2370
2371 if (eel_strcmp (file->details->group, group) != 0) {
2372 changed = TRUE(!(0));
2373 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)
;
2374 file->details->group = g_ref_string_new_intern (group);
2375 }
2376
2377 if (free_owner) {
2378 g_free ((char *)owner);
2379 }
2380 if (free_group) {
2381 g_free ((char *)group);
2382 }
2383
2384 size = -1;
2385 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size")) {
2386 size = g_file_info_get_size (info);
2387 }
2388 if (file->details->size != size) {
2389 changed = TRUE(!(0));
2390 }
2391 file->details->size = size;
2392
2393 size_on_disk = -1;
2394 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size")) {
2395 size_on_disk = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size");
2396 }
2397 if (file->details->size_on_disk != size_on_disk) {
2398 changed = TRUE(!(0));
2399 }
2400 file->details->size_on_disk = size_on_disk;
2401
2402 sort_order = g_file_info_get_attribute_int32 (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER"standard::sort-order");
2403
2404 if (file->details->sort_order != sort_order) {
2405 changed = TRUE(!(0));
2406 }
2407 file->details->sort_order = sort_order;
2408
2409 atime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS"time::access");
2410 ctime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED"time::changed");
2411 mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED"time::modified");
2412 if (file->details->atime != atime ||
2413 file->details->mtime != mtime ||
2414 file->details->ctime != ctime) {
2415 if (file->details->thumbnail == NULL((void*)0)) {
2416 file->details->thumbnail_is_up_to_date = FALSE(0);
2417 }
2418
2419 changed = TRUE(!(0));
2420 }
2421 file->details->atime = atime;
2422 file->details->ctime = ctime;
2423 file->details->mtime = mtime;
2424
2425 if (file->details->thumbnail != NULL((void*)0) &&
2426 file->details->thumbnail_mtime != 0 &&
2427 file->details->thumbnail_mtime != mtime) {
2428 file->details->thumbnail_is_up_to_date = FALSE(0);
2429 changed = TRUE(!(0));
2430 }
2431
2432 icon = g_file_info_get_icon (info);
2433 if (!g_icon_equal (icon, file->details->icon)) {
2434 changed = TRUE(!(0));
2435
2436 if (file->details->icon) {
2437 g_object_unref (file->details->icon);
2438 }
2439 file->details->icon = g_object_ref (icon)((__typeof__ (icon)) (g_object_ref) (icon));
2440 }
2441
2442 thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH"thumbnail::path");
2443 if (eel_strcmp (file->details->thumbnail_path, thumbnail_path) != 0) {
2444 changed = TRUE(!(0));
2445 g_free (file->details->thumbnail_path);
2446 file->details->thumbnail_path = g_strdup (thumbnail_path)g_strdup_inline (thumbnail_path);
2447 }
2448
2449 thumbnailing_failed = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED"thumbnail::failed");
2450 if (file->details->thumbnailing_failed != thumbnailing_failed) {
2451 changed = TRUE(!(0));
2452 file->details->thumbnailing_failed = thumbnailing_failed;
2453 }
2454
2455 symlink_name = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET"standard::symlink-target");
2456
2457 if (eel_strcmp (file->details->symlink_name, symlink_name) != 0) {
2458 changed = TRUE(!(0));
2459 g_free (file->details->symlink_name);
2460 file->details->symlink_name = g_strdup (symlink_name)g_strdup_inline (symlink_name);
2461 }
2462
2463 mime_type = g_file_info_get_content_type (info);
2464 if (eel_strcmp (file->details->mime_type, mime_type) != 0) {
2465 changed = TRUE(!(0));
2466 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)
;
2467 file->details->mime_type = g_ref_string_new_intern (mime_type);
2468 }
2469
2470 selinux_context = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_SELINUX_CONTEXT"selinux::context");
2471 if (eel_strcmp (file->details->selinux_context, selinux_context) != 0) {
2472 changed = TRUE(!(0));
2473 g_free (file->details->selinux_context);
2474 file->details->selinux_context = g_strdup (selinux_context)g_strdup_inline (selinux_context);
2475 }
2476
2477 description = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION"standard::description");
2478 if (eel_strcmp (file->details->description, description) != 0) {
2479 changed = TRUE(!(0));
2480 g_free (file->details->description);
2481 file->details->description = g_strdup (description)g_strdup_inline (description);
2482 }
2483
2484 filesystem_id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem");
2485 if (eel_strcmp (file->details->filesystem_id, filesystem_id) != 0) {
2486 changed = TRUE(!(0));
2487 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)
;
2488 file->details->filesystem_id = g_ref_string_new_intern (filesystem_id);
2489 }
2490
2491 trash_time = 0;
2492 time_string = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_TRASH_DELETION_DATE"trash::deletion-date");
2493 if (time_string != NULL((void*)0)) {
2494 g_time_val_from_iso8601 (time_string, &g_trash_time);
2495 trash_time = g_trash_time.tv_sec;
2496 }
2497 if (file->details->trash_time != trash_time) {
2498 changed = TRUE(!(0));
2499 file->details->trash_time = trash_time;
2500 }
2501
2502 trash_orig_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH"trash::orig-path");
2503 if (eel_strcmp (file->details->trash_orig_path, trash_orig_path) != 0) {
2504 changed = TRUE(!(0));
2505 g_free (file->details->trash_orig_path);
2506 file->details->trash_orig_path = g_strdup (trash_orig_path)g_strdup_inline (trash_orig_path);
2507 }
2508
2509 changed |=
2510 baul_file_update_metadata_from_info (file, info);
2511
2512 if (update_name) {
2513 const char *name;
2514
2515 name = g_file_info_get_name (info);
2516 if (file->details->name == NULL((void*)0) ||
2517 strcmp (file->details->name, name) != 0) {
2518 GList *node;
2519
2520 changed = TRUE(!(0));
2521
2522 node = baul_directory_begin_file_name_change
2523 (file->details->directory, file);
2524
2525 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)
;
2526 if (eel_strcmp (file->details->display_name, name) == 0) {
2527 file->details->name = g_ref_string_acquire (file->details->display_name);
2528 } else {
2529 file->details->name = g_ref_string_new (name);
2530 }
2531
2532 if (!file->details->got_custom_display_name &&
2533 g_file_info_get_display_name (info) == NULL((void*)0)) {
2534 /* If the file info's display name is NULL,
2535 * baul_file_set_display_name() did
2536 * not unset the display name.
2537 */
2538 baul_file_clear_display_name (file);
2539 }
2540
2541 baul_directory_end_file_name_change
2542 (file->details->directory, file, node);
2543 }
2544 }
2545
2546 if (changed) {
2547 add_to_link_hash_table (file);
2548
2549 update_links_if_target (file);
2550 }
2551
2552 return changed;
2553}
2554
2555static gboolean
2556update_info_and_name (BaulFile *file,
2557 GFileInfo *info)
2558{
2559 return update_info_internal (file, info, TRUE(!(0)));
2560}
2561
2562gboolean
2563baul_file_update_info (BaulFile *file,
2564 GFileInfo *info)
2565{
2566 return update_info_internal (file, info, FALSE(0));
2567}
2568
2569void
2570baul_file_refresh_info (BaulFile *file)
2571{
2572 GFile *gfile;
2573 GFileInfo *new_info;
2574
2575 gfile = baul_file_get_location (file);
2576 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::*",
2577 G_FILE_QUERY_INFO_NONE, NULL((void*)0), NULL((void*)0));
2578 if (new_info != NULL((void*)0)) {
2579 if (baul_file_update_info (file, new_info)) {
2580 baul_file_changed (file);
2581 }
2582 g_object_unref (new_info);
2583 }
2584 g_object_unref (gfile);
2585}
2586
2587static gboolean
2588update_name_internal (BaulFile *file,
2589 const char *name,
2590 gboolean in_directory)
2591{
2592 GList *node;
2593
2594 g_assert (name != NULL)do { if (name != ((void*)0)) ; else g_assertion_message_expr (
((gchar*) 0), "baul-file.c", 2594, ((const char*) (__func__))
, "name != NULL"); } while (0)
;
2595
2596 if (file->details->is_gone) {
2597 return FALSE(0);
2598 }
2599
2600 if (name_is (file, name)) {
2601 return FALSE(0);
2602 }
2603
2604 node = NULL((void*)0);
2605 if (in_directory) {
2606 node = baul_directory_begin_file_name_change
2607 (file->details->directory, file);
2608 }
2609
2610 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)
;
2611 file->details->name = g_ref_string_new (name);
2612
2613 if (!file->details->got_custom_display_name) {
2614 baul_file_clear_display_name (file);
2615 }
2616
2617 if (in_directory) {
2618 baul_directory_end_file_name_change
2619 (file->details->directory, file, node);
2620 }
2621
2622 return TRUE(!(0));
2623}
2624
2625gboolean
2626baul_file_update_name (BaulFile *file, const char *name)
2627{
2628 gboolean ret;
2629
2630 ret = update_name_internal (file, name, TRUE(!(0)));
2631
2632 if (ret) {
2633 update_links_if_target (file);
2634 }
2635
2636 return ret;
2637}
2638
2639gboolean
2640baul_file_update_name_and_directory (BaulFile *file,
2641 const char *name,
2642 BaulDirectory *new_directory)
2643{
2644 BaulDirectory *old_directory;
2645 FileMonitors *monitors;
2646
2647 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)
;
2648 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)
;
2649 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)
;
2650 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)
;
2651 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)
;
2652
2653 old_directory = file->details->directory;
2654 if (old_directory == new_directory) {
2655 if (name) {
2656 return update_name_internal (file, name, TRUE(!(0)));
2657 } else {
2658 return FALSE(0);
2659 }
2660 }
2661
2662 baul_file_ref (file);
2663
2664 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2665 * point to the old name know that the file has been moved.
2666 */
2667
2668 remove_from_link_hash_table (file);
2669
2670 monitors = baul_directory_remove_file_monitors (old_directory, file);
2671 baul_directory_remove_file (old_directory, file);
2672
2673 file->details->directory = baul_directory_ref (new_directory);
2674 baul_directory_unref (old_directory);
2675
2676 if (name) {
2677 update_name_internal (file, name, FALSE(0));
2678 }
2679
2680 baul_directory_add_file (new_directory, file);
2681 baul_directory_add_file_monitors (new_directory, file, monitors);
2682
2683 add_to_link_hash_table (file);
2684
2685 update_links_if_target (file);
2686
2687 baul_file_unref (file);
2688
2689 return TRUE(!(0));
2690}
2691
2692void
2693baul_file_set_directory (BaulFile *file,
2694 BaulDirectory *new_directory)
2695{
2696 baul_file_update_name_and_directory (file, NULL((void*)0), new_directory);
2697}
2698
2699static Knowledge
2700get_item_count (BaulFile *file,
2701 guint *count)
2702{
2703 gboolean known, unreadable;
2704
2705 known = baul_file_get_directory_item_count
2706 (file, count, &unreadable);
2707 if (!known) {
2708 return UNKNOWN;
2709 }
2710 if (unreadable) {
2711 return UNKNOWABLE;
2712 }
2713 return KNOWN;
2714}
2715
2716static Knowledge
2717get_size (BaulFile *file,
2718 goffset *size,
2719 gboolean size_on_disk)
2720{
2721 /* If we tried and failed, then treat it like there is no size
2722 * to know.
2723 */
2724 if (file->details->get_info_failed) {
2725 return UNKNOWABLE;
2726 }
2727
2728 /* If the info is NULL that means we haven't even tried yet,
2729 * so it's just unknown, not unknowable.
2730 */
2731 if (!file->details->got_file_info) {
2732 return UNKNOWN;
2733 }
2734
2735 /* If we got info with no size in it, it means there is no
2736 * such thing as a size as far as cafe-vfs is concerned,
2737 * so "unknowable".
2738 */
2739 if (size_on_disk && file->details->size_on_disk == -1) {
2740 return UNKNOWABLE;
2741 }
2742
2743 if (!size_on_disk && file->details->size == -1) {
2744 return UNKNOWABLE;
2745 }
2746
2747 /* We have a size! */
2748 if (size_on_disk) {
2749 *size = file->details->size_on_disk;
2750 } else {
2751 *size = file->details->size;
2752 }
2753
2754 return KNOWN;
2755}
2756
2757static Knowledge
2758get_time (BaulFile *file,
2759 time_t *time_out,
2760 BaulDateType type)
2761{
2762 time_t time;
2763
2764 /* If we tried and failed, then treat it like there is no size
2765 * to know.
2766 */
2767 if (file->details->get_info_failed) {
2768 return UNKNOWABLE;
2769 }
2770
2771 /* If the info is NULL that means we haven't even tried yet,
2772 * so it's just unknown, not unknowable.
2773 */
2774 if (!file->details->got_file_info) {
2775 return UNKNOWN;
2776 }
2777
2778 time = 0;
2779 switch (type) {
2780 case BAUL_DATE_TYPE_MODIFIED:
2781 time = file->details->mtime;
2782 break;
2783 case BAUL_DATE_TYPE_ACCESSED:
2784 time = file->details->atime;
2785 break;
2786 case BAUL_DATE_TYPE_TRASHED:
2787 time = file->details->trash_time;
2788 break;
2789 default:
2790 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "baul-file.c", 2790
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2791 break;
2792 }
2793
2794 *time_out = time;
2795
2796 /* If we got info with no modification time in it, it means
2797 * there is no such thing as a modification time as far as
2798 * cafe-vfs is concerned, so "unknowable".
2799 */
2800 if (time == 0) {
2801 return UNKNOWABLE;
2802 }
2803 return KNOWN;
2804}
2805
2806static int
2807compare_directories_by_count (BaulFile *file_1, BaulFile *file_2)
2808{
2809 /* Sort order:
2810 * Directories with unknown # of items
2811 * Directories with "unknowable" # of items
2812 * Directories with 0 items
2813 * Directories with n items
2814 */
2815
2816 Knowledge count_known_1, count_known_2;
2817 guint count_1, count_2;
2818
2819 count_known_1 = get_item_count (file_1, &count_1);
2820 count_known_2 = get_item_count (file_2, &count_2);
2821
2822 if (count_known_1 > count_known_2) {
2823 return -1;
2824 }
2825 if (count_known_1 < count_known_2) {
2826 return +1;
2827 }
2828
2829 /* count_known_1 and count_known_2 are equal now. Check if count
2830 * details are UNKNOWABLE or UNKNOWN.
2831 */
2832 if (count_known_1 == UNKNOWABLE || count_known_1 == UNKNOWN) {
2833 return 0;
2834 }
2835
2836 if (count_1 < count_2) {
2837 return -1;
2838 }
2839 if (count_1 > count_2) {
2840 return +1;
2841 }
2842
2843 return 0;
2844}
2845
2846static int
2847compare_files_by_size (BaulFile *file_1, BaulFile *file_2, gboolean size_on_disk)
2848{
2849 /* Sort order:
2850 * Files with unknown size.
2851 * Files with "unknowable" size.
2852 * Files with smaller sizes.
2853 * Files with large sizes.
2854 */
2855
2856 Knowledge size_known_1, size_known_2;
2857 goffset size_1 = 0, size_2 = 0;
2858
2859 size_known_1 = get_size (file_1, &size_1, size_on_disk);
2860 size_known_2 = get_size (file_2, &size_2, size_on_disk);
2861
2862 if (size_known_1 > size_known_2) {
2863 return -1;
2864 }
2865 if (size_known_1 < size_known_2) {
2866 return +1;
2867 }
2868
2869 /* size_known_1 and size_known_2 are equal now. Check if size
2870 * details are UNKNOWABLE or UNKNOWN
2871 */
2872 if (size_known_1 == UNKNOWABLE || size_known_1 == UNKNOWN) {
2873 return 0;
2874 }
2875
2876 if (size_1 < size_2) {
2877 return -1;
2878 }
2879 if (size_1 > size_2) {
2880 return +1;
2881 }
2882
2883 return 0;
2884}
2885
2886static int
2887compare_by_size (BaulFile *file_1, BaulFile *file_2, gboolean size_on_disk)
2888{
2889 /* Sort order:
2890 * Directories with n items
2891 * Directories with 0 items
2892 * Directories with "unknowable" # of items
2893 * Directories with unknown # of items
2894 * Files with large sizes.
2895 * Files with smaller sizes.
2896 * Files with "unknowable" size.
2897 * Files with unknown size.
2898 */
2899
2900 gboolean is_directory_1, is_directory_2;
2901
2902 is_directory_1 = baul_file_is_directory (file_1);
2903 is_directory_2 = baul_file_is_directory (file_2);
2904
2905 if (is_directory_1 && !is_directory_2) {
2906 return -1;
2907 }
2908 if (is_directory_2 && !is_directory_1) {
2909 return +1;
2910 }
2911
2912 if (is_directory_1) {
2913 return compare_directories_by_count (file_1, file_2);
2914 } else {
2915 return compare_files_by_size (file_1, file_2, size_on_disk);
2916 }
2917}
2918
2919static int
2920compare_by_display_name (BaulFile *file_1, BaulFile *file_2)
2921{
2922 const char *name_1, *name_2;
2923 const char *key_1, *key_2;
2924 gboolean sort_last_1, sort_last_2;
2925 int compare;
2926
2927 name_1 = baul_file_peek_display_name (file_1);
2928 name_2 = baul_file_peek_display_name (file_2);
2929
2930 sort_last_1 = name_1[0] == SORT_LAST_CHAR1'.' || name_1[0] == SORT_LAST_CHAR2'#';
2931 sort_last_2 = name_2[0] == SORT_LAST_CHAR1'.' || name_2[0] == SORT_LAST_CHAR2'#';
2932
2933 if (sort_last_1 && !sort_last_2) {
2934 compare = +1;
2935 } else if (!sort_last_1 && sort_last_2) {
2936 compare = -1;
2937 } else {
2938 key_1 = baul_file_peek_display_name_collation_key (file_1);
2939 key_2 = baul_file_peek_display_name_collation_key (file_2);
2940 compare = strcmp (key_1, key_2);
2941 }
2942
2943 return compare;
2944}
2945
2946static int
2947compare_by_directory_name (BaulFile *file_1, BaulFile *file_2)
2948{
2949 char *directory_1, *directory_2;
2950 int compare;
2951
2952 if (file_1->details->directory == file_2->details->directory) {
2953 return 0;
2954 }
2955
2956 directory_1 = baul_file_get_parent_uri_for_display (file_1);
2957 directory_2 = baul_file_get_parent_uri_for_display (file_2);
2958
2959 compare = g_utf8_collate (directory_1, directory_2);
2960
2961 g_free (directory_1);
2962 g_free (directory_2);
2963
2964 return compare;
2965}
2966
2967static gboolean
2968file_has_note (BaulFile *file)
2969{
2970 char *note;
2971 gboolean res;
2972
2973 note = baul_file_get_metadata (file, BAUL_METADATA_KEY_ANNOTATION"annotation", NULL((void*)0));
2974 res = note != NULL((void*)0) && note[0] != 0;
2975 g_free (note);
2976
2977 return res;
2978}
2979
2980static GList *
2981prepend_automatic_keywords (BaulFile *file,
2982 GList *names)
2983{
2984 /* Prepend in reverse order. */
2985 BaulFile *parent;
2986
2987 parent = baul_file_get_parent (file);
2988
2989#ifdef TRASH_IS_FAST_ENOUGH
2990 if (baul_file_is_in_trash (file)) {
2991 names = g_list_prepend
2992 (names, g_strdup (BAUL_FILE_EMBLEM_NAME_TRASH)g_strdup_inline ("trash"));
2993 }
2994#endif
2995 if (file_has_note (file)) {
2996 names = g_list_prepend
2997 (names, g_strdup (BAUL_FILE_EMBLEM_NAME_NOTE)g_strdup_inline ("note"));
2998 }
2999
3000 /* Trash files are assumed to be read-only,
3001 * so we want to ignore them here. */
3002 if (!baul_file_can_write (file) &&
3003 !baul_file_is_in_trash (file) &&
3004 (parent == NULL((void*)0) || baul_file_can_write (parent))) {
3005 names = g_list_prepend
3006 (names, g_strdup (BAUL_FILE_EMBLEM_NAME_CANT_WRITE)g_strdup_inline ("nowrite"));
3007 }
3008 if (!baul_file_can_read (file)) {
3009 names = g_list_prepend
3010 (names, g_strdup (BAUL_FILE_EMBLEM_NAME_CANT_READ)g_strdup_inline ("noread"));
3011 }
3012 if (baul_file_is_symbolic_link (file)) {
3013 names = g_list_prepend
3014 (names, g_strdup (BAUL_FILE_EMBLEM_NAME_SYMBOLIC_LINK)g_strdup_inline ("symbolic-link"));
3015 }
3016
3017 if (parent) {
3018 baul_file_unref (parent);
3019 }
3020
3021
3022 return names;
3023}
3024
3025static void
3026fill_emblem_cache_if_needed (BaulFile *file)
3027{
3028 GList *node, *keywords;
3029 char *scanner;
3030 size_t length;
3031
3032 if (file->details->compare_by_emblem_cache != NULL((void*)0)) {
3033 /* Got a cache already. */
3034 return;
3035 }
3036
3037 keywords = baul_file_get_keywords (file);
3038
3039 /* Add up the keyword string lengths */
3040 length = 1;
3041 for (node = keywords; node != NULL((void*)0); node = node->next) {
3042 length += strlen ((const char *) node->data) + 1;
3043 }
3044
3045 /* Now that we know how large the cache struct needs to be, allocate it. */
3046 file->details->compare_by_emblem_cache = g_malloc (sizeof(BaulFileSortByEmblemCache) + length);
3047
3048 /* Copy them into the cache. */
3049 scanner = file->details->compare_by_emblem_cache->emblem_keywords;
3050 for (node = keywords; node != NULL((void*)0); node = node->next) {
3051 length = strlen ((const char *) node->data) + 1;
3052 memcpy (scanner, (const char *) node->data, length);
3053 scanner += length;
3054 }
3055
3056 /* Zero-terminate so we can tell where the list ends. */
3057 *scanner = 0;
3058
3059 g_list_free_full (keywords, g_free);
3060}
3061
3062static int
3063compare_by_emblems (BaulFile *file_1, BaulFile *file_2)
3064{
3065 const char *keyword_cache_1, *keyword_cache_2;
3066 int compare_result;
3067
3068 fill_emblem_cache_if_needed (file_1);
3069 fill_emblem_cache_if_needed (file_2);
3070
3071 /* We ignore automatic emblems, and only sort by user-added keywords. */
3072 compare_result = 0;
3073 keyword_cache_1 = file_1->details->compare_by_emblem_cache->emblem_keywords;
3074 keyword_cache_2 = file_2->details->compare_by_emblem_cache->emblem_keywords;
3075 for (; *keyword_cache_1 != '\0' && *keyword_cache_2 != '\0';) {
3076 size_t length;
3077
3078 compare_result = g_utf8_collate (keyword_cache_1, keyword_cache_2);
3079 if (compare_result != 0) {
3080 return compare_result;
3081 }
3082
3083 /* Advance to the next keyword */
3084 length = strlen (keyword_cache_1);
3085 keyword_cache_1 += length + 1;
3086 keyword_cache_2 += length + 1;
3087 }
3088
3089
3090 /* One or both is now NULL. */
3091 if (*keyword_cache_1 != '\0') {
3092 g_assert (*keyword_cache_2 == '\0')do { if (*keyword_cache_2 == '\0') ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 3092, ((const char*) (__func__
)), "*keyword_cache_2 == '\\0'"); } while (0)
;
3093 return -1;
3094 } else if (*keyword_cache_2 != '\0') {
3095 return +1;
3096 }
3097
3098 return 0;
3099}
3100
3101static int
3102compare_by_type (BaulFile *file_1, BaulFile *file_2)
3103{
3104 gboolean is_directory_1;
3105 gboolean is_directory_2;
3106 char *type_string_1;
3107 char *type_string_2;
3108 int result;
3109
3110 /* Directories go first. Then, if mime types are identical,
3111 * don't bother getting strings (for speed). This assumes
3112 * that the string is dependent entirely on the mime type,
3113 * which is true now but might not be later.
3114 */
3115 is_directory_1 = baul_file_is_directory (file_1);
3116 is_directory_2 = baul_file_is_directory (file_2);
3117
3118 if (is_directory_1 && is_directory_2) {
3119 return 0;
3120 }
3121
3122 if (is_directory_1) {
3123 return -1;
3124 }
3125
3126 if (is_directory_2) {
3127 return +1;
3128 }
3129
3130 if (file_1->details->mime_type != NULL((void*)0) &&
3131 file_2->details->mime_type != NULL((void*)0) &&
3132 strcmp (file_1->details->mime_type,
3133 file_2->details->mime_type) == 0) {
3134 return 0;
3135 }
3136
3137 type_string_1 = baul_file_get_type_as_string (file_1);
3138 type_string_2 = baul_file_get_type_as_string (file_2);
3139
3140 result = g_utf8_collate (type_string_1, type_string_2);
3141
3142 g_free (type_string_1);
3143 g_free (type_string_2);
3144
3145 return result;
3146}
3147
3148static int
3149compare_by_time (BaulFile *file_1, BaulFile *file_2, BaulDateType type)
3150{
3151 /* Sort order:
3152 * Files with unknown times.
3153 * Files with "unknowable" times.
3154 * Files with older times.
3155 * Files with newer times.
3156 */
3157
3158 Knowledge time_known_1, time_known_2;
3159 time_t time_1, time_2;
3160
3161 time_1 = 0;
3162 time_2 = 0;
3163
3164 time_known_1 = get_time (file_1, &time_1, type);
3165 time_known_2 = get_time (file_2, &time_2, type);
3166
3167 if (time_known_1 > time_known_2) {
3168 return -1;
3169 }
3170 if (time_known_1 < time_known_2) {
3171 return +1;
3172 }
3173
3174 /* Now time_known_1 is equal to time_known_2. Check whether
3175 * we failed to get modification times for files
3176 */
3177 if(time_known_1 == UNKNOWABLE || time_known_1 == UNKNOWN) {
3178 return 0;
3179 }
3180
3181 if (time_1 < time_2) {
3182 return -1;
3183 }
3184 if (time_1 > time_2) {
3185 return +1;
3186 }
3187
3188 return 0;
3189}
3190
3191static int
3192compare_by_full_path (BaulFile *file_1, BaulFile *file_2)
3193{
3194 int compare;
3195
3196 compare = compare_by_directory_name (file_1, file_2);
3197 if (compare != 0) {
3198 return compare;
3199 }
3200 return compare_by_display_name (file_1, file_2);
3201}
3202
3203/* prev_extension_segment:
3204 * @basename The basename of a file
3205 * @rem_chars A pointer to the amount of remaining characters
3206 *
3207 * Finds the next segment delimiter to the left. A starting character of '.' is
3208 * set to '\0'.
3209 *
3210 * Return value: The start of the previous segment (right of the dot) or
3211 * basename if there are none remaining.
3212 */
3213static char *
3214prev_extension_segment (char *basename, int *rem_chars)
3215{
3216 if (*basename == '.') {
3217 *basename = 0;
3218 basename--;
3219 (*rem_chars)--;
3220 }
3221
3222 while (*rem_chars > 0 && *basename != '.') {
3223 (*rem_chars)--;
3224 basename--;
3225 }
3226
3227 return basename + 1;
3228}
3229
3230/* is_valid_extension_segment:
3231 * @segment Part of a modifiable zero-terminated string
3232 * @segment_index The index of the current segment
3233 *
3234 * Uses a heuristic to identify valid file extensions.
3235 *
3236 * Return value: Whether the segment is part of the file extension.
3237 */
3238static gboolean
3239is_valid_extension_segment (const char *segment, int segment_index)
3240{
3241 gboolean result;
3242 gboolean has_letters;
3243 int char_offset;
3244 switch (segment_index) {
3245 case 0:
3246 /* extremely long segments are probably not part of the extension */
3247 result = strlen (segment) < 20;
3248 break;
3249 default:
3250 has_letters = FALSE(0);
3251 char_offset = 0;
3252 while (TRUE(!(0))) {
3253 char c;
3254
3255 c = *(segment + char_offset);
3256 if (c == '\0') {
3257 result = has_letters;
3258 break;
3259 }
3260 /* allow digits if there are also letters */
3261 else if (isalpha (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISalpha
)
) {
3262 has_letters = TRUE(!(0));
3263 }
3264 /* fail if it is neither digit nor letter */
3265 else if (!isdigit (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISdigit
)
) {
3266 result = FALSE(0);
3267 break;
3268 }
3269
3270 if (char_offset >= SORT_BY_EXTENSION_FOLLOWING_MAX_LENGTH3) {
3271 result = FALSE(0);
3272 break;
3273 }
3274 char_offset++;
3275 }
3276 }
3277 return result;
3278}
3279
3280static int
3281compare_by_extension_segments (BaulFile *file_1, BaulFile *file_2)
3282{
3283 char *name_1, *name_2;
3284 char *segment_1, *segment_2;
3285 int compare;
3286 int rem_chars_1, rem_chars_2;
3287 gboolean done_1, done_2;
3288 gboolean is_directory_1, is_directory_2;
3289 int segment_index;
3290
3291
3292 /* Directories do not have an extension */
3293 is_directory_1 = baul_file_is_directory (file_1);
3294 is_directory_2 = baul_file_is_directory (file_2);
3295
3296 if (is_directory_1 && is_directory_2) {
3297 return 0;
3298 } else if (is_directory_1) {
3299 return -1;
3300 } else if (is_directory_2) {
3301 return 1;
3302 }
3303
3304 name_1 = baul_file_get_display_name (file_1);
3305 name_2 = baul_file_get_display_name (file_2);
3306 rem_chars_1 = strlen (name_1);
3307 rem_chars_2 = strlen (name_2);
3308
3309 /* Point to one after the zero character */
3310 segment_1 = name_1 + rem_chars_1 + 1;
3311 segment_2 = name_2 + rem_chars_2 + 1;
3312
3313 segment_index = 0;
3314 do {
3315 segment_1 = prev_extension_segment (segment_1 - 1, &rem_chars_1);
3316 segment_2 = prev_extension_segment (segment_2 - 1, &rem_chars_2);
3317
3318 done_1 = rem_chars_1 <= 0 || !is_valid_extension_segment (segment_1, segment_index);
3319 done_2 = rem_chars_2 <= 0 || !is_valid_extension_segment (segment_2, segment_index);
3320 if (done_1 && !done_2) {
3321 compare = -1;
3322 break;
3323 }
3324 else if (!done_1 && done_2) {
3325 compare = 1;
3326 break;
3327 }
3328 else if (done_1 && done_2) {
3329 compare = 0;
3330 break;
3331 }
3332
3333 segment_index++;
3334 if (segment_index > SORT_BY_EXTENSION_MAX_SEGMENTS3 - 1) {
3335 break;
3336 }
3337 compare = strcmp (segment_1, segment_2);
3338 } while (compare == 0);
3339
3340 g_free (name_1);
3341 g_free (name_2);
3342
3343 return compare;
3344}
3345
3346static gchar *
3347baul_file_get_extension_as_string (BaulFile *file)
3348{
3349 int rem_chars;
3350 char *segment;
3351
3352 if (!baul_file_is_directory (file)) {
3353 char *name;
3354
3355 name = baul_file_get_display_name (file);
3356 rem_chars = strlen (name);
3357 segment = prev_extension_segment (name + rem_chars, &rem_chars);
3358
3359 if (rem_chars > 0 && is_valid_extension_segment (segment, 0)) {
3360 int segment_index;
3361 char *right_segment;
3362 char *result;
3363
3364 segment_index = 1;
3365 do {
3366 right_segment = segment;
3367 segment = prev_extension_segment (segment - 1, &rem_chars);
3368 if (rem_chars > 0 && is_valid_extension_segment (segment, segment_index)) {
3369 /* remove zero-termination of segment */
3370 *(right_segment - 1) = '.';
3371 }
3372 else {
3373 break;
3374 }
3375
3376 segment_index++;
3377 } while (segment_index < SORT_BY_EXTENSION_MAX_SEGMENTS3 + 1);
3378 result = g_strdup (right_segment)g_strdup_inline (right_segment);
3379 g_free (name);
3380 return result;
3381 }
3382 g_free (name);
3383 }
3384 return g_strdup ("")g_strdup_inline ("");
3385}
3386
3387static int
3388baul_file_compare_for_sort_internal (BaulFile *file_1,
3389 BaulFile *file_2,
3390 gboolean directories_first,
3391 gboolean reversed)
3392{
3393 gboolean is_directory_1, is_directory_2;
3394
3395 if (directories_first) {
3396 is_directory_1 = baul_file_is_directory (file_1);
3397 is_directory_2 = baul_file_is_directory (file_2);
3398
3399 if (is_directory_1 && !is_directory_2) {
3400 return -1;
3401 }
3402
3403 if (is_directory_2 && !is_directory_1) {
3404 return +1;
3405 }
3406 }
3407
3408 if (file_1->details->sort_order < file_2->details->sort_order) {
3409 return reversed ? 1 : -1;
3410 } else if (file_1->details->sort_order > file_2->details->sort_order) {
3411 return reversed ? -1 : 1;
3412 }
3413
3414 return 0;
3415}
3416
3417/**
3418 * baul_file_compare_for_sort:
3419 * @file_1: A file object
3420 * @file_2: Another file object
3421 * @sort_type: Sort criterion
3422 * @directories_first: Put all directories before any non-directories
3423 * @reversed: Reverse the order of the items, except that
3424 * the directories_first flag is still respected.
3425 *
3426 * Return value: int < 0 if @file_1 should come before file_2 in a
3427 * sorted list; int > 0 if @file_2 should come before file_1 in a
3428 * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
3429 * that each named sort type may actually break ties several ways, with the name
3430 * of the sort criterion being the primary but not only differentiator.
3431 **/
3432int
3433baul_file_compare_for_sort (BaulFile *file_1,
3434 BaulFile *file_2,
3435 BaulFileSortType sort_type,
3436 gboolean directories_first,
3437 gboolean reversed)
3438{
3439 int result;
3440
3441 if (file_1 == file_2) {
3442 return 0;
3443 }
3444
3445 result = baul_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3446
3447 if (result == 0) {
3448 switch (sort_type) {
3449 case BAUL_FILE_SORT_BY_DISPLAY_NAME:
3450 result = compare_by_display_name (file_1, file_2);
3451 if (result == 0) {
3452 result = compare_by_directory_name (file_1, file_2);
3453 }
3454 break;
3455 case BAUL_FILE_SORT_BY_DIRECTORY:
3456 result = compare_by_full_path (file_1, file_2);
3457 break;
3458 case BAUL_FILE_SORT_BY_SIZE:
3459 /* Compare directory sizes ourselves, then if necessary
3460 * use CafeVFS to compare file sizes.
3461 */
3462 result = compare_by_size (file_1, file_2, FALSE(0));
3463 if (result == 0) {
3464 result = compare_by_full_path (file_1, file_2);
3465 }
3466 break;
3467 case BAUL_FILE_SORT_BY_SIZE_ON_DISK:
3468 /* Compare directory sizes ourselves, then if necessary
3469 * use CafeVFS to compare file sizes.
3470 */
3471 result = compare_by_size (file_1, file_2, TRUE(!(0)));
3472 if (result == 0) {
3473 result = compare_by_full_path (file_1, file_2);
3474 }
3475 break;
3476 case BAUL_FILE_SORT_BY_TYPE:
3477 /* CafeVFS doesn't know about our special text for certain
3478 * mime types, so we handle the mime-type sorting ourselves.
3479 */
3480 result = compare_by_type (file_1, file_2);
3481 if (result == 0) {
3482 result = compare_by_full_path (file_1, file_2);
3483 }
3484 break;
3485 case BAUL_FILE_SORT_BY_MTIME:
3486 result = compare_by_time (file_1, file_2, BAUL_DATE_TYPE_MODIFIED);
3487 if (result == 0) {
3488 result = compare_by_full_path (file_1, file_2);
3489 }
3490 break;
3491 case BAUL_FILE_SORT_BY_ATIME:
3492 result = compare_by_time (file_1, file_2, BAUL_DATE_TYPE_ACCESSED);
3493 if (result == 0) {
3494 result = compare_by_full_path (file_1, file_2);
3495 }
3496 break;
3497 case BAUL_FILE_SORT_BY_TRASHED_TIME:
3498 result = compare_by_time (file_1, file_2, BAUL_DATE_TYPE_TRASHED);
3499 if (result == 0) {
3500 result = compare_by_full_path (file_1, file_2);
3501 }
3502 break;
3503 case BAUL_FILE_SORT_BY_EMBLEMS:
3504 /* CafeVFS doesn't know squat about our emblems, so
3505 * we handle comparing them here, before falling back
3506 * to tie-breakers.
3507 */
3508 result = compare_by_emblems (file_1, file_2);
3509 if (result == 0) {
3510 result = compare_by_full_path (file_1, file_2);
3511 }
3512 break;
3513 case BAUL_FILE_SORT_BY_EXTENSION:
3514 result = compare_by_extension_segments (file_1, file_2);
3515 if (result == 0) {
3516 result = compare_by_full_path (file_1, file_2);
3517 }
3518 break;
3519 default:
3520 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", 3520, ((const char*) (__func__))); return (0
); } while (0)
;
3521 }
3522
3523 if (reversed) {
3524 result = -result;
3525 }
3526 }
3527
3528 return result;
3529}
3530
3531int
3532baul_file_compare_for_sort_by_attribute_q (BaulFile *file_1,
3533 BaulFile *file_2,
3534 GQuark attribute,
3535 gboolean directories_first,
3536 gboolean reversed)
3537{
3538 int result;
3539
3540 if (file_1 == file_2) {
3541 return 0;
3542 }
3543
3544 /* Convert certain attributes into BaulFileSortTypes and use
3545 * baul_file_compare_for_sort()
3546 */
3547 if (attribute == 0 || attribute == attribute_name_q) {
3548 return baul_file_compare_for_sort (file_1, file_2,
3549 BAUL_FILE_SORT_BY_DISPLAY_NAME,
3550 directories_first,
3551 reversed);
3552 } else if (attribute == attribute_size_q) {
3553 return baul_file_compare_for_sort (file_1, file_2,
3554 BAUL_FILE_SORT_BY_SIZE,
3555 directories_first,
3556 reversed);
3557 } else if (attribute == attribute_size_on_disk_q) {
3558 return baul_file_compare_for_sort (file_1, file_2,
3559 BAUL_FILE_SORT_BY_SIZE_ON_DISK,
3560 directories_first,
3561 reversed);
3562 } else if (attribute == attribute_type_q) {
3563 return baul_file_compare_for_sort (file_1, file_2,
3564 BAUL_FILE_SORT_BY_TYPE,
3565 directories_first,
3566 reversed);
3567 } else if (attribute == attribute_modification_date_q || attribute == attribute_date_modified_q) {
3568 return baul_file_compare_for_sort (file_1, file_2,
3569 BAUL_FILE_SORT_BY_MTIME,
3570 directories_first,
3571 reversed);
3572 } else if (attribute == attribute_accessed_date_q || attribute == attribute_date_accessed_q) {
3573 return baul_file_compare_for_sort (file_1, file_2,
3574 BAUL_FILE_SORT_BY_ATIME,
3575 directories_first,
3576 reversed);
3577 } else if (attribute == attribute_trashed_on_q) {
3578 return baul_file_compare_for_sort (file_1, file_2,
3579 BAUL_FILE_SORT_BY_TRASHED_TIME,
3580 directories_first,
3581 reversed);
3582 } else if (attribute == attribute_emblems_q) {
3583 return baul_file_compare_for_sort (file_1, file_2,
3584 BAUL_FILE_SORT_BY_EMBLEMS,
3585 directories_first,
3586 reversed);
3587 } else if (attribute == attribute_extension_q) {
3588 return baul_file_compare_for_sort (file_1, file_2,
3589 BAUL_FILE_SORT_BY_EXTENSION,
3590 directories_first,
3591 reversed);
3592 }
3593
3594 /* it is a normal attribute, compare by strings */
3595
3596 result = baul_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3597
3598 if (result == 0) {
3599 char *value_1;
3600 char *value_2;
3601
3602 value_1 = baul_file_get_string_attribute_q (file_1,
3603 attribute);
3604 value_2 = baul_file_get_string_attribute_q (file_2,
3605 attribute);
3606
3607 if (value_1 != NULL((void*)0) && value_2 != NULL((void*)0)) {
3608 result = strcmp (value_1, value_2);
3609 }
3610
3611 g_free (value_1);
3612 g_free (value_2);
3613
3614 if (reversed) {
3615 result = -result;
3616 }
3617 }
3618
3619 return result;
3620}
3621
3622int
3623baul_file_compare_for_sort_by_attribute (BaulFile *file_1,
3624 BaulFile *file_2,
3625 const char *attribute,
3626 gboolean directories_first,
3627 gboolean reversed)
3628{
3629 return baul_file_compare_for_sort_by_attribute_q (file_1, file_2,
3630 g_quark_from_string (attribute),
3631 directories_first,
3632 reversed);
3633}
3634
3635
3636/**
3637 * baul_file_compare_name:
3638 * @file: A file object
3639 * @pattern: A string we are comparing it with
3640 *
3641 * Return value: result of a comparison of the file name and the given pattern,
3642 * using the same sorting order as sort by name.
3643 **/
3644int
3645baul_file_compare_display_name (BaulFile *file,
3646 const char *pattern)
3647{
3648 const char *name;
3649 int result;
3650
3651 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)
;
3652
3653 name = baul_file_peek_display_name (file);
3654 result = g_utf8_collate (name, pattern);
3655 return result;
3656}
3657
3658
3659gboolean
3660baul_file_is_hidden_file (BaulFile *file)
3661{
3662 return file->details->is_hidden;
3663}
3664
3665gboolean
3666baul_file_is_backup_file (BaulFile *file)
3667{
3668 return file->details->is_backup;
3669}
3670
3671/**
3672 * baul_file_should_show:
3673 * @file: the file to check.
3674 * @show_hidden: whether we want to show hidden files or not.
3675 * @show_backup: whether we want to show backup files or not.
3676 *
3677 * Determines if a #BaulFile should be shown. Note that when browsing
3678 * a trash directory, this function will always return %TRUE.
3679 *
3680 * Returns: %TRUE if the file should be shown, %FALSE if it shouldn't.
3681 */
3682gboolean
3683baul_file_should_show (BaulFile *file,
3684 gboolean show_hidden,
3685 gboolean show_foreign,
3686 gboolean show_backup)
3687{
3688 /* Never hide any files in trash. */
3689 if (baul_file_is_in_trash (file)) {
3690 return TRUE(!(0));
3691 } else {
3692 return (show_hidden || !baul_file_is_hidden_file (file)) &&
3693 (show_backup || !baul_file_is_backup_file (file)) &&
3694 (show_foreign || !(baul_file_is_in_desktop (file) && baul_file_is_foreign_link (file)));
3695 }
3696}
3697
3698gboolean
3699baul_file_is_home (BaulFile *file)
3700{
3701 GFile *dir;
3702
3703 dir = file->details->directory->details->location;
3704 if (dir == NULL((void*)0)) {
3705 return FALSE(0);
3706 }
3707
3708 return baul_is_home_directory_file (dir, file->details->name);
3709}
3710
3711gboolean
3712baul_file_is_in_desktop (BaulFile *file)
3713{
3714 if (file->details->directory->details->location) {
3715 return baul_is_desktop_directory (file->details->directory->details->location);
3716 }
3717 return FALSE(0);
3718
3719}
3720
3721static gboolean
3722filter_hidden_partition_callback (gpointer data,
3723 gpointer callback_data)
3724{
3725 BaulFile *file;
3726 FilterOptions options;
3727
3728 file = BAUL_FILE (data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), (baul_file_get_type())))))
;
3729 options = GPOINTER_TO_INT (callback_data)((gint) (glong) (callback_data));
3730
3731 return baul_file_should_show (file,
3732 options & SHOW_HIDDEN,
3733 TRUE(!(0)),
3734 options & SHOW_BACKUP);
3735}
3736
3737GList *
3738baul_file_list_filter_hidden (GList *files,
3739 gboolean show_hidden)
3740{
3741 GList *filtered_files;
3742 GList *removed_files;
3743
3744 /* FIXME bugzilla.gnome.org 40653:
3745 * Eventually this should become a generic filtering thingy.
3746 */
3747
3748 filtered_files = baul_file_list_copy (files);
3749 filtered_files = eel_g_list_partition (filtered_files,
3750 filter_hidden_partition_callback,
3751 GINT_TO_POINTER ((show_hidden ? SHOW_HIDDEN : 0))((gpointer) (glong) ((show_hidden ? SHOW_HIDDEN : 0))),
3752 &removed_files);
3753 baul_file_list_free (removed_files);
3754
3755 return filtered_files;
3756}
3757
3758char *
3759baul_file_get_metadata (BaulFile *file,
3760 const char *key,
3761 const char *default_metadata)
3762{
3763 guint id;
3764 char *value;
3765
3766 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)
;
3767 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)
;
3768
3769 if (file == NULL((void*)0) ||
3770 file->details->metadata == NULL((void*)0)) {
3771 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3772 }
3773
3774 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)
;
3775
3776 id = baul_metadata_get_id (key);
3777 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3778
3779 if (value) {
3780 return g_strdup (value)g_strdup_inline (value);
3781 }
3782 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3783}
3784
3785GList *
3786baul_file_get_metadata_list (BaulFile *file,
3787 const char *key)
3788{
3789 guint id;
3790 char **value;
3791
3792 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)
;
3793 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)
;
3794
3795 if (file == NULL((void*)0) ||
3796 file->details->metadata == NULL((void*)0)) {
3797 return NULL((void*)0);
3798 }
3799
3800 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)
;
3801
3802 id = baul_metadata_get_id (key);
3803 id |= METADATA_ID_IS_LIST_MASK(1U<<31);
3804
3805 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3806
3807 if (value) {
3808 GList *res;
3809 int i;
3810
3811 res = NULL((void*)0);
3812 for (i = 0; value[i] != NULL((void*)0); i++) {
3813 res = g_list_prepend (res, g_strdup (value[i])g_strdup_inline (value[i]));
3814 }
3815 return g_list_reverse (res);
3816 }
3817
3818 return NULL((void*)0);
3819}
3820
3821void
3822baul_file_set_metadata (BaulFile *file,
3823 const char *key,
3824 const char *default_metadata,
3825 const char *metadata)
3826{
3827 const char *val;
3828
3829 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)
;
3830 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)
;
3831 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)
;
3832
3833 val = metadata;
3834 if (val == NULL((void*)0)) {
3835 val = default_metadata;
3836 }
3837
3838 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)
3839 (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)
3840 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)
;
3841}
3842
3843void
3844baul_file_set_metadata_list (BaulFile *file,
3845 const char *key,
3846 GList *list)
3847{
3848 char **val;
3849 int len, i;
3850 GList *l;
3851
3852 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)
;
3853 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)
;
3854 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)
;
3855
3856 len = g_list_length (list);
3857 val = g_new (char *, len + 1)((char * *) g_malloc_n ((len + 1), sizeof (char *)));
3858 for (l = list, i = 0; l != NULL((void*)0); l = l->next, i++) {
3859 val[i] = l->data;
3860 }
3861 val[i] = NULL((void*)0);
3862
3863 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)
3864 (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)
3865 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)
;
3866
3867 g_free (val);
3868}
3869
3870
3871gboolean
3872baul_file_get_boolean_metadata (BaulFile *file,
3873 const char *key,
3874 gboolean default_metadata)
3875{
3876 char *result_as_string;
3877 gboolean result;
3878
3879 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)
;
3880 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)
;
3881
3882 if (file == NULL((void*)0)) {
3883 return default_metadata;
3884 }
3885
3886 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)
;
3887
3888 result_as_string = baul_file_get_metadata
3889 (file, key, default_metadata ? "true" : "false");
3890 g_assert (result_as_string != NULL)do { if (result_as_string != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 3890, ((const char*) (__func__
)), "result_as_string != NULL"); } while (0)
;
3891
3892 if (g_ascii_strcasecmp (result_as_string, "true") == 0) {
3893 result = TRUE(!(0));
3894 } else if (g_ascii_strcasecmp (result_as_string, "false") == 0) {
3895 result = FALSE(0);
3896 } else {
3897 g_error ("boolean metadata with value other than true or false");
3898 result = default_metadata;
This statement is never executed
3899 }
3900
3901 g_free (result_as_string);
3902 return result;
3903}
3904
3905int
3906baul_file_get_integer_metadata (BaulFile *file,
3907 const char *key,
3908 int default_metadata)
3909{
3910 char *result_as_string;
3911 char default_as_string[32];
3912 int result;
3913 char c;
3914
3915 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)
;
3916 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)
;
3917
3918 if (file == NULL((void*)0)) {
3919 return default_metadata;
3920 }
3921 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)
;
3922
3923 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
3924 result_as_string = baul_file_get_metadata
3925 (file, key, default_as_string);
3926
3927 /* Normally we can't get a a NULL, but we check for it here to
3928 * handle the oddball case of a non-existent directory.
3929 */
3930 if (result_as_string == NULL((void*)0)) {
3931 result = default_metadata;
3932 } else {
3933 if (sscanf (result_as_string, " %d %c", &result, &c) != 1) {
3934 result = default_metadata;
3935 }
3936 g_free (result_as_string);
3937 }
3938
3939 return result;
3940}
3941
3942static gboolean
3943get_time_from_time_string (const char *time_string,
3944 time_t *time)
3945{
3946 long scanned_time;
3947 char c;
3948
3949 g_assert (time != NULL)do { if (time != ((void*)0)) ; else g_assertion_message_expr (
((gchar*) 0), "baul-file.c", 3949, ((const char*) (__func__))
, "time != NULL"); } while (0)
;
3950
3951 /* Only accept string if it has one integer with nothing
3952 * afterwards.
3953 */
3954 if (time_string == NULL((void*)0) ||
3955 sscanf (time_string, "%ld%c", &scanned_time, &c) != 1) {
3956 return FALSE(0);
3957 }
3958 *time = (time_t) scanned_time;
3959 return TRUE(!(0));
3960}
3961
3962time_t
3963baul_file_get_time_metadata (BaulFile *file,
3964 const char *key)
3965{
3966 time_t time;
3967 char *time_string;
3968
3969 time_string = baul_file_get_metadata (file, key, NULL((void*)0));
3970 if (!get_time_from_time_string (time_string, &time)) {
3971 time = UNDEFINED_TIME((time_t) (-1));
3972 }
3973 g_free (time_string);
3974
3975 return time;
3976}
3977
3978void
3979baul_file_set_time_metadata (BaulFile *file,
3980 const char *key,
3981 time_t time)
3982{
3983 char time_str[21];
3984 char *metadata;
3985
3986 if (time != UNDEFINED_TIME((time_t) (-1))) {
3987 /* 2^64 turns out to be 20 characters */
3988 g_snprintf (time_str, 20, "%ld", (long int)time);
3989 time_str[20] = '\0';
3990 metadata = time_str;
3991 } else {
3992 metadata = NULL((void*)0);
3993 }
3994
3995 baul_file_set_metadata (file, key, NULL((void*)0), metadata);
3996}
3997
3998
3999void
4000baul_file_set_boolean_metadata (BaulFile *file,
4001 const char *key,
4002 gboolean default_metadata,
4003 gboolean metadata)
4004{
4005 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)
;
4006 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)
;
4007 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)
;
4008
4009 baul_file_set_metadata (file, key,
4010 default_metadata ? "true" : "false",
4011 metadata ? "true" : "false");
4012}
4013
4014void
4015baul_file_set_integer_metadata (BaulFile *file,
4016 const char *key,
4017 int default_metadata,
4018 int metadata)
4019{
4020 char value_as_string[32];
4021 char default_as_string[32];
4022
4023 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)
;
4024 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)
;
4025 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)
;
4026
4027 g_snprintf (value_as_string, sizeof (value_as_string), "%d", metadata);
4028 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
4029
4030 baul_file_set_metadata (file, key,
4031 default_as_string, value_as_string);
4032}
4033
4034static const char *
4035baul_file_peek_display_name_collation_key (BaulFile *file)
4036{
4037 const char *res;
4038
4039 res = file->details->display_name_collation_key;
4040 if (res == NULL((void*)0))
4041 res = "";
4042
4043 return res;
4044}
4045
4046static const char *
4047baul_file_peek_display_name (BaulFile *file)
4048{
4049 /*
4050 stefano-k: Imported 15_nautilus_file_peek_crash.patch from debian nautilus
4051 Date: Thu, 27 Jan 2011 10:22:10 +0000
4052 Subject: Prevent a crash in nautilus_file_peek_display_name() on invalid NautilusFile
4053 This is more a workaround only, expect assert failures at other
4054 places when something bad happens. There's a race condition somewhere,
4055 this patch only prevents immediate crash.
4056 Patch by Marcus Husar <marcus.husar@rose.uni-heidelberg.de>
4057 https://bugzilla.gnome.org/show_bug.cgi?id=602500
4058 */
4059 if (file == NULL((void*)0) || baul_file_is_gone (file))
4060 return "";
4061
4062 /* Default to display name based on filename if its not set yet */
4063
4064 if (file->details->display_name == NULL((void*)0)) {
4065 const char *name;
4066
4067 name = file->details->name;
4068 if (g_utf8_validate (name, -1, NULL((void*)0))) {
4069 baul_file_set_display_name (file,
4070 name,
4071 NULL((void*)0),
4072 FALSE(0));
4073 } else {
4074 char *escaped_name;
4075
4076 escaped_name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
4077 baul_file_set_display_name (file,
4078 escaped_name,
4079 NULL((void*)0),
4080 FALSE(0));
4081 g_free (escaped_name);
4082 }
4083 }
4084
4085 return file->details->display_name;
4086}
4087
4088char *
4089baul_file_get_display_name (BaulFile *file)
4090{
4091 return g_strdup (baul_file_peek_display_name (file))g_strdup_inline (baul_file_peek_display_name (file));
4092}
4093
4094char *
4095baul_file_get_edit_name (BaulFile *file)
4096{
4097 const char *res;
4098
4099 res = file->details->edit_name;
4100 if (res == NULL((void*)0))
4101 res = "";
4102
4103 return g_strdup (res)g_strdup_inline (res);
4104}
4105
4106char *
4107baul_file_get_name (BaulFile *file)
4108{
4109 return g_strdup (file->details->name)g_strdup_inline (file->details->name);
4110}
4111
4112/**
4113 * baul_file_get_description:
4114 * @file: a #BaulFile.
4115 *
4116 * Gets the standard::description key from @file, if
4117 * it has been cached.
4118 *
4119 * Returns: a string containing the value of the standard::description
4120 * key, or %NULL.
4121 */
4122char *
4123baul_file_get_description (BaulFile *file)
4124{
4125 return g_strdup (file->details->description)g_strdup_inline (file->details->description);
4126}
4127
4128void
4129baul_file_monitor_add (BaulFile *file,
4130 gconstpointer client,
4131 BaulFileAttributes attributes)
4132{
4133 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)
;
4134 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)
;
4135
4136 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)
4137 (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)
4138 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)
;
4139}
4140
4141void
4142baul_file_monitor_remove (BaulFile *file,
4143 gconstpointer client)
4144{
4145 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)
;
4146 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)
;
4147
4148 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)
4149 (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)
4150 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)
;
4151}
4152
4153gboolean
4154baul_file_is_launcher (BaulFile *file)
4155{
4156 return file->details->is_launcher;
4157}
4158
4159gboolean
4160baul_file_is_foreign_link (BaulFile *file)
4161{
4162 return file->details->is_foreign_link;
4163}
4164
4165gboolean
4166baul_file_is_trusted_link (BaulFile *file)
4167{
4168 return file->details->is_trusted_link;
4169}
4170
4171gboolean
4172baul_file_has_activation_uri (BaulFile *file)
4173{
4174 return file->details->activation_uri != NULL((void*)0);
4175}
4176
4177
4178/* Return the uri associated with the passed-in file, which may not be
4179 * the actual uri if the file is an desktop file or a baul
4180 * xml link file.
4181 */
4182char *
4183baul_file_get_activation_uri (BaulFile *file)
4184{
4185 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)
;
4186
4187 if (file->details->activation_uri != NULL((void*)0)) {
4188 return g_strdup (file->details->activation_uri)g_strdup_inline (file->details->activation_uri);
4189 }
4190
4191 return baul_file_get_uri (file);
4192}
4193
4194GFile *
4195baul_file_get_activation_location (BaulFile *file)
4196{
4197 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)
;
4198
4199 if (file->details->activation_uri != NULL((void*)0)) {
4200 return g_file_new_for_uri (file->details->activation_uri);
4201 }
4202
4203 return baul_file_get_location (file);
4204}
4205
4206
4207char *
4208baul_file_get_drop_target_uri (BaulFile *file)
4209{
4210 char *uri, *target_uri;
4211 GFile *location;
4212
4213 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)
;
4214
4215 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; }))))
) {
4216 BaulDesktopLink *link;
4217
4218 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
())))))
);
4219
4220 if (link != NULL((void*)0)) {
4221 location = baul_desktop_link_get_activation_location (link);
4222 g_object_unref (link);
4223 if (location != NULL((void*)0)) {
4224 uri = g_file_get_uri (location);
4225 g_object_unref (location);
4226 return uri;
4227 }
4228 }
4229 }
4230
4231 uri = baul_file_get_uri (file);
4232
4233 /* Check for Baul link */
4234 if (baul_file_is_baul_link (file)) {
4235 location = baul_file_get_location (file);
4236 /* FIXME bugzilla.gnome.org 43020: This does sync. I/O and works only locally. */
4237 if (g_file_is_native (location)) {
4238 target_uri = baul_link_local_get_link_uri (uri);
4239 if (target_uri != NULL((void*)0)) {
4240 g_free (uri);
4241 uri = target_uri;
4242 }
4243 }
4244 g_object_unref (location);
4245 }
4246
4247 return uri;
4248}
4249
4250static gboolean
4251is_uri_relative (const char *uri)
4252{
4253 char *scheme;
4254 gboolean ret;
4255
4256 scheme = g_uri_parse_scheme (uri);
4257 ret = (scheme == NULL((void*)0));
4258 g_free (scheme);
4259 return ret;
4260}
4261
4262static char *
4263get_custom_icon_metadata_uri (BaulFile *file)
4264{
4265 char *custom_icon_uri;
4266 char *uri;
4267
4268 uri = baul_file_get_metadata (file, BAUL_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0));
4269 if (uri != NULL((void*)0) &&
4270 baul_file_is_directory (file) &&
4271 is_uri_relative (uri)) {
4272 char *dir_uri;
4273
4274 dir_uri = baul_file_get_uri (file);
4275 custom_icon_uri = g_build_filename (dir_uri, uri, NULL((void*)0));
4276 g_free (dir_uri);
4277 g_free (uri);
4278 } else {
4279 custom_icon_uri = uri;
4280 }
4281 return custom_icon_uri;
4282}
4283
4284static GIcon *
4285get_custom_icon (BaulFile *file)
4286{
4287 char *custom_icon_uri;
4288 GFile *icon_file;
4289 GIcon *icon;
4290
4291 if (file == NULL((void*)0)) {
4292 return NULL((void*)0);
4293 }
4294
4295 icon = NULL((void*)0);
4296
4297 /* Metadata takes precedence */
4298 custom_icon_uri = get_custom_icon_metadata_uri (file);
4299
4300 if (custom_icon_uri) {
4301 icon_file = g_file_new_for_uri (custom_icon_uri);
4302 icon = g_file_icon_new (icon_file);
4303 g_object_unref (icon_file);
4304 g_free (custom_icon_uri);
4305 }
4306
4307 if (icon == NULL((void*)0) && file->details->got_link_info && file->details->custom_icon != NULL((void*)0)) {
4308 if (g_path_is_absolute (file->details->custom_icon)) {
4309 icon_file = g_file_new_for_path (file->details->custom_icon);
4310 icon = g_file_icon_new (icon_file);
4311 g_object_unref (icon_file);
4312 } else {
4313 icon = g_themed_icon_new (file->details->custom_icon);
4314 }
4315 }
4316
4317 return icon;
4318}
4319
4320
4321static guint64 cached_thumbnail_limit;
4322int cached_thumbnail_size;
4323static int show_image_thumbs;
4324
4325GFilesystemPreviewType
4326baul_file_get_filesystem_use_preview (BaulFile *file)
4327{
4328 GFilesystemPreviewType use_preview;
4329 BaulFile *parent;
4330
4331 parent = baul_file_get_parent (file);
4332 if (parent != NULL((void*)0)) {
4333 use_preview = parent->details->filesystem_use_preview;
4334 g_object_unref (parent);
4335 } else {
4336 use_preview = 0;
4337 }
4338
4339 return use_preview;
4340}
4341
4342gboolean
4343baul_file_should_show_thumbnail (BaulFile *file)
4344{
4345 const char *mime_type;
4346 GFilesystemPreviewType use_preview;
4347
4348 use_preview = baul_file_get_filesystem_use_preview (file);
4349
4350 mime_type = file->details->mime_type;
4351 if (mime_type == NULL((void*)0)) {
4352 mime_type = "application/octet-stream";
4353 }
4354
4355 /* If the thumbnail has already been created, don't care about the size
4356 * of the original file.
4357 */
4358 if (baul_thumbnail_is_mimetype_limited_by_size (mime_type) &&
4359 file->details->thumbnail_path == NULL((void*)0) &&
4360 baul_file_get_size (file) > cached_thumbnail_limit) {
4361 return FALSE(0);
4362 }
4363
4364 if (show_image_thumbs == BAUL_SPEED_TRADEOFF_ALWAYS) {
4365 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4366 return FALSE(0);
4367 } else {
4368 return TRUE(!(0));
4369 }
4370 } else if (show_image_thumbs == BAUL_SPEED_TRADEOFF_NEVER) {
4371 return FALSE(0);
4372 } else {
4373 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4374 /* file system says to never thumbnail anything */
4375 return FALSE(0);
4376 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
4377 /* file system says we should treat file as if it's local */
4378 return TRUE(!(0));
4379 } else {
4380 /* only local files */
4381 return baul_file_is_local (file);
4382 }
4383 }
4384
4385 return FALSE(0);
4386}
4387
4388static void
4389prepend_icon_name (const char *name,
4390 GThemedIcon *icon)
4391{
4392 g_themed_icon_prepend_name(icon, name);
4393}
4394
4395GIcon *
4396baul_file_get_gicon (BaulFile *file,
4397 BaulFileIconFlags flags)
4398{
4399 const char * const * names;
4400 GIcon *icon, *mount_icon = NULL((void*)0), *emblemed_icon;
4401 gboolean is_folder = FALSE(0), is_preview = FALSE(0), is_inode_directory = FALSE(0);
4402
4403 if (file == NULL((void*)0)) {
4404 return NULL((void*)0);
4405 }
4406
4407 icon = get_custom_icon (file);
4408 if (icon != NULL((void*)0)) {
4409 return icon;
4410 }
4411
4412 if (file->details->icon) {
4413 icon = NULL((void*)0);
4414
4415 /* fetch the mount icon here, we'll use it later */
4416 if (flags & BAUL_FILE_ICON_FLAGS_USE_MOUNT_ICON ||
4417 flags & BAUL_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) {
4418 GMount *mount;
4419
4420 mount = baul_file_get_mount (file);
4421
4422 if (mount != NULL((void*)0)) {
4423 mount_icon = g_mount_get_icon (mount);
4424 g_object_unref (mount);
4425 }
4426 }
4427
4428 if (((flags & BAUL_FILE_ICON_FLAGS_EMBEDDING_TEXT) ||
4429 (flags & BAUL_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT) ||
4430 (flags & BAUL_FILE_ICON_FLAGS_FOR_OPEN_FOLDER) ||
4431 (flags & BAUL_FILE_ICON_FLAGS_USE_MOUNT_ICON) ||
4432 (flags & BAUL_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) ||
4433 ((flags & BAUL_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4434 baul_file_has_open_window (file))) &&
4435 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; }))))
) {
4436 GPtrArray *prepend_array;
4437 int i;
4438
4439 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 ()
))))))
);
4440 prepend_array = g_ptr_array_new ();
4441
4442 for (i = 0; names[i] != NULL((void*)0); i++) {
4443 const char *name;
4444
4445 name = names[i];
4446
4447 if (strcmp (name, "folder") == 0) {
4448 is_folder = TRUE(!(0));
4449 }
4450 if (strcmp (name, "inode-directory") == 0) {
4451 is_inode_directory = TRUE(!(0));
4452 }
4453 if (strcmp (name, "text-x-generic") == 0 &&
4454 (flags & BAUL_FILE_ICON_FLAGS_EMBEDDING_TEXT)) {
4455 is_preview = TRUE(!(0));
4456 }
4457 }
4458
4459 /* Here, we add icons in reverse order of precedence,
4460 * because they are later prepended */
4461 if (is_preview) {
4462 g_ptr_array_add (prepend_array, "text-x-preview");
4463 }
4464
4465 /* "folder" should override "inode-directory", not the other way around */
4466 if (is_inode_directory) {
4467 g_ptr_array_add (prepend_array, "folder");
4468 }
4469 if (is_folder && (flags & BAUL_FILE_ICON_FLAGS_FOR_OPEN_FOLDER)) {
4470 g_ptr_array_add (prepend_array, "folder-open");
4471 }
4472 if (is_folder &&
4473 (flags & BAUL_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4474 baul_file_has_open_window (file)) {
4475 g_ptr_array_add (prepend_array, "folder-visiting");
4476 }
4477 if (is_folder &&
4478 (flags & BAUL_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT)) {
4479 g_ptr_array_add (prepend_array, "folder-drag-accept");
4480 }
4481
4482 if (prepend_array->len) {
4483 /* When constructing GThemed Icon, pointers from the array
4484 * are reused, but not the array itself, so the cast is safe */
4485 icon = g_themed_icon_new_from_names ((char**) names, -1);
4486 g_ptr_array_foreach (prepend_array, (GFunc) prepend_icon_name, icon);
4487 }
4488
4489 g_ptr_array_free (prepend_array, TRUE(!(0)));
4490 }
4491
4492 if (icon == NULL((void*)0)) {
4493 icon = g_object_ref (file->details->icon)((__typeof__ (file->details->icon)) (g_object_ref) (file
->details->icon))
;
4494 }
4495
4496 if ((flags & BAUL_FILE_ICON_FLAGS_USE_MOUNT_ICON) &&
4497 mount_icon != NULL((void*)0)) {
4498 g_object_unref (icon);
4499 icon = mount_icon;
4500 } else if ((flags & BAUL_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) &&
4501 mount_icon != NULL((void*)0) && !g_icon_equal (mount_icon, icon)) {
4502 GEmblem *emblem;
4503
4504 emblem = g_emblem_new (mount_icon);
4505 emblemed_icon = g_emblemed_icon_new (icon, emblem);
4506
4507 g_object_unref (emblem);
4508 g_object_unref (icon);
4509 g_object_unref (mount_icon);
4510
4511 icon = emblemed_icon;
4512 } else if (mount_icon != NULL((void*)0)) {
4513 g_object_unref (mount_icon);
4514 }
4515
4516 return icon;
4517 }
4518
4519 return g_themed_icon_new ("text-x-generic");
4520}
4521
4522static GIcon *
4523get_default_file_icon (BaulFileIconFlags flags)
4524{
4525 static GIcon *fallback_icon = NULL((void*)0);
4526 static GIcon *fallback_icon_preview = NULL((void*)0);
4527 if (fallback_icon == NULL((void*)0)) {
4528 fallback_icon = g_themed_icon_new ("text-x-generic");
4529 fallback_icon_preview = g_themed_icon_new ("text-x-preview");
4530 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");
4531 }
4532 if (flags & BAUL_FILE_ICON_FLAGS_EMBEDDING_TEXT) {
4533 return fallback_icon_preview;
4534 } else {
4535 return fallback_icon;
4536 }
4537}
4538
4539BaulIconInfo *
4540baul_file_get_icon (BaulFile *file,
4541 int size,
4542 int scale,
4543 BaulFileIconFlags flags)
4544{
4545 BaulIconInfo *icon;
4546 GIcon *gicon;
4547 GdkPixbuf *scaled_pixbuf;
4548
4549 if (file == NULL((void*)0)) {
4550 return NULL((void*)0);
4551 }
4552
4553 gicon = get_custom_icon (file);
4554 if (gicon) {
4555 GdkPixbuf *pixbuf;
4556
4557 icon = baul_icon_info_lookup (gicon, size, scale);
4558 g_object_unref (gicon);
4559
4560 pixbuf = baul_icon_info_get_pixbuf (icon);
4561 if (pixbuf != NULL((void*)0)) {
4562 if (!file->details->is_launcher && !gdk_pixbuf_get_has_alpha (pixbuf)) {
4563 baul_ui_frame_image (&pixbuf);
4564 }
4565 g_object_unref (icon);
4566
4567 icon = baul_icon_info_new_for_pixbuf (pixbuf, scale);
4568 g_object_unref (pixbuf);
4569 }
4570
4571 return icon;
4572 }
4573
4574 if (flags & BAUL_FILE_ICON_FLAGS_USE_THUMBNAILS &&
4575 baul_file_should_show_thumbnail (file)) {
4576 int modified_size;
4577
4578 if (flags & BAUL_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE) {
4579 modified_size = size * scale;
4580 } else {
4581 modified_size = size * scale * cached_thumbnail_size / BAUL_ICON_SIZE_STANDARD48;
4582 }
4583
4584 if (file->details->thumbnail) {
4585 int w, h, s;
4586 double thumb_scale;
4587 GdkPixbuf *raw_pixbuf;
4588
4589 raw_pixbuf = g_object_ref (file->details->thumbnail)((__typeof__ (file->details->thumbnail)) (g_object_ref)
(file->details->thumbnail))
;
4590
4591 w = gdk_pixbuf_get_width (raw_pixbuf);
4592 h = gdk_pixbuf_get_height (raw_pixbuf);
4593
4594 s = MAX (w, h)(((w) > (h)) ? (w) : (h));
4595 /* Don't scale up small thumbnails in the standard view */
4596 if (s <= cached_thumbnail_size) {
4597 thumb_scale = (double)size / BAUL_ICON_SIZE_STANDARD48;
4598 }
4599 else {
4600 thumb_scale = (double)modified_size / s;
4601 }
4602 /* Make sure that icons don't get smaller than BAUL_ICON_SIZE_SMALLEST */
4603 if (s*thumb_scale <= BAUL_ICON_SIZE_SMALLEST16) {
4604 thumb_scale = (double) BAUL_ICON_SIZE_SMALLEST16 / s;
4605 }
4606
4607 scaled_pixbuf = gdk_pixbuf_scale_simple (raw_pixbuf,
4608 MAX (w * thumb_scale, 1)(((w * thumb_scale) > (1)) ? (w * thumb_scale) : (1)),
4609 MAX (h * thumb_scale, 1)(((h * thumb_scale) > (1)) ? (h * thumb_scale) : (1)),
4610 GDK_INTERP_BILINEAR);
4611
4612 /* Render frames only for thumbnails of non-image files
4613 and for images with no alpha channel. */
4614 gboolean is_image = file->details->mime_type &&
4615 (strncmp (file->details->mime_type, "image/", 6) == 0);
4616 if (!is_image || !gdk_pixbuf_get_has_alpha (raw_pixbuf)) {
4617 baul_ui_frame_image (&scaled_pixbuf);
4618 }
4619
4620 g_object_unref (raw_pixbuf);
4621
4622 /* Don't scale up if more than 25%, then read the original
4623 image instead. We don't want to compare to exactly 100%,
4624 since the zoom level 150% gives thumbnails at 144, which is
4625 ok to scale up from 128. */
4626 if (modified_size > 128 * 1.25 * scale &&
4627 !file->details->thumbnail_wants_original &&
4628 baul_can_thumbnail_internally (file)) {
4629 /* Invalidate if we resize upward */
4630 file->details->thumbnail_wants_original = TRUE(!(0));
4631 baul_file_invalidate_attributes (file, BAUL_FILE_ATTRIBUTE_THUMBNAIL);
4632 }
4633
4634 icon = baul_icon_info_new_for_pixbuf (scaled_pixbuf, scale);
4635 g_object_unref (scaled_pixbuf);
4636 return icon;
4637 } else if (file->details->thumbnail_path == NULL((void*)0) &&
4638 file->details->can_read &&
4639 !file->details->is_thumbnailing &&
4640 !file->details->thumbnailing_failed) {
4641 if (baul_can_thumbnail (file)) {
4642 baul_create_thumbnail (file);
4643 }
4644 }
4645 }
4646
4647 if (file->details->is_thumbnailing &&
4648 flags & BAUL_FILE_ICON_FLAGS_USE_THUMBNAILS)
4649 gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING"image-loading");
4650 else
4651 gicon = baul_file_get_gicon (file, flags);
4652
4653 if (gicon) {
4654 icon = baul_icon_info_lookup (gicon, size, scale);
4655 g_object_unref (gicon);
4656 return icon;
4657 } else {
4658 return baul_icon_info_lookup (get_default_file_icon (flags), size, scale);
4659 }
4660}
4661
4662cairo_surface_t *
4663baul_file_get_icon_surface (BaulFile *file,
4664 int size,
4665 gboolean force_size,
4666 int scale,
4667 BaulFileIconFlags flags)
4668{
4669 BaulIconInfo *info;
4670 cairo_surface_t *surface;
4671
4672 info = baul_file_get_icon (file, size, scale, flags);
4673 if (force_size) {
4674 surface = baul_icon_info_get_surface_at_size (info, size);
4675 } else {
4676 surface = baul_icon_info_get_surface (info);
4677 }
4678 g_object_unref (info);
4679
4680 return surface;
4681}
4682
4683char *
4684baul_file_get_custom_icon (BaulFile *file)
4685{
4686 char *custom_icon;
4687
4688 if (file == NULL((void*)0)) {
4689 return NULL((void*)0);
4690 }
4691
4692 /* Metadata takes precedence */
4693 custom_icon = get_custom_icon_metadata_uri (file);
4694
4695 if (custom_icon == NULL((void*)0) && file->details->got_link_info) {
4696 custom_icon = g_strdup (file->details->custom_icon)g_strdup_inline (file->details->custom_icon);
4697 }
4698
4699 return custom_icon;
4700}
4701
4702
4703gboolean
4704baul_file_get_date (BaulFile *file,
4705 BaulDateType date_type,
4706 time_t *date)
4707{
4708 if (date != NULL((void*)0)) {
4709 *date = 0;
4710 }
4711
4712 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)
4713 || 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)
4714 || 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)
4715 || 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)
4716 || 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)
;
4717
4718 if (file == NULL((void*)0)) {
4719 return FALSE(0);
4720 }
4721
4722 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)
;
4723
4724 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))
4725 (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))
4726 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))
;
4727}
4728
4729static char *
4730baul_file_get_where_string (BaulFile *file)
4731{
4732 if (file == NULL((void*)0)) {
4733 return NULL((void*)0);
4734 }
4735
4736 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)
;
4737
4738 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))
4739 (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))
4740 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))
;
4741}
4742
4743static const char *TODAY_TIME_FORMATS [] = {
4744 /* Today, use special word.
4745 * strftime patterns preceeded with the widest
4746 * possible resulting string for that pattern.
4747 *
4748 * Note to localizers: You can look at man strftime
4749 * for details on the format, but you should only use
4750 * the specifiers from the C standard, not extensions.
4751 * These include "%" followed by one of
4752 * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions
4753 * in the Baul version of strftime that can be
4754 * used (and match GNU extensions). Putting a "-"
4755 * between the "%" and any numeric directive will turn
4756 * off zero padding, and putting a "_" there will use
4757 * space padding instead of zero padding.
4758 */
4759 N_("today at 00:00:00 PM")("today at 00:00:00 PM"),
4760 N_("today at %-I:%M:%S %p")("today at %-I:%M:%S %p"),
4761
4762 N_("today at 00:00 PM")("today at 00:00 PM"),
4763 N_("today at %-I:%M %p")("today at %-I:%M %p"),
4764
4765 N_("today, 00:00 PM")("today, 00:00 PM"),
4766 N_("today, %-I:%M %p")("today, %-I:%M %p"),
4767
4768 N_("today")("today"),
4769 N_("today")("today"),
4770
4771 NULL((void*)0)
4772};
4773
4774static const char *YESTERDAY_TIME_FORMATS [] = {
4775 /* Yesterday, use special word.
4776 * Note to localizers: Same issues as "today" string.
4777 */
4778 N_("yesterday at 00:00:00 PM")("yesterday at 00:00:00 PM"),
4779 N_("yesterday at %-I:%M:%S %p")("yesterday at %-I:%M:%S %p"),
4780
4781 N_("yesterday at 00:00 PM")("yesterday at 00:00 PM"),
4782 N_("yesterday at %-I:%M %p")("yesterday at %-I:%M %p"),
4783
4784 N_("yesterday, 00:00 PM")("yesterday, 00:00 PM"),
4785 N_("yesterday, %-I:%M %p")("yesterday, %-I:%M %p"),
4786
4787 N_("yesterday")("yesterday"),
4788 N_("yesterday")("yesterday"),
4789
4790 NULL((void*)0)
4791};
4792
4793static const char *CURRENT_WEEK_TIME_FORMATS [] = {
4794 /* Current week, include day of week.
4795 * Note to localizers: Same issues as "today" string.
4796 * The width measurement templates correspond to
4797 * the day/month name with the most letters.
4798 */
4799 N_("Wednesday, September 00 0000 at 00:00:00 PM")("Wednesday, September 00 0000 at 00:00:00 PM"),
4800 N_("%A, %B %-d %Y at %-I:%M:%S %p")("%A, %B %-d %Y at %-I:%M:%S %p"),
4801
4802 N_("Mon, Oct 00 0000 at 00:00:00 PM")("Mon, Oct 00 0000 at 00:00:00 PM"),
4803 N_("%a, %b %-d %Y at %-I:%M:%S %p")("%a, %b %-d %Y at %-I:%M:%S %p"),
4804
4805 N_("Mon, Oct 00 0000 at 00:00 PM")("Mon, Oct 00 0000 at 00:00 PM"),
4806 N_("%a, %b %-d %Y at %-I:%M %p")("%a, %b %-d %Y at %-I:%M %p"),
4807
4808 N_("Oct 00 0000 at 00:00 PM")("Oct 00 0000 at 00:00 PM"),
4809 N_("%b %-d %Y at %-I:%M %p")("%b %-d %Y at %-I:%M %p"),
4810
4811 N_("Oct 00 0000, 00:00 PM")("Oct 00 0000, 00:00 PM"),
4812 N_("%b %-d %Y, %-I:%M %p")("%b %-d %Y, %-I:%M %p"),
4813
4814 N_("00/00/00, 00:00 PM")("00/00/00, 00:00 PM"),
4815 N_("%m/%-d/%y, %-I:%M %p")("%m/%-d/%y, %-I:%M %p"),
4816
4817 N_("00/00/00")("00/00/00"),
4818 N_("%m/%d/%y")("%m/%d/%y"),
4819
4820 NULL((void*)0)
4821};
4822
4823static char *
4824baul_file_fit_date_as_string (BaulFile *file,
4825 BaulDateType date_type,
4826 int width,
4827 BaulWidthMeasureCallback measure_callback,
4828 BaulTruncateCallback truncate_callback,
4829 void *measure_context)
4830{
4831 time_t file_time_raw;
4832 const char **formats;
4833 const char *format;
4834 char *date_string;
4835 gchar *result = NULL((void*)0);
4836 int i;
4837 GDateTime *date_time, *today;
4838 GTimeSpan file_date_age;
4839
4840 if (!baul_file_get_date (file, date_type, &file_time_raw)) {
4841 return NULL((void*)0);
4842 }
4843
4844 date_time = g_date_time_new_from_unix_local (file_time_raw);
4845
4846 if (date_format_pref == BAUL_DATE_FORMAT_LOCALE) {
4847 result = g_date_time_format (date_time, "%c");
4848 goto out;
4849 } else if (date_format_pref == BAUL_DATE_FORMAT_ISO) {
4850 result = g_date_time_format (date_time, "%Y-%m-%d %H:%M:%S");
4851 goto out;
4852 }
4853
4854 today = g_date_time_new_now_local ();
4855 file_date_age = g_date_time_difference (today, date_time);
4856 g_date_time_unref (today);
4857
4858 /* Format varies depending on how old the date is. This minimizes
4859 * the length (and thus clutter & complication) of typical dates
4860 * while providing sufficient detail for recent dates to make
4861 * them maximally understandable at a glance. Keep all format
4862 * strings separate rather than combining bits & pieces for
4863 * internationalization's sake.
4864 */
4865
4866 if (file_date_age < G_TIME_SPAN_DAY((86400000000L))) {
4867 formats = TODAY_TIME_FORMATS;
4868 } else if (file_date_age < 2 * G_TIME_SPAN_DAY((86400000000L))) {
4869 formats = YESTERDAY_TIME_FORMATS;
4870 } else {
4871 formats = CURRENT_WEEK_TIME_FORMATS;
4872 }
4873
4874 /* Find the date format that just fits the required width. Instead of measuring
4875 * the resulting string width directly, measure the width of a template that represents
4876 * the widest possible version of a date in a given format. This is done by using M, m
4877 * and 0 for the variable letters/digits respectively.
4878 */
4879 format = NULL((void*)0);
4880
4881 for (i = 0; ; i += 2) {
4882 const char *width_template;
4883
4884 width_template = (formats [i] ? _(formats [i])gettext (formats [i]) : NULL((void*)0));
4885 if (width_template == NULL((void*)0)) {
4886 /* no more formats left */
4887 g_assert (format != NULL)do { if (format != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 4887, ((const char*) (__func__
)), "format != NULL"); } while (0)
;
4888
4889 /* Can't fit even the shortest format -- return an ellipsized form in the
4890 * shortest format
4891 */
4892
4893 date_string = g_date_time_format (date_time, format);
4894
4895 if (truncate_callback == NULL((void*)0)) {
4896 result = date_string;
4897 break;
4898 }
4899
4900 result = (* truncate_callback) (date_string, width, measure_context);
4901 g_free (date_string);
4902 break;
4903 }
4904
4905 format = _(formats [i + 1])gettext (formats [i + 1]);
4906
4907 if (measure_callback == NULL((void*)0)) {
4908 /* don't care about fitting the width */
4909 break;
4910 }
4911
4912 if ((* measure_callback) (width_template, measure_context) <= width) {
4913 /* The template fits, this is the format we can fit. */
4914 break;
4915 }
4916 }
4917
4918 if (result == NULL((void*)0)) {
4919 result = g_date_time_format (date_time, format);
4920 }
4921
4922out:
4923 g_date_time_unref (date_time);
4924 return result;
4925}
4926
4927/**
4928 * baul_file_fit_modified_date_as_string:
4929 *
4930 * Get a user-displayable string representing a file modification date,
4931 * truncated to @width using the measuring and truncating callbacks.
4932 * @file: BaulFile representing the file in question.
4933 * @width: The desired resulting string width.
4934 * @measure_callback: The callback used to measure the string width.
4935 * @truncate_callback: The callback used to truncate the string to a desired width.
4936 * @measure_context: Data neede when measuring and truncating.
4937 *
4938 * Returns: Newly allocated string ready to display to the user.
4939 *
4940 **/
4941char *
4942baul_file_fit_modified_date_as_string (BaulFile *file,
4943 int width,
4944 BaulWidthMeasureCallback measure_callback,
4945 BaulTruncateCallback truncate_callback,
4946 void *measure_context)
4947{
4948 return baul_file_fit_date_as_string (file, BAUL_DATE_TYPE_MODIFIED,
4949 width, measure_callback, truncate_callback, measure_context);
4950}
4951
4952static char *
4953baul_file_get_trash_original_file_parent_as_string (BaulFile *file)
4954{
4955 if (file->details->trash_orig_path != NULL((void*)0)) {
4956 BaulFile *orig_file, *parent;
4957 GFile *location;
4958 char *filename;
4959
4960 orig_file = baul_file_get_trash_original_file (file);
4961 parent = baul_file_get_parent (orig_file);
4962 location = baul_file_get_location (parent);
4963
4964 filename = g_file_get_parse_name (location);
4965
4966 g_object_unref (location);
4967 baul_file_unref (parent);
4968 baul_file_unref (orig_file);
4969
4970 return filename;
4971 }
4972
4973 return NULL((void*)0);
4974}
4975
4976/**
4977 * baul_file_get_date_as_string:
4978 *
4979 * Get a user-displayable string representing a file modification date.
4980 * The caller is responsible for g_free-ing this string.
4981 * @file: BaulFile representing the file in question.
4982 *
4983 * Returns: Newly allocated string ready to display to the user.
4984 *
4985 **/
4986static char *
4987baul_file_get_date_as_string (BaulFile *file, BaulDateType date_type)
4988{
4989 return baul_file_fit_date_as_string (file, date_type,
4990 0, NULL((void*)0), NULL((void*)0), NULL((void*)0));
4991}
4992
4993static BaulSpeedTradeoffValue show_directory_item_count;
4994static BaulSpeedTradeoffValue show_text_in_icons;
4995
4996static void
4997show_text_in_icons_changed_callback (gpointer callback_data)
4998{
4999 show_text_in_icons = g_settings_get_enum (baul_preferences, BAUL_PREFERENCES_SHOW_TEXT_IN_ICONS"show-icon-text");
5000}
5001
5002static void
5003show_directory_item_count_changed_callback (gpointer callback_data)
5004{
5005 show_directory_item_count = g_settings_get_enum (baul_preferences, BAUL_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS"show-directory-item-counts");
5006}
5007
5008static gboolean
5009get_speed_tradeoff_preference_for_file (BaulFile *file, BaulSpeedTradeoffValue value)
5010{
5011 GFilesystemPreviewType use_preview;
5012
5013 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)
;
5014
5015 use_preview = baul_file_get_filesystem_use_preview (file);
5016
5017 if (value == BAUL_SPEED_TRADEOFF_ALWAYS) {
5018 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5019 return FALSE(0);
5020 } else {
5021 return TRUE(!(0));
5022 }
5023 }
5024
5025 if (value == BAUL_SPEED_TRADEOFF_NEVER) {
5026 return FALSE(0);
5027 }
5028
5029 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", 5029, ((const char*) (__func__
)), "value == BAUL_SPEED_TRADEOFF_LOCAL_ONLY"); } while (0)
;
5030
5031 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5032 /* file system says to never preview anything */
5033 return FALSE(0);
5034 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
5035 /* file system says we should treat file as if it's local */
5036 return TRUE(!(0));
5037 } else {
5038 /* only local files */
5039 return baul_file_is_local (file);
5040 }
5041}
5042
5043gboolean
5044baul_file_should_show_directory_item_count (BaulFile *file)
5045{
5046 static gboolean show_directory_item_count_callback_added = FALSE(0);
5047
5048 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)
;
5049
5050 if (file->details->mime_type &&
5051 strcmp (file->details->mime_type, "x-directory/smb-share") == 0) {
5052 return FALSE(0);
5053 }
5054
5055 /* Add the callback once for the life of our process */
5056 if (!show_directory_item_count_callback_added) {
5057 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)
5058 "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)
5059 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)
5060 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)
;
5061 show_directory_item_count_callback_added = TRUE(!(0));
5062
5063 /* Peek for the first time */
5064 show_directory_item_count_changed_callback (NULL((void*)0));
5065 }
5066
5067 return get_speed_tradeoff_preference_for_file (file, show_directory_item_count);
5068}
5069
5070gboolean
5071baul_file_should_show_type (BaulFile *file)
5072{
5073 char *uri;
5074 gboolean ret;
5075
5076 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)
;
5077
5078 uri = baul_file_get_uri (file);
5079 ret = ((strcmp (uri, "computer:///") != 0) &&
5080 (strcmp (uri, "network:///") != 0) &&
5081 (strcmp (uri, "smb:///") != 0));
5082 g_free (uri);
5083
5084 return ret;
5085}
5086
5087gboolean
5088baul_file_should_get_top_left_text (BaulFile *file)
5089{
5090 static gboolean show_text_in_icons_callback_added = FALSE(0);
5091
5092 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)
;
5093
5094 /* Add the callback once for the life of our process */
5095 if (!show_text_in_icons_callback_added) {
5096 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)
5097 "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)
5098 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)
5099 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)
;
5100 show_text_in_icons_callback_added = TRUE(!(0));
5101
5102 /* Peek for the first time */
5103 show_text_in_icons_changed_callback (NULL((void*)0));
5104 }
5105
5106 if (show_text_in_icons == BAUL_SPEED_TRADEOFF_ALWAYS) {
5107 return TRUE(!(0));
5108 }
5109
5110 if (show_text_in_icons == BAUL_SPEED_TRADEOFF_NEVER) {
5111 return FALSE(0);
5112 }
5113
5114 return get_speed_tradeoff_preference_for_file (file, show_text_in_icons);
5115}
5116
5117/**
5118 * baul_file_get_directory_item_count
5119 *
5120 * Get the number of items in a directory.
5121 * @file: BaulFile representing a directory.
5122 * @count: Place to put count.
5123 * @count_unreadable: Set to TRUE (if non-NULL) if permissions prevent
5124 * the item count from being read on this directory. Otherwise set to FALSE.
5125 *
5126 * Returns: TRUE if count is available.
5127 *
5128 **/
5129gboolean
5130baul_file_get_directory_item_count (BaulFile *file,
5131 guint *count,
5132 gboolean *count_unreadable)
5133{
5134 if (count != NULL((void*)0)) {
5135 *count = 0;
5136 }
5137 if (count_unreadable != NULL((void*)0)) {
5138 *count_unreadable = FALSE(0);
5139 }
5140
5141 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)
;
5142
5143 if (!baul_file_is_directory (file)) {
5144 return FALSE(0);
5145 }
5146
5147 if (!baul_file_should_show_directory_item_count (file)) {
5148 return FALSE(0);
5149 }
5150
5151 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))
5152 (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))
5153 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))
;
5154}
5155
5156/**
5157 * baul_file_get_deep_counts
5158 *
5159 * Get the statistics about items inside a directory.
5160 * @file: BaulFile representing a directory or file.
5161 * @directory_count: Place to put count of directories inside.
5162 * @files_count: Place to put count of files inside.
5163 * @unreadable_directory_count: Number of directories encountered
5164 * that were unreadable.
5165 * @total_size: Total size of all files and directories visited.
5166 * @total_size_on_disk: Total size on disk of all files and directories visited.
5167 * @force: Whether the deep counts should even be collected if
5168 * baul_file_should_show_directory_item_count returns FALSE
5169 * for this file.
5170 *
5171 * Returns: Status to indicate whether sizes are available.
5172 *
5173 **/
5174BaulRequestStatus
5175baul_file_get_deep_counts (BaulFile *file,
5176 guint *directory_count,
5177 guint *file_count,
5178 guint *unreadable_directory_count,
5179 goffset *total_size,
5180 goffset *total_size_on_disk,
5181 gboolean force)
5182{
5183 if (directory_count != NULL((void*)0)) {
5184 *directory_count = 0;
5185 }
5186 if (file_count != NULL((void*)0)) {
5187 *file_count = 0;
5188 }
5189 if (unreadable_directory_count != NULL((void*)0)) {
5190 *unreadable_directory_count = 0;
5191 }
5192 if (total_size != NULL((void*)0)) {
5193 *total_size = 0;
5194 }
5195 if (total_size_on_disk != NULL((void*)0)) {
5196 *total_size_on_disk = 0;
5197 }
5198
5199 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)
;
5200
5201 if (!force && !baul_file_should_show_directory_item_count (file)) {
5202 /* Set field so an existing value isn't treated as up-to-date
5203 * when preference changes later.
5204 */
5205 file->details->deep_counts_status = BAUL_REQUEST_NOT_STARTED;
5206 return file->details->deep_counts_status;
5207 }
5208
5209 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))
5210 (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))
5211 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))
5212 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))
5213 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))
5214 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))
5215 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))
5216 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))
;
5217}
5218
5219void
5220baul_file_recompute_deep_counts (BaulFile *file)
5221{
5222 if (file->details->deep_counts_status != BAUL_REQUEST_IN_PROGRESS) {
5223 file->details->deep_counts_status = BAUL_REQUEST_NOT_STARTED;
5224 if (file->details->directory != NULL((void*)0)) {
5225 baul_directory_add_file_to_work_queue (file->details->directory, file);
5226 baul_directory_async_state_changed (file->details->directory);
5227 }
5228 }
5229}
5230
5231gboolean
5232baul_file_can_get_size (BaulFile *file)
5233{
5234 return file->details->size == -1;
5235}
5236
5237
5238/**
5239 * baul_file_get_size
5240 *
5241 * Get the file size.
5242 * @file: BaulFile representing the file in question.
5243 *
5244 * Returns: Size in bytes.
5245 *
5246 **/
5247goffset
5248baul_file_get_size (BaulFile *file)
5249{
5250 /* Before we have info on the file, we don't know the size. */
5251 if (file->details->size == -1)
5252 return 0;
5253 return file->details->size;
5254}
5255
5256/**
5257 * baul_file_get_size_on_disk
5258 *
5259 * Get the file size on disk (how many bytes is using on the filesystem).
5260 * e.g.: usually files with 1 byte will use a whole inode so it will return the
5261 * size of 1 inode. If the file is sparse the size on disk will be equal or less
5262 * than the size of the file.
5263 * @file: BaulFile representing the file in question.
5264 *
5265 * Returns: Size in bytes.
5266 *
5267 **/
5268goffset
5269baul_file_get_size_on_disk (BaulFile *file)
5270{
5271 /* Before we have info on the file, we don't know the size. */
5272 if (file->details->size_on_disk == -1)
5273 return 0;
5274 return file->details->size_on_disk;
5275}
5276
5277time_t
5278baul_file_get_mtime (BaulFile *file)
5279{
5280 return file->details->mtime;
5281}
5282
5283
5284static void
5285set_attributes_get_info_callback (GObject *source_object,
5286 GAsyncResult *res,
5287 gpointer callback_data)
5288{
5289 BaulFileOperation *op;
5290 GFileInfo *new_info;
5291 GError *error;
5292
5293 op = callback_data;
5294
5295 error = NULL((void*)0);
5296 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);
5297 if (new_info != NULL((void*)0)) {
5298 if (baul_file_update_info (op->file, new_info)) {
5299 baul_file_changed (op->file);
5300 }
5301 g_object_unref (new_info);
5302 }
5303 baul_file_operation_complete (op, NULL((void*)0), error);
5304 if (error) {
5305 g_error_free (error);
5306 }
5307}
5308
5309
5310static void
5311set_attributes_callback (GObject *source_object,
5312 GAsyncResult *result,
5313 gpointer callback_data)
5314{
5315 BaulFileOperation *op;
5316 GError *error;
5317 gboolean res;
5318
5319 op = callback_data;
5320
5321 error = NULL((void*)0);
5322 res = g_file_set_attributes_finish (G_FILE (source_object)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_file_get_type ()))))))
,
5323 result,
5324 NULL((void*)0),
5325 &error);
5326
5327 if (res) {
5328 g_file_query_info_async (G_FILE (source_object)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((source_object)), ((g_file_get_type ()))))))
,
5329 BAUL_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
5330 0,
5331 G_PRIORITY_DEFAULT0,
5332 op->cancellable,
5333 set_attributes_get_info_callback, op);
5334 } else {
5335 baul_file_operation_complete (op, NULL((void*)0), error);
5336 g_error_free (error);
5337 }
5338}
5339
5340void
5341baul_file_set_attributes (BaulFile *file,
5342 GFileInfo *attributes,
5343 BaulFileOperationCallback callback,
5344 gpointer callback_data)
5345{
5346 BaulFileOperation *op;
5347 GFile *location;
5348
5349 op = baul_file_operation_new (file, callback, callback_data);
5350
5351 location = baul_file_get_location (file);
5352 g_file_set_attributes_async (location,
5353 attributes,
5354 0,
5355 G_PRIORITY_DEFAULT0,
5356 op->cancellable,
5357 set_attributes_callback,
5358 op);
5359 g_object_unref (location);
5360}
5361
5362
5363/**
5364 * baul_file_can_get_permissions:
5365 *
5366 * Check whether the permissions for a file are determinable.
5367 * This might not be the case for files on non-UNIX file systems.
5368 *
5369 * @file: The file in question.
5370 *
5371 * Return value: TRUE if the permissions are valid.
5372 */
5373gboolean
5374baul_file_can_get_permissions (BaulFile *file)
5375{
5376 return file->details->has_permissions;
5377}
5378
5379/**
5380 * baul_file_can_set_permissions:
5381 *
5382 * Check whether the current user is allowed to change
5383 * the permissions of a file.
5384 *
5385 * @file: The file in question.
5386 *
5387 * Return value: TRUE if the current user can change the
5388 * permissions of @file, FALSE otherwise. It's always possible
5389 * that when you actually try to do it, you will fail.
5390 */
5391gboolean
5392baul_file_can_set_permissions (BaulFile *file)
5393{
5394 uid_t user_id;
5395
5396 if (file->details->uid != -1 &&
5397 baul_file_is_local (file)) {
5398 /* Check the user. */
5399 user_id = geteuid();
5400
5401 /* Owner is allowed to set permissions. */
5402 if (user_id == (uid_t) file->details->uid) {
5403 return TRUE(!(0));
5404 }
5405
5406 /* Root is also allowed to set permissions. */
5407 if (user_id == 0) {
5408 return TRUE(!(0));
5409 }
5410
5411 /* Nobody else is allowed. */
5412 return FALSE(0);
5413 }
5414
5415 /* pretend to have full chmod rights when no info is available, relevant when
5416 * the FS can't provide ownership info, for instance for FTP */
5417 return TRUE(!(0));
5418}
5419
5420guint
5421baul_file_get_permissions (BaulFile *file)
5422{
5423 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)
;
5424
5425 return file->details->permissions;
5426}
5427
5428/**
5429 * baul_file_set_permissions:
5430 *
5431 * Change a file's permissions. This should only be called if
5432 * baul_file_can_set_permissions returned TRUE.
5433 *
5434 * @file: BaulFile representing the file in question.
5435 * @new_permissions: New permissions value. This is the whole
5436 * set of permissions, not a delta.
5437 **/
5438void
5439baul_file_set_permissions (BaulFile *file,
5440 guint32 new_permissions,
5441 BaulFileOperationCallback callback,
5442 gpointer callback_data)
5443{
5444 GFileInfo *info;
5445
5446 if (!baul_file_can_set_permissions (file)) {
5447 GError *error;
5448
5449 /* Claim that something changed even if the permission change failed.
5450 * This makes it easier for some clients who see the "reverting"
5451 * to the old permissions as "changing back".
5452 */
5453 baul_file_changed (file);
5454 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5455 _("Not allowed to set permissions")gettext ("Not allowed to set permissions"));
5456 (* callback) (file, NULL((void*)0), error, callback_data);
5457 g_error_free (error);
5458 return;
5459 }
5460
5461 /* Test the permissions-haven't-changed case explicitly
5462 * because we don't want to send the file-changed signal if
5463 * nothing changed.
5464 */
5465 if (new_permissions == file->details->permissions) {
5466 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5467 return;
5468 }
5469
5470 // Start UNDO-REDO
5471 if (!baul_undostack_manager_is_undo_redo(baul_undostack_manager_instance())) {
5472 BaulUndoStackActionData* undo_redo_data = baul_undostack_manager_data_new (BAUL_UNDOSTACK_SETPERMISSIONS, 1);
5473 baul_undostack_manager_data_set_file_permissions(undo_redo_data, baul_file_get_uri(file), file->details->permissions, new_permissions);
5474 baul_undostack_manager_add_action (baul_undostack_manager_instance(),
5475 undo_redo_data);
5476 }
5477 // End UNDO-REDO
5478
5479 info = g_file_info_new ();
5480 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode", new_permissions);
5481 baul_file_set_attributes (file, info, callback, callback_data);
5482 g_object_unref (info);
5483}
5484
5485/**
5486 * baul_file_can_get_selinux_context:
5487 *
5488 * Check whether the selinux context for a file are determinable.
5489 * This might not be the case for files on non-UNIX file systems,
5490 * files without a context or systems that don't support selinux.
5491 *
5492 * @file: The file in question.
5493 *
5494 * Return value: TRUE if the permissions are valid.
5495 */
5496gboolean
5497baul_file_can_get_selinux_context (BaulFile *file)
5498{
5499 return file->details->selinux_context != NULL((void*)0);
5500}
5501
5502
5503/**
5504 * baul_file_get_selinux_context:
5505 *
5506 * Get a user-displayable string representing a file's selinux
5507 * context
5508 * @file: BaulFile representing the file in question.
5509 *
5510 * Returns: Newly allocated string ready to display to the user.
5511 *
5512 **/
5513char *
5514baul_file_get_selinux_context (BaulFile *file)
5515{
5516 char *translated;
5517 char *raw;
5518
5519 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)
;
5520
5521 if (!baul_file_can_get_selinux_context (file)) {
5522 return NULL((void*)0);
5523 }
5524
5525 raw = file->details->selinux_context;
5526
5527#ifdef HAVE_SELINUX1
5528 if (selinux_raw_to_trans_context (raw, &translated) == 0) {
5529 char *tmp;
5530 tmp = g_strdup (translated)g_strdup_inline (translated);
5531 freecon (translated);
5532 translated = tmp;
5533 }
5534 else
5535#endif
5536 {
5537 translated = g_strdup (raw)g_strdup_inline (raw);
5538 }
5539
5540 return translated;
5541}
5542
5543static char *
5544get_real_name (const char *name, const char *gecos)
5545{
5546 char *locale_string, *part_before_comma, *capitalized_login_name, *real_name;
5547
5548 if (gecos == NULL((void*)0)) {
5549 return NULL((void*)0);
5550 }
5551
5552 locale_string = eel_str_strip_substring_and_after (gecos, ",");
5553 if (!g_utf8_validate (locale_string, -1, NULL((void*)0))) {
5554 part_before_comma = g_locale_to_utf8 (locale_string, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5555 g_free (locale_string);
5556 } else {
5557 part_before_comma = locale_string;
5558 }
5559
5560 if (!g_utf8_validate (name, -1, NULL((void*)0))) {
5561 locale_string = g_locale_to_utf8 (name, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5562 } else {
5563 locale_string = g_strdup (name)g_strdup_inline (name);
5564 }
5565
5566 capitalized_login_name = eel_str_capitalize (locale_string);
5567 g_free (locale_string);
5568
5569 if (capitalized_login_name == NULL((void*)0)) {
5570 real_name = part_before_comma;
5571 } else {
5572 real_name = eel_str_replace_substring
5573 (part_before_comma, "&", capitalized_login_name);
5574 g_free (part_before_comma);
5575 }
5576
5577
5578 if (eel_str_is_empty (real_name)
5579 || eel_strcmp (name, real_name) == 0
5580 || eel_strcmp (capitalized_login_name, real_name) == 0) {
5581 g_free (real_name);
5582 real_name = NULL((void*)0);
5583 }
5584
5585 g_free (capitalized_login_name);
5586
5587 return real_name;
5588}
5589
5590static gboolean
5591get_group_id_from_group_name (const char *group_name, uid_t *gid)
5592{
5593 struct group *group;
5594
5595 g_assert (gid != NULL)do { if (gid != ((void*)0)) ; else g_assertion_message_expr (
((gchar*) 0), "baul-file.c", 5595, ((const char*) (__func__))
, "gid != NULL"); } while (0)
;
5596
5597 group = getgrnam (group_name);
5598
5599 if (group == NULL((void*)0)) {
5600 return FALSE(0);
5601 }
5602
5603 *gid = group->gr_gid;
5604
5605 return TRUE(!(0));
5606}
5607
5608static gboolean
5609get_ids_from_user_name (const char *user_name, uid_t *uid, uid_t *gid)
5610{
5611 struct passwd *password_info;
5612
5613 g_assert (uid != NULL || gid != NULL)do { if (uid != ((void*)0) || gid != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 5613, ((const char*) (__func__
)), "uid != NULL || gid != NULL"); } while (0)
;
5614
5615 password_info = getpwnam (user_name);
5616
5617 if (password_info == NULL((void*)0)) {
5618 return FALSE(0);
5619 }
5620
5621 if (uid != NULL((void*)0)) {
5622 *uid = password_info->pw_uid;
5623 }
5624
5625 if (gid != NULL((void*)0)) {
5626 *gid = password_info->pw_gid;
5627 }
5628
5629 return TRUE(!(0));
5630}
5631
5632static gboolean
5633get_user_id_from_user_name (const char *user_name, uid_t *id)
5634{
5635 return get_ids_from_user_name (user_name, id, NULL((void*)0));
5636}
5637
5638static gboolean
5639get_id_from_digit_string (const char *digit_string, uid_t *id)
5640{
5641 long scanned_id;
5642 char c;
5643
5644 g_assert (id != NULL)do { if (id != ((void*)0)) ; else g_assertion_message_expr ((
(gchar*) 0), "baul-file.c", 5644, ((const char*) (__func__)),
"id != NULL"); } while (0)
;
5645
5646 /* Only accept string if it has one integer with nothing
5647 * afterwards.
5648 */
5649 if (sscanf (digit_string, "%ld%c", &scanned_id, &c) != 1) {
5650 return FALSE(0);
5651 }
5652 *id = scanned_id;
5653 return TRUE(!(0));
5654}
5655
5656/**
5657 * baul_file_can_get_owner:
5658 *
5659 * Check whether the owner a file is determinable.
5660 * This might not be the case for files on non-UNIX file systems.
5661 *
5662 * @file: The file in question.
5663 *
5664 * Return value: TRUE if the owner is valid.
5665 */
5666gboolean
5667baul_file_can_get_owner (BaulFile *file)
5668{
5669 /* Before we have info on a file, the owner is unknown. */
5670 return file->details->uid != -1;
5671}
5672
5673/**
5674 * baul_file_get_owner_name:
5675 *
5676 * Get the user name of the file's owner. If the owner has no
5677 * name, returns the userid as a string. The caller is responsible
5678 * for g_free-ing this string.
5679 *
5680 * @file: The file in question.
5681 *
5682 * Return value: A newly-allocated string.
5683 */
5684char *
5685baul_file_get_owner_name (BaulFile *file)
5686{
5687 return baul_file_get_owner_as_string (file, FALSE(0));
5688}
5689
5690/**
5691 * baul_file_can_set_owner:
5692 *
5693 * Check whether the current user is allowed to change
5694 * the owner of a file.
5695 *
5696 * @file: The file in question.
5697 *
5698 * Return value: TRUE if the current user can change the
5699 * owner of @file, FALSE otherwise. It's always possible
5700 * that when you actually try to do it, you will fail.
5701 */
5702gboolean
5703baul_file_can_set_owner (BaulFile *file)
5704{
5705 /* Not allowed to set the owner if we can't
5706 * even read it. This can happen on non-UNIX file
5707 * systems.
5708 */
5709 if (!baul_file_can_get_owner (file)) {
5710 return FALSE(0);
5711 }
5712
5713 /* Only root is also allowed to set the owner. */
5714 return geteuid() == 0;
5715}
5716
5717/**
5718 * baul_file_set_owner:
5719 *
5720 * Set the owner of a file. This will only have any effect if
5721 * baul_file_can_set_owner returns TRUE.
5722 *
5723 * @file: The file in question.
5724 * @user_name_or_id: The user name to set the owner to.
5725 * If the string does not match any user name, and the
5726 * string is an integer, the owner will be set to the
5727 * userid represented by that integer.
5728 * @callback: Function called when asynch owner change succeeds or fails.
5729 * @callback_data: Parameter passed back with callback function.
5730 */
5731void
5732baul_file_set_owner (BaulFile *file,
5733 const char *user_name_or_id,
5734 BaulFileOperationCallback callback,
5735 gpointer callback_data)
5736{
5737 GError *error;
5738 GFileInfo *info;
5739 uid_t new_id;
5740
5741 if (!baul_file_can_set_owner (file)) {
5742 /* Claim that something changed even if the permission
5743 * change failed. This makes it easier for some
5744 * clients who see the "reverting" to the old owner as
5745 * "changing back".
5746 */
5747 baul_file_changed (file);
5748 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5749 _("Not allowed to set owner")gettext ("Not allowed to set owner"));
5750 (* callback) (file, NULL((void*)0), error, callback_data);
5751 g_error_free (error);
5752 return;
5753 }
5754
5755 /* If no match treating user_name_or_id as name, try treating
5756 * it as id.
5757 */
5758 if (!get_user_id_from_user_name (user_name_or_id, &new_id)
5759 && !get_id_from_digit_string (user_name_or_id, &new_id)) {
5760 /* Claim that something changed even if the permission
5761 * change failed. This makes it easier for some
5762 * clients who see the "reverting" to the old owner as
5763 * "changing back".
5764 */
5765 baul_file_changed (file);
5766 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
5767 _("Specified owner '%s' doesn't exist")gettext ("Specified owner '%s' doesn't exist"), user_name_or_id);
5768 (* callback) (file, NULL((void*)0), error, callback_data);
5769 g_error_free (error);
5770 return;
5771 }
5772
5773 /* Test the owner-hasn't-changed case explicitly because we
5774 * don't want to send the file-changed signal if nothing
5775 * changed.
5776 */
5777 if (new_id == (uid_t) file->details->uid) {
5778 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5779 return;
5780 }
5781
5782 // Start UNDO-REDO
5783 if (!baul_undostack_manager_is_undo_redo(baul_undostack_manager_instance())) {
5784 char* current_owner = baul_file_get_owner_as_string (file, FALSE(0));
5785 BaulUndoStackActionData* undo_redo_data = baul_undostack_manager_data_new (BAUL_UNDOSTACK_CHANGEOWNER, 1);
5786 baul_undostack_manager_data_set_owner_change_information(undo_redo_data, baul_file_get_uri(file), current_owner, user_name_or_id);
5787 baul_undostack_manager_add_action (baul_undostack_manager_instance(),
5788 undo_redo_data);
5789 g_free(current_owner);
5790 }
5791 // End UNDO-REDO
5792
5793 info = g_file_info_new ();
5794 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid", new_id);
5795 baul_file_set_attributes (file, info, callback, callback_data);
5796 g_object_unref (info);
5797}
5798
5799/**
5800 * baul_get_user_names:
5801 *
5802 * Get a list of user names. For users with a different associated
5803 * "real name", the real name follows the standard user name, separated
5804 * by a carriage return. The caller is responsible for freeing this list
5805 * and its contents.
5806 */
5807GList *
5808baul_get_user_names (void)
5809{
5810 GList *list;
5811 char *name;
5812 struct passwd *user;
5813
5814 list = NULL((void*)0);
5815
5816 setpwent ();
5817
5818 while ((user = getpwent ()) != NULL((void*)0)) {
5819 char *real_name;
5820
5821 real_name = get_real_name (user->pw_name, user->pw_gecos);
5822 if (real_name != NULL((void*)0)) {
5823 name = g_strconcat (user->pw_name, "\n", real_name, NULL((void*)0));
5824 } else {
5825 name = g_strdup (user->pw_name)g_strdup_inline (user->pw_name);
5826 }
5827 g_free (real_name);
5828 list = g_list_prepend (list, name);
5829 }
5830
5831 endpwent ();
5832
5833 return eel_g_str_list_alphabetize (list);
5834}
5835
5836/**
5837 * baul_file_can_get_group:
5838 *
5839 * Check whether the group a file is determinable.
5840 * This might not be the case for files on non-UNIX file systems.
5841 *
5842 * @file: The file in question.
5843 *
5844 * Return value: TRUE if the group is valid.
5845 */
5846gboolean
5847baul_file_can_get_group (BaulFile *file)
5848{
5849 /* Before we have info on a file, the group is unknown. */
5850 return file->details->gid != -1;
5851}
5852
5853/**
5854 * baul_file_get_group_name:
5855 *
5856 * Get the name of the file's group. If the group has no
5857 * name, returns the groupid as a string. The caller is responsible
5858 * for g_free-ing this string.
5859 *
5860 * @file: The file in question.
5861 *
5862 * Return value: A newly-allocated string.
5863 **/
5864char *
5865baul_file_get_group_name (BaulFile *file)
5866{
5867 return g_strdup (file->details->group)g_strdup_inline (file->details->group);
5868}
5869
5870/**
5871 * baul_file_can_set_group:
5872 *
5873 * Check whether the current user is allowed to change
5874 * the group of a file.
5875 *
5876 * @file: The file in question.
5877 *
5878 * Return value: TRUE if the current user can change the
5879 * group of @file, FALSE otherwise. It's always possible
5880 * that when you actually try to do it, you will fail.
5881 */
5882gboolean
5883baul_file_can_set_group (BaulFile *file)
5884{
5885 uid_t user_id;
5886
5887 /* Not allowed to set the permissions if we can't
5888 * even read them. This can happen on non-UNIX file
5889 * systems.
5890 */
5891 if (!baul_file_can_get_group (file)) {
5892 return FALSE(0);
5893 }
5894
5895 /* Check the user. */
5896 user_id = geteuid();
5897
5898 /* Owner is allowed to set group (with restrictions). */
5899 if (user_id == (uid_t) file->details->uid) {
5900 return TRUE(!(0));
5901 }
5902
5903 /* Root is also allowed to set group. */
5904 if (user_id == 0) {
5905 return TRUE(!(0));
5906 }
5907
5908 /* Nobody else is allowed. */
5909 return FALSE(0);
5910}
5911
5912/* Get a list of group names, filtered to only the ones
5913 * that contain the given username. If the username is
5914 * NULL, returns a list of all group names.
5915 */
5916static GList *
5917baul_get_group_names_for_user (void)
5918{
5919 GList *list;
5920 int count, i;
5921 gid_t gid_list[NGROUPS_MAX65536 + 1];
5922 struct group *group = NULL((void*)0);
5923
5924
5925 list = NULL((void*)0);
5926
5927 count = getgroups (NGROUPS_MAX65536 + 1, gid_list);
5928 for (i = 0; i < count; i++) {
5929 group = getgrgid (gid_list[i]);
5930 if (group == NULL((void*)0))
5931 break;
5932
5933 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5934 }
5935
5936 return eel_g_str_list_alphabetize (list);
5937}
5938
5939/**
5940 * baul_get_group_names:
5941 *
5942 * Get a list of all group names.
5943 */
5944GList *
5945baul_get_all_group_names (void)
5946{
5947 GList *list;
5948 struct group *group;
5949
5950 list = NULL((void*)0);
5951
5952 setgrent ();
5953
5954 while ((group = getgrent ()) != NULL((void*)0))
5955 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5956
5957 endgrent ();
5958
5959 return eel_g_str_list_alphabetize (list);
5960}
5961
5962/**
5963 * baul_file_get_settable_group_names:
5964 *
5965 * Get a list of all group names that the current user
5966 * can set the group of a specific file to.
5967 *
5968 * @file: The BaulFile in question.
5969 */
5970GList *
5971baul_file_get_settable_group_names (BaulFile *file)
5972{
5973 uid_t user_id;
5974 GList *result;
5975
5976 if (!baul_file_can_set_group (file)) {
5977 return NULL((void*)0);
5978 }
5979
5980 /* Check the user. */
5981 user_id = geteuid();
5982
5983 if (user_id == 0) {
5984 /* Root is allowed to set group to anything. */
5985 result = baul_get_all_group_names ();
5986 } else if (user_id == (uid_t) file->details->uid) {
5987 /* Owner is allowed to set group to any that owner is member of. */
5988 result = baul_get_group_names_for_user ();
5989 } else {
5990 g_warning ("unhandled case in baul_get_settable_group_names");
5991 result = NULL((void*)0);
5992 }
5993
5994 return result;
5995}
5996
5997/**
5998 * baul_file_set_group:
5999 *
6000 * Set the group of a file. This will only have any effect if
6001 * baul_file_can_set_group returns TRUE.
6002 *
6003 * @file: The file in question.
6004 * @group_name_or_id: The group name to set the owner to.
6005 * If the string does not match any group name, and the
6006 * string is an integer, the group will be set to the
6007 * group id represented by that integer.
6008 * @callback: Function called when asynch group change succeeds or fails.
6009 * @callback_data: Parameter passed back with callback function.
6010 */
6011void
6012baul_file_set_group (BaulFile *file,
6013 const char *group_name_or_id,
6014 BaulFileOperationCallback callback,
6015 gpointer callback_data)
6016{
6017 GError *error;
6018 GFileInfo *info;
6019 uid_t new_id;
6020
6021 if (!baul_file_can_set_group (file)) {
6022 /* Claim that something changed even if the group
6023 * change failed. This makes it easier for some
6024 * clients who see the "reverting" to the old group as
6025 * "changing back".
6026 */
6027 baul_file_changed (file);
6028 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
6029 _("Not allowed to set group")gettext ("Not allowed to set group"));
6030 (* callback) (file, NULL((void*)0), error, callback_data);
6031 g_error_free (error);
6032 return;
6033 }
6034
6035 /* If no match treating group_name_or_id as name, try treating
6036 * it as id.
6037 */
6038 if (!get_group_id_from_group_name (group_name_or_id, &new_id)
6039 && !get_id_from_digit_string (group_name_or_id, &new_id)) {
6040 /* Claim that something changed even if the group
6041 * change failed. This makes it easier for some
6042 * clients who see the "reverting" to the old group as
6043 * "changing back".
6044 */
6045 baul_file_changed (file);
6046 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
6047 _("Specified group '%s' doesn't exist")gettext ("Specified group '%s' doesn't exist"), group_name_or_id);
6048 (* callback) (file, NULL((void*)0), error, callback_data);
6049 g_error_free (error);
6050 return;
6051 }
6052
6053 if (new_id == (gid_t) file->details->gid) {
6054 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
6055 return;
6056 }
6057
6058 // Start UNDO-REDO
6059 if (!baul_undostack_manager_is_undo_redo(baul_undostack_manager_instance())) {
6060 char* current_group = baul_file_get_group_name (file);
6061 BaulUndoStackActionData* undo_redo_data = baul_undostack_manager_data_new (BAUL_UNDOSTACK_CHANGEGROUP, 1);
6062 baul_undostack_manager_data_set_group_change_information(undo_redo_data, baul_file_get_uri(file), current_group, group_name_or_id);
6063 baul_undostack_manager_add_action (baul_undostack_manager_instance(),
6064 undo_redo_data);
6065 g_free(current_group);
6066 }
6067 // End UNDO-REDO
6068
6069 info = g_file_info_new ();
6070 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid", new_id);
6071 baul_file_set_attributes (file, info, callback, callback_data);
6072 g_object_unref (info);
6073}
6074
6075/**
6076 * baul_file_get_octal_permissions_as_string:
6077 *
6078 * Get a user-displayable string representing a file's permissions
6079 * as an octal number. The caller
6080 * is responsible for g_free-ing this string.
6081 * @file: BaulFile representing the file in question.
6082 *
6083 * Returns: Newly allocated string ready to display to the user.
6084 *
6085 **/
6086static char *
6087baul_file_get_octal_permissions_as_string (BaulFile *file)
6088{
6089 guint32 permissions;
6090
6091 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", 6091,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
6092
6093 if (!baul_file_can_get_permissions (file)) {
6094 return NULL((void*)0);
6095 }
6096
6097 permissions = file->details->permissions;
6098 return g_strdup_printf ("%03o", permissions);
6099}
6100
6101/**
6102 * baul_file_get_permissions_as_string:
6103 *
6104 * Get a user-displayable string representing a file's permissions. The caller
6105 * is responsible for g_free-ing this string.
6106 * @file: BaulFile representing the file in question.
6107 *
6108 * Returns: Newly allocated string ready to display to the user.
6109 *
6110 **/
6111static char *
6112baul_file_get_permissions_as_string (BaulFile *file)
6113{
6114 guint32 permissions;
6115 gboolean is_directory;
6116 gboolean is_link;
6117 gboolean suid, sgid, sticky;
6118
6119 if (!baul_file_can_get_permissions (file)) {
6120 return NULL((void*)0);
6121 }
6122
6123 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", 6123,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
6124
6125 permissions = file->details->permissions;
6126 is_directory = baul_file_is_directory (file);
6127 is_link = baul_file_is_symbolic_link (file);
6128
6129 /* We use ls conventions for displaying these three obscure flags */
6130 suid = permissions & S_ISUID04000;
6131 sgid = permissions & S_ISGID02000;
6132 sticky = permissions & S_ISVTX01000;
6133
6134 return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
6135 is_link ? 'l' : is_directory ? 'd' : '-',
6136 permissions & S_IRUSR0400 ? 'r' : '-',
6137 permissions & S_IWUSR0200 ? 'w' : '-',
6138 permissions & S_IXUSR0100
6139 ? (suid ? 's' : 'x')
6140 : (suid ? 'S' : '-'),
6141 permissions & S_IRGRP(0400 >> 3) ? 'r' : '-',
6142 permissions & S_IWGRP(0200 >> 3) ? 'w' : '-',
6143 permissions & S_IXGRP(0100 >> 3)
6144 ? (sgid ? 's' : 'x')
6145 : (sgid ? 'S' : '-'),
6146 permissions & S_IROTH((0400 >> 3) >> 3) ? 'r' : '-',
6147 permissions & S_IWOTH((0200 >> 3) >> 3) ? 'w' : '-',
6148 permissions & S_IXOTH((0100 >> 3) >> 3)
6149 ? (sticky ? 't' : 'x')
6150 : (sticky ? 'T' : '-'));
6151}
6152
6153/**
6154 * baul_file_get_owner_as_string:
6155 *
6156 * Get a user-displayable string representing a file's owner. The caller
6157 * is responsible for g_free-ing this string.
6158 * @file: BaulFile representing the file in question.
6159 * @include_real_name: Whether or not to append the real name (if any)
6160 * for this user after the user name.
6161 *
6162 * Returns: Newly allocated string ready to display to the user.
6163 *
6164 **/
6165static char *
6166baul_file_get_owner_as_string (BaulFile *file, gboolean include_real_name)
6167{
6168 char *user_name;
6169
6170 /* Before we have info on a file, the owner is unknown. */
6171 if (file->details->owner == NULL((void*)0) &&
6172 file->details->owner_real == NULL((void*)0)) {
6173 return NULL((void*)0);
6174 }
6175
6176 if (file->details->owner_real == NULL((void*)0)) {
6177 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6178 } else if (file->details->owner == NULL((void*)0)) {
6179 user_name = g_strdup (file->details->owner_real)g_strdup_inline (file->details->owner_real);
6180 } else if (include_real_name &&
6181 strcmp (file->details->owner, file->details->owner_real) != 0) {
6182 user_name = g_strdup_printf ("%s - %s",
6183 file->details->owner,
6184 file->details->owner_real);
6185 } else {
6186 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6187 }
6188
6189 return user_name;
6190}
6191
6192static char *
6193format_item_count_for_display (guint item_count,
6194 gboolean includes_directories,
6195 gboolean includes_files)
6196{
6197 g_assert (includes_directories || includes_files)do { if (includes_directories || includes_files) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 6197, ((const char*) (__func__
)), "includes_directories || includes_files"); } while (0)
;
6198
6199 return g_strdup_printf (includes_directories
6200 ? (includes_files
6201 ? ngettext ("%'u item", "%'u items", item_count)
6202 : ngettext ("%'u folder", "%'u folders", item_count))
6203 : ngettext ("%'u file", "%'u files", item_count), item_count);
6204}
6205
6206/**
6207 * baul_file_get_size_as_string:
6208 *
6209 * Get a user-displayable string representing a file size. The caller
6210 * is responsible for g_free-ing this string. The string is an item
6211 * count for directories.
6212 * @file: BaulFile representing the file in question.
6213 * @size_on_disk: If TRUE will return the size on disk. If FALSE return file size.
6214 *
6215 * Returns: Newly allocated string ready to display to the user.
6216 *
6217 **/
6218static char *
6219baul_file_get_size_as_string (BaulFile *file,
6220 gboolean size_on_disk)
6221{
6222 guint item_count;
6223 gboolean count_unreadable;
6224 goffset size;
6225
6226 if (file == NULL((void*)0)) {
6227 return NULL((void*)0);
6228 }
6229
6230 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", 6230,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
6231
6232 if (baul_file_is_directory (file)) {
6233 if (!baul_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6234 return NULL((void*)0);
6235 }
6236 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6237 }
6238
6239 if (size_on_disk) {
6240 size = file->details->size_on_disk;
6241 } else {
6242 size = file->details->size;
6243 }
6244
6245 if (size == -1) {
6246 return NULL((void*)0);
6247 }
6248
6249 if (g_settings_get_boolean (baul_preferences, BAUL_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6250 return g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6251 else
6252 return g_format_size (size);
6253}
6254
6255/**
6256 * baul_file_get_size_as_string_with_real_size:
6257 *
6258 * Get a user-displayable string representing a file size. The caller
6259 * is responsible for g_free-ing this string. The string is an item
6260 * count for directories.
6261 * This function adds the real size in the string.
6262 * @file: BaulFile representing the file in question.
6263 *
6264 * Returns: Newly allocated string ready to display to the user.
6265 *
6266 **/
6267static char *
6268baul_file_get_size_as_string_with_real_size (BaulFile *file,
6269 gboolean size_on_disk)
6270{
6271 guint item_count;
6272 gboolean count_unreadable;
6273 goffset size;
6274 char * formatted;
6275 char * formatted_plus_real;
6276 char * real_size;
6277
6278 if (file == NULL((void*)0)) {
6279 return NULL((void*)0);
6280 }
6281
6282 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", 6282,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
6283
6284 if (baul_file_is_directory (file)) {
6285 if (!baul_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6286 return NULL((void*)0);
6287 }
6288 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6289 }
6290
6291 if (size_on_disk) {
6292 size = file->details->size_on_disk;
6293 } else {
6294 size = file->details->size;
6295 }
6296
6297 if (size == -1) {
6298 return NULL((void*)0);
6299 }
6300
6301 if (g_settings_get_boolean (baul_preferences, BAUL_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6302 formatted = g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6303 else
6304 formatted = g_format_size(size);
6305
6306 /* Do this in a separate stage so that we don't have to put G_GUINT64_FORMAT in the translated string */
6307 real_size = g_strdup_printf (_("%"G_GUINT64_FORMAT)gettext ("%""lu"), (guint64) size);
6308 formatted_plus_real = g_strdup_printf (_("%s (%s bytes)")gettext ("%s (%s bytes)"), formatted, real_size);
6309 g_free (real_size);
6310 g_free (formatted);
6311 return formatted_plus_real;
6312}
6313
6314static char *
6315baul_file_get_deep_count_as_string_internal (BaulFile *file,
6316 gboolean report_size,
6317 gboolean report_size_on_disk,
6318 gboolean report_directory_count,
6319 gboolean report_file_count)
6320{
6321 BaulRequestStatus status;
6322 guint directory_count;
6323 guint file_count;
6324 guint unreadable_count;
6325 guint total_count;
6326 goffset total_size;
6327 goffset total_size_on_disk;
6328
6329 /* Can't ask for more than one of those: size, size on disk or (directory and/or file count) */
6330 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", 6330,
((const char*) (__func__)), "!(report_size && report_size_on_disk)"
); } while (0)
;
6331 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"
, 6331, ((const char*) (__func__)), "!(report_size && (report_directory_count || report_file_count))"
); } while (0)
;
6332 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", 6332, ((const char*) (__func__)), "!(report_size_on_disk && (report_directory_count || report_file_count))"
); } while (0)
;
6333
6334 /* Must ask for something */
6335 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", 6335, ((const char*) (__func__)), "report_size || report_size_on_disk || report_directory_count || report_file_count"
); } while (0)
;
6336
6337 if (file == NULL((void*)0)) {
6338 return NULL((void*)0);
6339 }
6340
6341 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", 6341,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
6342 g_assert (baul_file_is_directory (file))do { if (baul_file_is_directory (file)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 6342, ((const char*) (__func__
)), "baul_file_is_directory (file)"); } while (0)
;
6343
6344 status = baul_file_get_deep_counts (file,
6345 &directory_count,
6346 &file_count,
6347 &unreadable_count,
6348 &total_size,
6349 &total_size_on_disk,
6350 FALSE(0));
6351
6352 /* Check whether any info is available. */
6353 if (status == BAUL_REQUEST_NOT_STARTED) {
6354 return NULL((void*)0);
6355 }
6356
6357 total_count = file_count + directory_count;
6358
6359 if (total_count == 0) {
6360 switch (status) {
6361 case BAUL_REQUEST_IN_PROGRESS:
6362 /* Don't return confident "zero" until we're finished looking,
6363 * because of next case.
6364 */
6365 return NULL((void*)0);
6366 case BAUL_REQUEST_DONE:
6367 /* Don't return "zero" if we there were contents but we couldn't read them. */
6368 if (unreadable_count != 0) {
6369 return NULL((void*)0);
6370 }
6371 default: break;
6372 }
6373 }
6374
6375 /* Note that we don't distinguish the "everything was readable" case
6376 * from the "some things but not everything was readable" case here.
6377 * Callers can distinguish them using baul_file_get_deep_counts
6378 * directly if desired.
6379 */
6380 if (report_size)
6381 {
6382 if (g_settings_get_boolean (baul_preferences, BAUL_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6383 return g_format_size_full (total_size, G_FORMAT_SIZE_IEC_UNITS);
6384 else
6385 return g_format_size(total_size);
6386 }
6387
6388 if (report_size_on_disk)
6389 {
6390 if (g_settings_get_boolean (baul_preferences, BAUL_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6391 return g_format_size_full (total_size_on_disk, G_FORMAT_SIZE_IEC_UNITS);
6392 else
6393 return g_format_size (total_size_on_disk);
6394 }
6395
6396 return format_item_count_for_display (report_directory_count
6397 ? (report_file_count ? total_count : directory_count)
6398 : file_count,
6399 report_directory_count, report_file_count);
6400}
6401
6402/**
6403 * baul_file_get_deep_size_as_string:
6404 *
6405 * Get a user-displayable string representing the size of all contained
6406 * items (only makes sense for directories). The caller
6407 * is responsible for g_free-ing this string.
6408 * @file: BaulFile representing the file in question.
6409 * @size_on_disk: if TRUE will return the size on disk, else return size of file.
6410 *
6411 * Returns: Newly allocated string ready to display to the user.
6412 *
6413 **/
6414static char *
6415baul_file_get_deep_size_as_string (BaulFile *file, gboolean size_on_disk)
6416{
6417 if (size_on_disk) {
6418 return baul_file_get_deep_count_as_string_internal (file, FALSE(0), TRUE(!(0)), FALSE(0), FALSE(0));
6419 } else {
6420 return baul_file_get_deep_count_as_string_internal (file, TRUE(!(0)), FALSE(0), FALSE(0), FALSE(0));
6421 }
6422}
6423
6424/**
6425 * baul_file_get_deep_total_count_as_string:
6426 *
6427 * Get a user-displayable string representing the count of all contained
6428 * items (only makes sense for directories). The caller
6429 * is responsible for g_free-ing this string.
6430 * @file: BaulFile representing the file in question.
6431 *
6432 * Returns: Newly allocated string ready to display to the user.
6433 *
6434 **/
6435static char *
6436baul_file_get_deep_total_count_as_string (BaulFile *file)
6437{
6438 return baul_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), TRUE(!(0)));
6439}
6440
6441/**
6442 * baul_file_get_deep_file_count_as_string:
6443 *
6444 * Get a user-displayable string representing the count of all contained
6445 * items, not including directories. It only makes sense to call this
6446 * function on a directory. The caller
6447 * is responsible for g_free-ing this string.
6448 * @file: BaulFile representing the file in question.
6449 *
6450 * Returns: Newly allocated string ready to display to the user.
6451 *
6452 **/
6453static char *
6454baul_file_get_deep_file_count_as_string (BaulFile *file)
6455{
6456 return baul_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), FALSE(0), TRUE(!(0)));
6457}
6458
6459/**
6460 * baul_file_get_deep_directory_count_as_string:
6461 *
6462 * Get a user-displayable string representing the count of all contained
6463 * directories. It only makes sense to call this
6464 * function on a directory. The caller
6465 * is responsible for g_free-ing this string.
6466 * @file: BaulFile representing the file in question.
6467 *
6468 * Returns: Newly allocated string ready to display to the user.
6469 *
6470 **/
6471static char *
6472baul_file_get_deep_directory_count_as_string (BaulFile *file)
6473{
6474 return baul_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), FALSE(0));
6475}
6476
6477/**
6478 * baul_file_get_string_attribute:
6479 *
6480 * Get a user-displayable string from a named attribute. Use g_free to
6481 * free this string. If the value is unknown, returns NULL. You can call
6482 * baul_file_get_string_attribute_with_default if you want a non-NULL
6483 * default.
6484 *
6485 * @file: BaulFile representing the file in question.
6486 * @attribute_name: The name of the desired attribute. The currently supported
6487 * set includes "name", "type", "mime_type", "size", "size_on_disk", "deep_size", "deep_size_on_disk",
6488 * "deep_directory_count", "deep_file_count", "deep_total_count", "date_modified", "date_changed",
6489 * "date_accessed", "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where",
6490 * "link_target", "volume", "free_space", "selinux_context", "trashed_on", "trashed_orig_path"
6491 *
6492 * Returns: Newly allocated string ready to display to the user, or NULL
6493 * if the value is unknown or @attribute_name is not supported.
6494 *
6495 **/
6496char *
6497baul_file_get_string_attribute_q (BaulFile *file, GQuark attribute_q)
6498{
6499 char *extension_attribute;
6500
6501 if (attribute_q == attribute_name_q) {
6502 return baul_file_get_display_name (file);
6503 }
6504 if (attribute_q == attribute_type_q) {
6505 return baul_file_get_type_as_string (file);
6506 }
6507 if (attribute_q == attribute_mime_type_q) {
6508 return baul_file_get_mime_type (file);
6509 }
6510 if (attribute_q == attribute_size_q) {
6511 return baul_file_get_size_as_string (file, FALSE(0));
6512 }
6513 if (attribute_q == attribute_size_on_disk_q) {
6514 return baul_file_get_size_as_string (file, TRUE(!(0)));
6515 }
6516 if (attribute_q == attribute_size_detail_q) {
6517 return baul_file_get_size_as_string_with_real_size (file, FALSE(0));
6518 }
6519 if (attribute_q == attribute_size_on_disk_detail_q) {
6520 return baul_file_get_size_as_string_with_real_size (file, TRUE(!(0)));
6521 }
6522 if (attribute_q == attribute_deep_size_q) {
6523 return baul_file_get_deep_size_as_string (file, FALSE(0));
6524 }
6525 if (attribute_q == attribute_deep_size_on_disk_q) {
6526 return baul_file_get_deep_size_as_string (file, TRUE(!(0)));
6527 }
6528 if (attribute_q == attribute_deep_file_count_q) {
6529 return baul_file_get_deep_file_count_as_string (file);
6530 }
6531 if (attribute_q == attribute_deep_directory_count_q) {
6532 return baul_file_get_deep_directory_count_as_string (file);
6533 }
6534 if (attribute_q == attribute_deep_total_count_q) {
6535 return baul_file_get_deep_total_count_as_string (file);
6536 }
6537 if (attribute_q == attribute_trash_orig_path_q) {
6538 return baul_file_get_trash_original_file_parent_as_string (file);
6539 }
6540 if (attribute_q == attribute_date_modified_q) {
6541 return baul_file_get_date_as_string (file,
6542 BAUL_DATE_TYPE_MODIFIED);
6543 }
6544 if (attribute_q == attribute_date_changed_q) {
6545 return baul_file_get_date_as_string (file,
6546 BAUL_DATE_TYPE_CHANGED);
6547 }
6548 if (attribute_q == attribute_date_accessed_q) {
6549 return baul_file_get_date_as_string (file,
6550 BAUL_DATE_TYPE_ACCESSED);
6551 }
6552 if (attribute_q == attribute_trashed_on_q) {
6553 return baul_file_get_date_as_string (file,
6554 BAUL_DATE_TYPE_TRASHED);
6555 }
6556 if (attribute_q == attribute_date_permissions_q) {
6557 return baul_file_get_date_as_string (file,
6558 BAUL_DATE_TYPE_PERMISSIONS_CHANGED);
6559 }
6560 if (attribute_q == attribute_extension_q) {
6561 return baul_file_get_extension_as_string (file);
6562 }
6563 if (attribute_q == attribute_permissions_q) {
6564 return baul_file_get_permissions_as_string (file);
6565 }
6566 if (attribute_q == attribute_selinux_context_q) {
6567 return baul_file_get_selinux_context (file);
6568 }
6569 if (attribute_q == attribute_octal_permissions_q) {
6570 return baul_file_get_octal_permissions_as_string (file);
6571 }
6572 if (attribute_q == attribute_owner_q) {
6573 return baul_file_get_owner_as_string (file, TRUE(!(0)));
6574 }
6575 if (attribute_q == attribute_group_q) {
6576 return baul_file_get_group_name (file);
6577 }
6578 if (attribute_q == attribute_uri_q) {
6579 return baul_file_get_uri (file);
6580 }
6581 if (attribute_q == attribute_where_q) {
6582 return baul_file_get_where_string (file);
6583 }
6584 if (attribute_q == attribute_link_target_q) {
6585 return baul_file_get_symbolic_link_target_path (file);
6586 }
6587 if (attribute_q == attribute_volume_q) {
6588 return baul_file_get_volume_name (file);
6589 }
6590 if (attribute_q == attribute_free_space_q) {
6591 return baul_file_get_volume_free_space (file);
6592 }
6593
6594 extension_attribute = NULL((void*)0);
6595
6596 if (file->details->pending_extension_attributes) {
6597 extension_attribute = g_hash_table_lookup (file->details->pending_extension_attributes,
6598 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6599 }
6600
6601 if (extension_attribute == NULL((void*)0) && file->details->extension_attributes) {
6602 extension_attribute = g_hash_table_lookup (file->details->extension_attributes,
6603 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6604 }
6605
6606 return g_strdup (extension_attribute)g_strdup_inline (extension_attribute);
6607}
6608
6609char *
6610baul_file_get_string_attribute (BaulFile *file, const char *attribute_name)
6611{
6612 return baul_file_get_string_attribute_q (file, g_quark_from_string (attribute_name));
6613}
6614
6615
6616/**
6617 * baul_file_get_string_attribute_with_default:
6618 *
6619 * Get a user-displayable string from a named attribute. Use g_free to
6620 * free this string. If the value is unknown, returns a string representing
6621 * the unknown value, which varies with attribute. You can call
6622 * baul_file_get_string_attribute if you want NULL instead of a default
6623 * result.
6624 *
6625 * @file: BaulFile representing the file in question.
6626 * @attribute_name: The name of the desired attribute. See the description of
6627 * baul_file_get_string for the set of available attributes.
6628 *
6629 * Returns: Newly allocated string ready to display to the user, or a string
6630 * such as "unknown" if the value is unknown or @attribute_name is not supported.
6631 *
6632 **/
6633char *
6634baul_file_get_string_attribute_with_default_q (BaulFile *file, GQuark attribute_q)
6635{
6636 char *result;
6637 guint item_count;
6638 gboolean count_unreadable;
6639 BaulRequestStatus status;
6640
6641 result = baul_file_get_string_attribute_q (file, attribute_q);
6642 if (result != NULL((void*)0)) {
6643 return result;
6644 }
6645
6646 /* Supply default values for the ones we know about. */
6647 /* FIXME bugzilla.gnome.org 40646:
6648 * Use hash table and switch statement or function pointers for speed?
6649 */
6650 if (attribute_q == attribute_size_q) {
6651 if (!baul_file_should_show_directory_item_count (file)) {
6652 return g_strdup ("--")g_strdup_inline ("--");
6653 }
6654 count_unreadable = FALSE(0);
6655 if (baul_file_is_directory (file)) {
6656 baul_file_get_directory_item_count (file, &item_count, &count_unreadable);
6657 }
6658 return g_strdup (count_unreadable ? _("? items") : "...")g_strdup_inline (count_unreadable ? gettext ("? items") : "..."
)
;
6659 }
6660 if (attribute_q == attribute_deep_size_q) {
6661 status = baul_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6662 if (status == BAUL_REQUEST_DONE) {
6663 /* This means no contents at all were readable */
6664 return g_strdup (_("? bytes"))g_strdup_inline (gettext ("? bytes"));
6665 }
6666 return g_strdup ("...")g_strdup_inline ("...");
6667 }
6668 if (attribute_q == attribute_deep_size_on_disk_q) {
6669 status = baul_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6670 if (status == BAUL_REQUEST_DONE) {
6671 /* This means no contents at all were readable */
6672 return g_strdup (_("? bytes"))g_strdup_inline (gettext ("? bytes"));
6673 }
6674 return g_strdup ("...")g_strdup_inline ("...");
6675 }
6676 if (attribute_q == attribute_deep_file_count_q
6677 || attribute_q == attribute_deep_directory_count_q
6678 || attribute_q == attribute_deep_total_count_q) {
6679 status = baul_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6680 if (status == BAUL_REQUEST_DONE) {
6681 /* This means no contents at all were readable */
6682 return g_strdup (_("? items"))g_strdup_inline (gettext ("? items"));
6683 }
6684 return g_strdup ("...")g_strdup_inline ("...");
6685 }
6686 if (attribute_q == attribute_type_q) {
6687 return g_strdup (_("unknown type"))g_strdup_inline (gettext ("unknown type"));
6688 }
6689 if (attribute_q == attribute_mime_type_q) {
6690 return g_strdup (_("unknown MIME type"))g_strdup_inline (gettext ("unknown MIME type"));
6691 }
6692 if (attribute_q == attribute_trashed_on_q) {
6693 /* If n/a */
6694 return g_strdup ("")g_strdup_inline ("");
6695 }
6696 if (attribute_q == attribute_trash_orig_path_q) {
6697 /* If n/a */
6698 return g_strdup ("")g_strdup_inline ("");
6699 }
6700
6701 /* Fallback, use for both unknown attributes and attributes
6702 * for which we have no more appropriate default.
6703 */
6704 return g_strdup (_("unknown"))g_strdup_inline (gettext ("unknown"));
6705}
6706
6707char *
6708baul_file_get_string_attribute_with_default (BaulFile *file, const char *attribute_name)
6709{
6710 return baul_file_get_string_attribute_with_default_q (file, g_quark_from_string (attribute_name));
6711}
6712
6713gboolean
6714baul_file_is_date_sort_attribute_q (GQuark attribute_q)
6715{
6716 if (attribute_q == attribute_modification_date_q ||
6717 attribute_q == attribute_date_modified_q ||
6718 attribute_q == attribute_accessed_date_q ||
6719 attribute_q == attribute_date_accessed_q ||
6720 attribute_q == attribute_date_changed_q ||
6721 attribute_q == attribute_trashed_on_q ||
6722 attribute_q == attribute_date_permissions_q) {
6723 return TRUE(!(0));
6724 }
6725
6726 return FALSE(0);
6727}
6728
6729/**
6730 * get_description:
6731 *
6732 * Get a user-displayable string representing a file type. The caller
6733 * is responsible for g_free-ing this string.
6734 * @file: BaulFile representing the file in question.
6735 *
6736 * Returns: Newly allocated string ready to display to the user.
6737 *
6738 **/
6739static char *
6740get_description (BaulFile *file)
6741{
6742 const char *mime_type;
6743 char *description;
6744
6745 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", 6745,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
6746
6747 mime_type = file->details->mime_type;
6748 if (eel_str_is_empty (mime_type)) {
6749 return NULL((void*)0);
6750 }
6751
6752 if (g_content_type_is_unknown (mime_type) &&
6753 baul_file_is_executable (file)) {
6754 return g_strdup (_("program"))g_strdup_inline (gettext ("program"));
6755 }
6756
6757 description = g_content_type_get_description (mime_type);
6758 if (!eel_str_is_empty (description)) {
6759 return description;
6760 }
6761
6762 return g_strdup (mime_type)g_strdup_inline (mime_type);
6763}
6764
6765/* Takes ownership of string */
6766static char *
6767update_description_for_link (BaulFile *file, char *string)
6768{
6769 if (baul_file_is_symbolic_link (file)) {
6770 char *res;
6771
6772 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", 6772, ((const char*) (__func__
)), "!baul_file_is_broken_symbolic_link (file)"); } while (0)
;
6773 if (string == NULL((void*)0)) {
6774 return g_strdup (_("link"))g_strdup_inline (gettext ("link"));
6775 }
6776 /* Note to localizers: convert file type string for file
6777 * (e.g. "folder", "plain text") to file type for symbolic link
6778 * to that kind of file (e.g. "link to folder").
6779 */
6780 res = g_strdup_printf (_("Link to %s")gettext ("Link to %s"), string);
6781 g_free (string);
6782 return res;
6783 }
6784
6785 return string;
6786}
6787
6788static char *
6789baul_file_get_type_as_string (BaulFile *file)
6790{
6791 if (file == NULL((void*)0)) {
6792 return NULL((void*)0);
6793 }
6794
6795 if (baul_file_is_broken_symbolic_link (file)) {
6796 return g_strdup (_("link (broken)"))g_strdup_inline (gettext ("link (broken)"));
6797 }
6798
6799 return update_description_for_link (file, get_description (file));
6800}
6801
6802/**
6803 * baul_file_get_file_type
6804 *
6805 * Return this file's type.
6806 * @file: BaulFile representing the file in question.
6807 *
6808 * Returns: The type.
6809 *
6810 **/
6811GFileType
6812baul_file_get_file_type (BaulFile *file)
6813{
6814 if (file == NULL((void*)0)) {
6815 return G_FILE_TYPE_UNKNOWN;
6816 }
6817
6818 return file->details->type;
6819}
6820
6821/**
6822 * baul_file_get_mime_type
6823 *
6824 * Return this file's default mime type.
6825 * @file: BaulFile representing the file in question.
6826 *
6827 * Returns: The mime type.
6828 *
6829 **/
6830char *
6831baul_file_get_mime_type (BaulFile *file)
6832{
6833 if (file != NULL((void*)0)) {
6834 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)
;
6835 if (file->details->mime_type != NULL((void*)0)) {
6836 return g_strdup (file->details->mime_type)g_strdup_inline (file->details->mime_type);
6837 }
6838 }
6839 return g_strdup ("application/octet-stream")g_strdup_inline ("application/octet-stream");
6840}
6841
6842/**
6843 * baul_file_is_mime_type
6844 *
6845 * Check whether a file is of a particular MIME type, or inherited
6846 * from it.
6847 * @file: BaulFile representing the file in question.
6848 * @mime_type: The MIME-type string to test (e.g. "text/plain")
6849 *
6850 * Return value: TRUE if @mime_type exactly matches the
6851 * file's MIME type.
6852 *
6853 **/
6854gboolean
6855baul_file_is_mime_type (BaulFile *file, const char *mime_type)
6856{
6857 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)
;
6858 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)
;
6859
6860 if (file->details->mime_type == NULL((void*)0)) {
6861 return FALSE(0);
6862 }
6863 return g_content_type_is_a (file->details->mime_type,
6864 mime_type);
6865}
6866
6867gboolean
6868baul_file_is_launchable (BaulFile *file)
6869{
6870 gboolean type_can_be_executable;
6871
6872 type_can_be_executable = FALSE(0);
6873 if (file->details->mime_type != NULL((void*)0)) {
6874 type_can_be_executable =
6875 g_content_type_can_be_executable (file->details->mime_type);
6876 }
6877
6878 return type_can_be_executable &&
6879 baul_file_can_get_permissions (file) &&
6880 baul_file_can_execute (file) &&
6881 baul_file_is_executable (file) &&
6882 !baul_file_is_directory (file);
6883}
6884
6885
6886/**
6887 * baul_file_get_emblem_icons
6888 *
6889 * Return the list of names of emblems that this file should display,
6890 * in canonical order.
6891 * @file: BaulFile representing the file in question.
6892 *
6893 * Returns: A list of emblem names.
6894 *
6895 **/
6896GList *
6897baul_file_get_emblem_icons (BaulFile *file,
6898 char **exclude)
6899{
6900 GList *keywords, *l;
6901 GList *icons;
6902 char *icon_names[2];
6903 char *keyword;
6904 int i;
6905 GIcon *icon;
6906
6907 if (file == NULL((void*)0)) {
6908 return NULL((void*)0);
6909 }
6910
6911 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)
;
6912
6913 keywords = baul_file_get_keywords (file);
6914 keywords = prepend_automatic_keywords (file, keywords);
6915
6916 icons = NULL((void*)0);
6917 for (l = keywords; l != NULL((void*)0); l = l->next) {
6918 keyword = l->data;
6919
6920#ifdef TRASH_IS_FAST_ENOUGH
6921 if (strcmp (keyword, BAUL_FILE_EMBLEM_NAME_TRASH"trash") == 0) {
6922 char *uri;
6923 gboolean file_is_trash;
6924 /* Leave out the trash emblem for the trash itself, since
6925 * putting a trash emblem on a trash icon is gilding the
6926 * lily.
6927 */
6928 uri = baul_file_get_uri (file);
6929 file_is_trash = strcmp (uri, EEL_TRASH_URI"trash:") == 0;
6930 g_free (uri);
6931 if (file_is_trash) {
6932 continue;
6933 }
6934 }
6935#endif
6936 if (exclude) {
6937 for (i = 0; exclude[i] != NULL((void*)0); i++) {
6938 if (strcmp (exclude[i], keyword) == 0) {
6939 continue;
6940 }
6941 }
6942 }
6943
6944
6945 icon_names[0] = g_strconcat ("emblem-", keyword, NULL((void*)0));
6946 icon_names[1] = keyword;
6947 icon = g_themed_icon_new_from_names (icon_names, 2);
6948 g_free (icon_names[0]);
6949
6950 icons = g_list_prepend (icons, icon);
6951 }
6952
6953 g_list_free_full (keywords, g_free);
6954
6955 return icons;
6956}
6957
6958GList *
6959baul_file_get_emblem_pixbufs (BaulFile *file,
6960 int size,
6961 gboolean force_size,
6962 char **exclude)
6963{
6964 GList *icons, *l;
6965 GList *pixbufs;
6966 GdkPixbuf *pixbuf;
6967 GIcon *icon = NULL((void*)0);
6968 BaulIconInfo *icon_info = NULL((void*)0);
6969
6970 icons = baul_file_get_emblem_icons (file, exclude);
6971 pixbufs = NULL((void*)0);
6972
6973 for (l = icons; l != NULL((void*)0); l = l->next) {
6974 icon = l->data;
6975
6976 icon_info = baul_icon_info_lookup (icon, size, 1);
6977 if (force_size) {
6978 pixbuf = baul_icon_info_get_pixbuf_nodefault_at_size (icon_info, size);
6979 } else {
6980 pixbuf = baul_icon_info_get_pixbuf_nodefault (icon_info);
6981 }
6982
6983 if (pixbuf) {
6984 pixbufs = g_list_prepend (pixbufs, pixbuf);
6985 }
6986
6987
6988 g_object_unref (icon_info);
6989 g_object_unref (icon);
6990 }
6991 g_list_free (icons);
6992
6993 return g_list_reverse (pixbufs);
6994
6995
6996}
6997
6998static GList *
6999sort_keyword_list_and_remove_duplicates (GList *keywords)
7000{
7001 GList *p;
7002
7003 if (keywords != NULL((void*)0)) {
7004 GList *duplicate_link = NULL((void*)0);
7005
7006 keywords = eel_g_str_list_alphabetize (keywords);
7007
7008 p = keywords;
7009 while (p->next != NULL((void*)0)) {
7010 if (strcmp ((const char *) p->data, (const char *) p->next->data) == 0) {
7011 duplicate_link = p->next;
7012 keywords = g_list_remove_link (keywords, duplicate_link);
7013 g_list_free_full (duplicate_link, g_free);
7014 } else {
7015 p = p->next;
7016 }
7017 }
7018 }
7019
7020 return keywords;
7021}
7022
7023/**
7024 * baul_file_get_keywords
7025 *
7026 * Return this file's keywords.
7027 * @file: BaulFile representing the file in question.
7028 *
7029 * Returns: A list of keywords.
7030 *
7031 **/
7032GList *
7033baul_file_get_keywords (BaulFile *file)
7034{
7035 GList *keywords;
7036
7037 if (file == NULL((void*)0)) {
7038 return NULL((void*)0);
7039 }
7040
7041 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)
;
7042
7043 /* Put all the keywords into a list. */
7044 keywords = baul_file_get_metadata_list
7045 (file, BAUL_METADATA_KEY_EMBLEMS"emblems");
7046
7047 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7048 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->pending_extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7049
7050 return sort_keyword_list_and_remove_duplicates (keywords);
7051}
7052
7053/**
7054 * baul_file_set_keywords
7055 *
7056 * Change this file's keywords.
7057 * @file: BaulFile representing the file in question.
7058 * @keywords: New set of keywords (a GList of strings).
7059 *
7060 **/
7061void
7062baul_file_set_keywords (BaulFile *file, GList *keywords)
7063{
7064 GList *canonical_keywords;
7065
7066 /* Invalidate the emblem compare cache */
7067 g_free (file->details->compare_by_emblem_cache);
7068 file->details->compare_by_emblem_cache = NULL((void*)0);
7069
7070 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)
;
7071
7072 canonical_keywords = sort_keyword_list_and_remove_duplicates
7073 (g_list_copy (keywords));
7074 baul_file_set_metadata_list
7075 (file, BAUL_METADATA_KEY_EMBLEMS"emblems", canonical_keywords);
7076 g_list_free (canonical_keywords);
7077}
7078
7079/**
7080 * baul_file_is_symbolic_link
7081 *
7082 * Check if this file is a symbolic link.
7083 * @file: BaulFile representing the file in question.
7084 *
7085 * Returns: True if the file is a symbolic link.
7086 *
7087 **/
7088gboolean
7089baul_file_is_symbolic_link (BaulFile *file)
7090{
7091 return file->details->is_symlink;
7092}
7093
7094gboolean
7095baul_file_is_mountpoint (BaulFile *file)
7096{
7097 return file->details->is_mountpoint;
7098}
7099
7100GMount *
7101baul_file_get_mount (BaulFile *file)
7102{
7103 if (file->details->mount) {
7104 return g_object_ref (file->details->mount)((__typeof__ (file->details->mount)) (g_object_ref) (file
->details->mount))
;
7105 }
7106 return NULL((void*)0);
7107}
7108
7109static void
7110file_mount_unmounted (GMount *mount,
7111 gpointer data)
7112{
7113 BaulFile *file;
7114
7115 file = BAUL_FILE (data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), (baul_file_get_type())))))
;
7116
7117 baul_file_invalidate_attributes (file, BAUL_FILE_ATTRIBUTE_MOUNT);
7118}
7119
7120void
7121baul_file_set_mount (BaulFile *file,
7122 GMount *mount)
7123{
7124 if (file->details->mount) {
7125 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))
;
7126 g_object_unref (file->details->mount);
7127 file->details->mount = NULL((void*)0);
7128 }
7129
7130 if (mount) {
7131 file->details->mount = g_object_ref (mount)((__typeof__ (mount)) (g_object_ref) (mount));
7132 g_signal_connect (mount, "unmounted",g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
7133 G_CALLBACK (file_mount_unmounted), file)g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
;
7134 }
7135}
7136
7137/**
7138 * baul_file_is_broken_symbolic_link
7139 *
7140 * Check if this file is a symbolic link with a missing target.
7141 * @file: BaulFile representing the file in question.
7142 *
7143 * Returns: True if the file is a symbolic link with a missing target.
7144 *
7145 **/
7146gboolean
7147baul_file_is_broken_symbolic_link (BaulFile *file)
7148{
7149 if (file == NULL((void*)0)) {
7150 return FALSE(0);
7151 }
7152
7153 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)
;
7154
7155 /* Non-broken symbolic links return the target's type for get_file_type. */
7156 return baul_file_get_file_type (file) == G_FILE_TYPE_SYMBOLIC_LINK;
7157}
7158
7159static void
7160get_fs_free_cb (GObject *source_object,
7161 GAsyncResult *res,
7162 gpointer user_data)
7163{
7164 BaulDirectory *directory;
7165 guint64 free_space;
7166 GFileInfo *info;
7167
7168 directory = BAUL_DIRECTORY (user_data)((((BaulDirectory*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), (baul_directory_get_type())))))
;
7169
7170 free_space = (guint64)-1;
7171 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 ()))))))
,
7172 res, NULL((void*)0));
7173 if (info) {
7174 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free")) {
7175 free_space = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
7176 }
7177 g_object_unref (info);
7178 }
7179
7180 if (directory->details->free_space != free_space) {
7181 BaulFile *file;
7182
7183 directory->details->free_space = free_space;
7184 file = baul_directory_get_existing_corresponding_file (directory);
7185 if (file) {
7186 baul_file_emit_changed (file);
7187 baul_file_unref (file);
7188 }
7189 }
7190 baul_directory_unref (directory);
7191}
7192
7193/**
7194 * baul_file_get_volume_free_space
7195 * Get a nicely formatted char with free space on the file's volume
7196 * @file: BaulFile representing the file in question.
7197 *
7198 * Returns: newly-allocated copy of file size in a formatted string
7199 */
7200char *
7201baul_file_get_volume_free_space (BaulFile *file)
7202{
7203 BaulDirectory *directory;
7204 char *res;
7205 time_t now;
7206
7207 directory = baul_directory_get_for_file (file);
7208
7209 now = time (NULL((void*)0));
7210 /* Update first time and then every 2 seconds */
7211 if (directory->details->free_space_read == 0 ||
7212 (now - directory->details->free_space_read) > 2) {
7213 GFile *location;
7214
7215 directory->details->free_space_read = now;
7216 location = baul_file_get_location (file);
7217 g_file_query_filesystem_info_async (location,
7218 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free",
7219 0, NULL((void*)0),
7220 get_fs_free_cb,
7221 directory); /* Inherits ref */
7222 g_object_unref (location);
7223 } else {
7224 baul_directory_unref (directory);
7225 }
7226
7227
7228 res = NULL((void*)0);
7229
7230 if (directory->details->free_space != (guint64) -1)
7231 {
7232 if (g_settings_get_boolean (baul_preferences, BAUL_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
7233 res = g_format_size_full (directory->details->free_space, G_FORMAT_SIZE_IEC_UNITS);
7234 else
7235 res = g_format_size(directory->details->free_space);
7236 }
7237
7238 return res;
7239}
7240
7241/**
7242 * baul_file_get_volume_name
7243 * Get the path of the volume the file resides on
7244 * @file: BaulFile representing the file in question.
7245 *
7246 * Returns: newly-allocated copy of the volume name of the target file,
7247 * if the volume name isn't set, it returns the mount path of the volume
7248 */
7249char *
7250baul_file_get_volume_name (BaulFile *file)
7251{
7252 GFile *location;
7253 char *res;
7254 GMount *mount;
7255
7256 res = NULL((void*)0);
7257
7258 location = baul_file_get_location (file);
7259 mount = g_file_find_enclosing_mount (location, NULL((void*)0), NULL((void*)0));
7260 if (mount) {
7261 res = g_strdup (g_mount_get_name (mount))g_strdup_inline (g_mount_get_name (mount));
7262 g_object_unref (mount);
7263 }
7264 g_object_unref (location);
7265
7266 return res;
7267}
7268
7269/**
7270 * baul_file_get_symbolic_link_target_path
7271 *
7272 * Get the file path of the target of a symbolic link. It is an error
7273 * to call this function on a file that isn't a symbolic link.
7274 * @file: BaulFile representing the symbolic link in question.
7275 *
7276 * Returns: newly-allocated copy of the file path of the target of the symbolic link.
7277 */
7278char *
7279baul_file_get_symbolic_link_target_path (BaulFile *file)
7280{
7281 if (!baul_file_is_symbolic_link (file)) {
7282 g_warning ("File has symlink target, but is not marked as symlink");
7283 }
7284
7285 return g_strdup (file->details->symlink_name)g_strdup_inline (file->details->symlink_name);
7286}
7287
7288/**
7289 * baul_file_get_symbolic_link_target_uri
7290 *
7291 * Get the uri of the target of a symbolic link. It is an error
7292 * to call this function on a file that isn't a symbolic link.
7293 * @file: BaulFile representing the symbolic link in question.
7294 *
7295 * Returns: newly-allocated copy of the uri of the target of the symbolic link.
7296 */
7297char *
7298baul_file_get_symbolic_link_target_uri (BaulFile *file)
7299{
7300 if (!baul_file_is_symbolic_link (file)) {
7301 g_warning ("File has symlink target, but is not marked as symlink");
7302 }
7303
7304 if (file->details->symlink_name == NULL((void*)0)) {
7305 return NULL((void*)0);
7306 } else {
7307 GFile *location, *parent, *target;
7308 char *target_uri;
7309
7310 target = NULL((void*)0);
7311
7312 location = baul_file_get_location (file);
7313 parent = g_file_get_parent (location);
7314 g_object_unref (location);
7315 if (parent) {
7316 target = g_file_resolve_relative_path (parent, file->details->symlink_name);
7317 g_object_unref (parent);
7318 }
7319
7320 target_uri = NULL((void*)0);
7321 if (target) {
7322 target_uri = g_file_get_uri (target);
7323 g_object_unref (target);
7324 }
7325 return target_uri;
7326 }
7327}
7328
7329/**
7330 * baul_file_is_baul_link
7331 *
7332 * Check if this file is a "baul link", meaning a historical
7333 * baul xml link file or a desktop file.
7334 * @file: BaulFile representing the file in question.
7335 *
7336 * Returns: True if the file is a baul link.
7337 *
7338 **/
7339gboolean
7340baul_file_is_baul_link (BaulFile *file)
7341{
7342 if (file->details->mime_type == NULL((void*)0))
7343 {
7344 return FALSE(0);
7345 }
7346 return g_content_type_equals (file->details->mime_type,
7347 "application/x-desktop");
7348}
7349
7350/**
7351 * baul_file_is_directory
7352 *
7353 * Check if this file is a directory.
7354 * @file: BaulFile representing the file in question.
7355 *
7356 * Returns: TRUE if @file is a directory.
7357 *
7358 **/
7359gboolean
7360baul_file_is_directory (BaulFile *file)
7361{
7362 return baul_file_get_file_type (file) == G_FILE_TYPE_DIRECTORY;
7363}
7364
7365/**
7366 * baul_file_is_user_special_directory
7367 *
7368 * Check if this file is a special platform directory.
7369 * @file: BaulFile representing the file in question.
7370 * @special_directory: GUserDirectory representing the type to test for
7371 *
7372 * Returns: TRUE if @file is a special directory of the given kind.
7373 */
7374gboolean
7375baul_file_is_user_special_directory (BaulFile *file,
7376 GUserDirectory special_directory)
7377{
7378 gboolean is_special_dir;
7379 const gchar *special_dir;
7380
7381 special_dir = g_get_user_special_dir (special_directory);
7382 is_special_dir = FALSE(0);
7383
7384 if (special_dir) {
7385 GFile *loc;
7386 GFile *special_gfile;
7387
7388 loc = baul_file_get_location (file);
7389 special_gfile = g_file_new_for_path (special_dir);
7390 is_special_dir = g_file_equal (loc, special_gfile);
7391 g_object_unref (special_gfile);
7392 g_object_unref (loc);
7393 }
7394
7395 return is_special_dir;
7396}
7397
7398gboolean
7399baul_file_is_archive (BaulFile *file)
7400{
7401 char *mime_type;
7402 int i;
7403 static const char * archive_mime_types[] = { "application/x-gtar",
7404 "application/x-zip",
7405 "application/x-zip-compressed",
7406 "application/zip",
7407 "application/x-zip",
7408 "application/x-tar",
7409 "application/x-7z-compressed",
7410 "application/x-rar",
7411 "application/x-rar-compressed",
7412 "application/x-jar",
7413 "application/x-java-archive",
7414 "application/x-war",
7415 "application/x-ear",
7416 "application/x-arj",
7417 "application/x-gzip",
7418 "application/x-bzip-compressed-tar",
7419 "application/x-compressed-tar" };
7420
7421 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)
;
7422
7423 mime_type = baul_file_get_mime_type (file);
7424 for (i = 0; i < G_N_ELEMENTS (archive_mime_types)(sizeof (archive_mime_types) / sizeof ((archive_mime_types)[0
]))
; i++) {
7425 if (!strcmp (mime_type, archive_mime_types[i])) {
7426 g_free (mime_type);
7427 return TRUE(!(0));
7428 }
7429 }
7430 g_free (mime_type);
7431
7432 return FALSE(0);
7433}
7434
7435
7436/**
7437 * baul_file_is_in_trash
7438 *
7439 * Check if this file is a file in trash.
7440 * @file: BaulFile representing the file in question.
7441 *
7442 * Returns: TRUE if @file is in a trash.
7443 *
7444 **/
7445gboolean
7446baul_file_is_in_trash (BaulFile *file)
7447{
7448 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", 7448,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
7449
7450 return baul_directory_is_in_trash (file->details->directory);
7451}
7452
7453GError *
7454baul_file_get_file_info_error (BaulFile *file)
7455{
7456 if (!file->details->get_info_failed) {
7457 return NULL((void*)0);
7458 }
7459
7460 return file->details->get_info_error;
7461}
7462
7463/**
7464 * baul_file_contains_text
7465 *
7466 * Check if this file contains text.
7467 * This is private and is used to decide whether or not to read the top left text.
7468 * @file: BaulFile representing the file in question.
7469 *
7470 * Returns: TRUE if @file has a text MIME type.
7471 *
7472 **/
7473gboolean
7474baul_file_contains_text (BaulFile *file)
7475{
7476 if (file == NULL((void*)0)) {
7477 return FALSE(0);
7478 }
7479
7480 /* All text files inherit from text/plain */
7481 return baul_file_is_mime_type (file, "text/plain");
7482}
7483
7484/**
7485 * baul_file_is_binary
7486 *
7487 * Check if this file is a binary file.
7488 * This is private and is used to decide whether or not to show the diff
7489 * button in the file conflict dialog.
7490 * @file: BaulFile representing the file in question.
7491 *
7492 * Returns: TRUE if @file is a binary file.
7493 *
7494 **/
7495gboolean
7496baul_file_is_binary (BaulFile *file)
7497{
7498 if (!baul_file_can_read(file))
7499 {
7500 return FALSE(0);
7501 }
7502
7503 gboolean is_binary = FALSE(0);
7504 int i = 0;
7505 FILE *fp;
7506
7507 /* Check the first 4096 bytes of the files. If these contains a 0,
7508 * we can assume the file is binary.
7509 * This idea is taken from python code of meld.
7510 */
7511
7512 fp = g_fopenfopen (g_file_get_path (baul_file_get_location (file)), "r");
7513 if (fp == NULL((void*)0))
7514 {
7515 return FALSE(0);
7516 }
7517
7518 while (!feof (fp)) {
7519 int c;
7520
7521 if (i > 4096) {
7522 break;
7523 }
7524 c = fgetc(fp);
7525 if (c == 0) {
7526 is_binary = TRUE(!(0));
7527 break;
7528 }
7529 i++;
7530 }
7531 fclose(fp);
7532
7533 return is_binary;
7534}
7535
7536/**
7537 * baul_file_is_executable
7538 *
7539 * Check if this file is executable at all.
7540 * @file: BaulFile representing the file in question.
7541 *
7542 * Returns: TRUE if any of the execute bits are set. FALSE if
7543 * not, or if the permissions are unknown.
7544 *
7545 **/
7546gboolean
7547baul_file_is_executable (BaulFile *file)
7548{
7549 if (!file->details->has_permissions) {
7550 /* File's permissions field is not valid.
7551 * Can't access specific permissions, so return FALSE.
7552 */
7553 return FALSE(0);
7554 }
7555
7556 return file->details->can_execute;
7557}
7558
7559/**
7560 * baul_file_peek_top_left_text
7561 *
7562 * Peek at the text from the top left of the file.
7563 * @file: BaulFile representing the file in question.
7564 *
7565 * Returns: NULL if there is no text readable, otherwise, the text.
7566 * This string is owned by the file object and should not
7567 * be kept around or freed.
7568 *
7569 **/
7570char *
7571baul_file_peek_top_left_text (BaulFile *file,
7572 gboolean need_large_text,
7573 gboolean *needs_loading)
7574{
7575 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)
;
7576
7577 if (!baul_file_should_get_top_left_text (file)) {
7578 if (needs_loading) {
7579 *needs_loading = FALSE(0);
7580 }
7581 return NULL((void*)0);
7582 }
7583
7584 if (needs_loading) {
7585 *needs_loading = !file->details->top_left_text_is_up_to_date;
7586 if (need_large_text) {
7587 *needs_loading |= file->details->got_top_left_text != file->details->got_large_top_left_text;
7588 }
7589 }
7590
7591 /* Show " ..." in the file until we read the contents in. */
7592 if (!file->details->got_top_left_text) {
7593
7594 if (baul_file_contains_text (file)) {
7595 return " ...";
7596 }
7597 return NULL((void*)0);
7598 }
7599
7600 /* Show what we read in. */
7601 return file->details->top_left_text;
7602}
7603
7604/**
7605 * baul_file_get_top_left_text
7606 *
7607 * Get the text from the top left of the file.
7608 * @file: BaulFile representing the file in question.
7609 *
7610 * Returns: NULL if there is no text readable, otherwise, the text.
7611 *
7612 **/
7613char *
7614baul_file_get_top_left_text (BaulFile *file)
7615{
7616 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)))
;
7617}
7618
7619char *
7620baul_file_get_filesystem_id (BaulFile *file)
7621{
7622 return g_strdup (file->details->filesystem_id)g_strdup_inline (file->details->filesystem_id);
7623}
7624
7625BaulFile *
7626baul_file_get_trash_original_file (BaulFile *file)
7627{
7628 BaulFile *original_file;
7629
7630 original_file = NULL((void*)0);
7631
7632 if (file->details->trash_orig_path != NULL((void*)0)) {
7633 GFile *location;
7634
7635 location = g_file_new_for_path (file->details->trash_orig_path);
7636 original_file = baul_file_get (location);
7637 g_object_unref (location);
7638 }
7639
7640 return original_file;
7641
7642}
7643
7644void
7645baul_file_mark_gone (BaulFile *file)
7646{
7647 BaulDirectory *directory;
7648
7649 if (file->details->is_gone)
7650 return;
7651
7652 file->details->is_gone = TRUE(!(0));
7653
7654 update_links_if_target (file);
7655
7656 /* Drop it from the symlink hash ! */
7657 remove_from_link_hash_table (file);
7658
7659 /* Let the directory know it's gone. */
7660 directory = file->details->directory;
7661 if (!baul_file_is_self_owned (file)) {
7662 baul_directory_remove_file (directory, file);
7663 }
7664
7665 baul_file_clear_info (file);
7666
7667 /* FIXME bugzilla.gnome.org 42429:
7668 * Maybe we can get rid of the name too eventually, but
7669 * for now that would probably require too many if statements
7670 * everywhere anyone deals with the name. Maybe we can give it
7671 * a hard-coded "<deleted>" name or something.
7672 */
7673}
7674
7675/**
7676 * baul_file_changed
7677 *
7678 * Notify the user that this file has changed.
7679 * @file: BaulFile representing the file in question.
7680 **/
7681void
7682baul_file_changed (BaulFile *file)
7683{
7684 GList fake_list;
7685
7686 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)
;
7687
7688 if (baul_file_is_self_owned (file)) {
7689 baul_file_emit_changed (file);
7690 } else {
7691 fake_list.data = file;
7692 fake_list.next = NULL((void*)0);
7693 fake_list.prev = NULL((void*)0);
7694 baul_directory_emit_change_signals
7695 (file->details->directory, &fake_list);
7696 }
7697}
7698
7699/**
7700 * baul_file_updated_deep_count_in_progress
7701 *
7702 * Notify clients that a newer deep count is available for
7703 * the directory in question.
7704 */
7705void
7706baul_file_updated_deep_count_in_progress (BaulFile *file) {
7707 GList *link_files, *node;
7708
7709 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", 7709,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
7710 g_assert (baul_file_is_directory (file))do { if (baul_file_is_directory (file)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-file.c", 7710, ((const char*) (__func__
)), "baul_file_is_directory (file)"); } while (0)
;
7711
7712 /* Send out a signal. */
7713 g_signal_emit (file, signals[UPDATED_DEEP_COUNT_IN_PROGRESS], 0, file);
7714
7715 /* Tell link files pointing to this object about the change. */
7716 link_files = get_link_files (file);
7717 for (node = link_files; node != NULL((void*)0); node = node->next) {
7718 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())))))
);
7719 }
7720 baul_file_list_free (link_files);
7721}
7722
7723/**
7724 * baul_file_emit_changed
7725 *
7726 * Emit a file changed signal.
7727 * This can only be called by the directory, since the directory
7728 * also has to emit a files_changed signal.
7729 *
7730 * @file: BaulFile representing the file in question.
7731 **/
7732void
7733baul_file_emit_changed (BaulFile *file)
7734{
7735 GList *link_files, *p;
7736
7737 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", 7737,
((const char*) (__func__)), "BAUL_IS_FILE (file)"); } while (
0)
;
7738
7739
7740 /* Invalidate the emblem compare cache. -- This is not the cleanest
7741 * place to do it but it is the one guaranteed bottleneck through
7742 * which all change notifications pass.
7743 */
7744 g_free (file->details->compare_by_emblem_cache);
7745 file->details->compare_by_emblem_cache = NULL((void*)0);
7746
7747 /* Send out a signal. */
7748 g_signal_emit (file, signals[CHANGED], 0, file);
7749
7750 /* Tell link files pointing to this object about the change. */
7751 link_files = get_link_files (file);
7752 for (p = link_files; p != NULL((void*)0); p = p->next) {
7753 if (p->data != file) {
7754 baul_file_changed (BAUL_FILE (p->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((p->data)), (baul_file_get_type())))))
);
7755 }
7756 }
7757 baul_file_list_free (link_files);
7758}
7759
7760/**
7761 * baul_file_is_gone
7762 *
7763 * Check if a file has already been deleted.
7764 * @file: BaulFile representing the file in question.
7765 *
7766 * Returns: TRUE if the file is already gone.
7767 **/
7768gboolean
7769baul_file_is_gone (BaulFile *file)
7770{
7771 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)
;
7772
7773 return file->details->is_gone;
7774}
7775
7776/**
7777 * baul_file_is_not_yet_confirmed
7778 *
7779 * Check if we're in a state where we don't know if a file really
7780 * exists or not, before the initial I/O is complete.
7781 * @file: BaulFile representing the file in question.
7782 *
7783 * Returns: TRUE if the file is already gone.
7784 **/
7785gboolean
7786baul_file_is_not_yet_confirmed (BaulFile *file)
7787{
7788 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)
;
7789
7790 return !file->details->got_file_info;
7791}
7792
7793/**
7794 * baul_file_check_if_ready
7795 *
7796 * Check whether the values for a set of file attributes are
7797 * currently available, without doing any additional work. This
7798 * is useful for callers that want to reflect updated information
7799 * when it is ready but don't want to force the work required to
7800 * obtain the information, which might be slow network calls, e.g.
7801 *
7802 * @file: The file being queried.
7803 * @file_attributes: A bit-mask with the desired information.
7804 *
7805 * Return value: TRUE if all of the specified attributes are currently readable.
7806 */
7807gboolean
7808baul_file_check_if_ready (BaulFile *file,
7809 BaulFileAttributes file_attributes)
7810{
7811 /* To be parallel with call_when_ready, return
7812 * TRUE for NULL file.
7813 */
7814 if (file == NULL((void*)0)) {
7815 return TRUE(!(0));
7816 }
7817
7818 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)
;
7819
7820 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))
7821 (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))
7822 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))
;
7823}
7824
7825void
7826baul_file_call_when_ready (BaulFile *file,
7827 BaulFileAttributes file_attributes,
7828 BaulFileCallback callback,
7829 gpointer callback_data)
7830
7831{
7832 if (file == NULL((void*)0)) {
7833 (* callback) (file, callback_data);
7834 return;
7835 }
7836
7837 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)
;
7838
7839 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)
7840 (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)
7841 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)
7842 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)
;
7843}
7844
7845void
7846baul_file_cancel_call_when_ready (BaulFile *file,
7847 BaulFileCallback callback,
7848 gpointer callback_data)
7849{
7850 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)
;
7851
7852 if (file == NULL((void*)0)) {
7853 return;
7854 }
7855
7856 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)
;
7857
7858 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)
7859 (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)
7860 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)
;
7861}
7862
7863static void
7864invalidate_directory_count (BaulFile *file)
7865{
7866 file->details->directory_count_is_up_to_date = FALSE(0);
7867}
7868
7869static void
7870invalidate_deep_counts (BaulFile *file)
7871{
7872 file->details->deep_counts_status = BAUL_REQUEST_NOT_STARTED;
7873}
7874
7875static void
7876invalidate_mime_list (BaulFile *file)
7877{
7878 file->details->mime_list_is_up_to_date = FALSE(0);
7879}
7880
7881static void
7882invalidate_top_left_text (BaulFile *file)
7883{
7884 file->details->top_left_text_is_up_to_date = FALSE(0);
7885}
7886
7887static void
7888invalidate_file_info (BaulFile *file)
7889{
7890 file->details->file_info_is_up_to_date = FALSE(0);
7891}
7892
7893static void
7894invalidate_link_info (BaulFile *file)
7895{
7896 file->details->link_info_is_up_to_date = FALSE(0);
7897}
7898
7899static void
7900invalidate_thumbnail (BaulFile *file)
7901{
7902 file->details->thumbnail_is_up_to_date = FALSE(0);
7903}
7904
7905static void
7906invalidate_mount (BaulFile *file)
7907{
7908 file->details->mount_is_up_to_date = FALSE(0);
7909}
7910
7911void
7912baul_file_invalidate_extension_info_internal (BaulFile *file)
7913{
7914 if (file->details->pending_info_providers)
7915 g_list_free_full (file->details->pending_info_providers, g_object_unref);
7916
7917 file->details->pending_info_providers =
7918 baul_extensions_get_for_type (BAUL_TYPE_INFO_PROVIDER(baul_info_provider_get_type ()));
7919}
7920
7921void
7922baul_file_invalidate_attributes_internal (BaulFile *file,
7923 BaulFileAttributes file_attributes)
7924{
7925 Request request;
7926
7927 if (file == NULL((void*)0)) {
7928 return;
7929 }
7930
7931 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; }))))
) {
7932 /* Desktop icon files are always up to date.
7933 * If we invalidate their attributes they
7934 * will lose data, so we just ignore them.
7935 */
7936 return;
7937 }
7938
7939 request = baul_directory_set_up_request (file_attributes);
7940
7941 if (REQUEST_WANTS_TYPE (request, REQUEST_DIRECTORY_COUNT)((request) & (1<<(REQUEST_DIRECTORY_COUNT)))) {
7942 invalidate_directory_count (file);
7943 }
7944 if (REQUEST_WANTS_TYPE (request, REQUEST_DEEP_COUNT)((request) & (1<<(REQUEST_DEEP_COUNT)))) {
7945 invalidate_deep_counts (file);
7946 }
7947 if (REQUEST_WANTS_TYPE (request, REQUEST_MIME_LIST)((request) & (1<<(REQUEST_MIME_LIST)))) {
7948 invalidate_mime_list (file);
7949 }
7950 if (REQUEST_WANTS_TYPE (request, REQUEST_FILE_INFO)((request) & (1<<(REQUEST_FILE_INFO)))) {
7951 invalidate_file_info (file);
7952 }
7953 if (REQUEST_WANTS_TYPE (request, REQUEST_TOP_LEFT_TEXT)((request) & (1<<(REQUEST_TOP_LEFT_TEXT)))) {
7954 invalidate_top_left_text (file);
7955 }
7956 if (REQUEST_WANTS_TYPE (request, REQUEST_LINK_INFO)((request) & (1<<(REQUEST_LINK_INFO)))) {
7957 invalidate_link_info (file);
7958 }
7959 if (REQUEST_WANTS_TYPE (request, REQUEST_EXTENSION_INFO)((request) & (1<<(REQUEST_EXTENSION_INFO)))) {
7960 baul_file_invalidate_extension_info_internal (file);
7961 }
7962 if (REQUEST_WANTS_TYPE (request, REQUEST_THUMBNAIL)((request) & (1<<(REQUEST_THUMBNAIL)))) {
7963 invalidate_thumbnail (file);
7964 }
7965 if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)((request) & (1<<(REQUEST_MOUNT)))) {
7966 invalidate_mount (file);
7967 }
7968
7969 /* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */
7970}
7971
7972gboolean
7973baul_file_has_open_window (BaulFile *file)
7974{
7975 return file->details->has_open_window;
7976}
7977
7978void
7979baul_file_set_has_open_window (BaulFile *file,
7980 gboolean has_open_window)
7981{
7982 has_open_window = (has_open_window != FALSE(0));
7983
7984 if (file->details->has_open_window != has_open_window) {
7985 file->details->has_open_window = has_open_window;
7986 baul_file_changed (file);
7987 }
7988}
7989
7990
7991gboolean
7992baul_file_is_thumbnailing (BaulFile *file)
7993{
7994 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)
;
7995
7996 return file->details->is_thumbnailing;
7997}
7998
7999void
8000baul_file_set_is_thumbnailing (BaulFile *file,
8001 gboolean is_thumbnailing)
8002{
8003 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)
;
8004
8005 file->details->is_thumbnailing = is_thumbnailing;
8006}
8007
8008
8009/**
8010 * baul_file_invalidate_attributes
8011 *
8012 * Invalidate the specified attributes and force a reload.
8013 * @file: BaulFile representing the file in question.
8014 * @file_attributes: attributes to froget.
8015 **/
8016
8017void
8018baul_file_invalidate_attributes (BaulFile *file,
8019 BaulFileAttributes file_attributes)
8020{
8021 /* Cancel possible in-progress loads of any of these attributes */
8022 baul_directory_cancel_loading_file_attributes (file->details->directory,
8023 file,
8024 file_attributes);
8025
8026 /* Actually invalidate the values */
8027 baul_file_invalidate_attributes_internal (file, file_attributes);
8028
8029 baul_directory_add_file_to_work_queue (file->details->directory, file);
8030
8031 /* Kick off I/O if necessary */
8032 baul_directory_async_state_changed (file->details->directory);
8033}
8034
8035BaulFileAttributes
8036baul_file_get_all_attributes (void)
8037{
8038 return BAUL_FILE_ATTRIBUTE_INFO |
8039 BAUL_FILE_ATTRIBUTE_LINK_INFO |
8040 BAUL_FILE_ATTRIBUTE_DEEP_COUNTS |
8041 BAUL_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
8042 BAUL_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES |
8043 BAUL_FILE_ATTRIBUTE_TOP_LEFT_TEXT |
8044 BAUL_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT |
8045 BAUL_FILE_ATTRIBUTE_EXTENSION_INFO |
8046 BAUL_FILE_ATTRIBUTE_THUMBNAIL |
8047 BAUL_FILE_ATTRIBUTE_MOUNT;
8048}
8049
8050void
8051baul_file_invalidate_all_attributes (BaulFile *file)
8052{
8053 BaulFileAttributes all_attributes;
8054
8055 all_attributes = baul_file_get_all_attributes ();
8056 baul_file_invalidate_attributes (file, all_attributes);
8057}
8058
8059
8060/**
8061 * baul_file_dump
8062 *
8063 * Debugging call, prints out the contents of the file
8064 * fields.
8065 *
8066 * @file: file to dump.
8067 **/
8068void
8069baul_file_dump (BaulFile *file)
8070{
8071 long size = file->details->deep_size;
8072 long size_on_disk = file->details->deep_size_on_disk;
8073 char *uri;
8074 const char *file_kind;
8075
8076 uri = baul_file_get_uri (file);
8077 g_print ("uri: %s \n", uri);
8078 if (!file->details->got_file_info) {
8079 g_print ("no file info \n");
8080 } else if (file->details->get_info_failed) {
8081 g_print ("failed to get file info \n");
8082 } else {
8083 g_print ("size: %ld \n", size);
8084 g_print ("disk size: %ld \n", size_on_disk);
8085 switch (file->details->type) {
8086 case G_FILE_TYPE_REGULAR:
8087 file_kind = "regular file";
8088 break;
8089 case G_FILE_TYPE_DIRECTORY:
8090 file_kind = "folder";
8091 break;
8092 case G_FILE_TYPE_SPECIAL:
8093 file_kind = "special";
8094 break;
8095 case G_FILE_TYPE_SYMBOLIC_LINK:
8096 file_kind = "symbolic link";
8097 break;
8098 case G_FILE_TYPE_UNKNOWN:
8099 default:
8100 file_kind = "unknown";
8101 break;
8102 }
8103 g_print ("kind: %s \n", file_kind);
8104 if (file->details->type == G_FILE_TYPE_SYMBOLIC_LINK) {
8105 g_print ("link to %s \n", file->details->symlink_name);
8106 /* FIXME bugzilla.gnome.org 42430: add following of symlinks here */
8107 }
8108 /* FIXME bugzilla.gnome.org 42431: add permissions and other useful stuff here */
8109 }
8110 g_free (uri);
8111}
8112
8113/**
8114 * baul_file_list_ref
8115 *
8116 * Ref all the files in a list.
8117 * @list: GList of files.
8118 **/
8119GList *
8120baul_file_list_ref (GList *list)
8121{
8122 g_list_foreach (list, (GFunc) baul_file_ref, NULL((void*)0));
8123 return list;
8124}
8125
8126/**
8127 * baul_file_list_unref
8128 *
8129 * Unref all the files in a list.
8130 * @list: GList of files.
8131 **/
8132void
8133baul_file_list_unref (GList *list)
8134{
8135 g_list_foreach (list, (GFunc) baul_file_unref, NULL((void*)0));
8136}
8137
8138/**
8139 * baul_file_list_free
8140 *
8141 * Free a list of files after unrefing them.
8142 * @list: GList of files.
8143 **/
8144void
8145baul_file_list_free (GList *list)
8146{
8147 baul_file_list_unref (list);
8148 g_list_free (list);
8149}
8150
8151/**
8152 * baul_file_list_copy
8153 *
8154 * Copy the list of files, making a new ref of each,
8155 * @list: GList of files.
8156 **/
8157GList *
8158baul_file_list_copy (GList *list)
8159{
8160 return g_list_copy (baul_file_list_ref (list));
8161}
8162
8163static gboolean
8164get_attributes_for_default_sort_type (BaulFile *file,
8165 gboolean *is_download,
8166 gboolean *is_trash)
8167{
8168 gboolean is_download_dir, is_desktop_dir, is_trash_dir, retval;
8169
8170 *is_download = FALSE(0);
8171 *is_trash = FALSE(0);
8172 retval = FALSE(0);
8173
8174 /* special handling for certain directories */
8175 if (file && baul_file_is_directory (file)) {
8176 is_download_dir =
8177 baul_file_is_user_special_directory (file, G_USER_DIRECTORY_DOWNLOAD);
8178 is_desktop_dir =
8179 baul_file_is_user_special_directory (file, G_USER_DIRECTORY_DESKTOP);
8180 is_trash_dir =
8181 baul_file_is_in_trash (file);
8182
8183 if (is_download_dir && !is_desktop_dir) {
8184 *is_download = TRUE(!(0));
8185 retval = TRUE(!(0));
8186 } else if (is_trash_dir) {
8187 *is_trash = TRUE(!(0));
8188 retval = TRUE(!(0));
8189 }
8190 }
8191
8192 return retval;
8193}
8194
8195BaulFileSortType
8196baul_file_get_default_sort_type (BaulFile *file,
8197 gboolean *reversed)
8198{
8199 BaulFileSortType retval;
8200 gboolean is_download, is_trash, res;
8201
8202 retval = BAUL_FILE_SORT_NONE;
8203 is_download = is_trash = FALSE(0);
8204 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8205
8206 if (res) {
8207 if (is_download) {
8208 retval = BAUL_FILE_SORT_BY_MTIME;
8209 } else if (is_trash) {
8210 retval = BAUL_FILE_SORT_BY_TRASHED_TIME;
8211 }
8212
8213 if (reversed != NULL((void*)0)) {
8214 *reversed = res;
8215 }
8216 }
8217
8218 return retval;
8219}
8220
8221const gchar *
8222baul_file_get_default_sort_attribute (BaulFile *file,
8223 gboolean *reversed)
8224{
8225 const gchar *retval;
8226 gboolean is_download, is_trash, res;
8227
8228 retval = NULL((void*)0);
8229 is_download = is_trash = FALSE(0);
8230 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8231
8232 if (res) {
8233 if (is_download) {
8234 retval = g_quark_to_string (attribute_date_modified_q);
8235 } else if (is_trash) {
8236 retval = g_quark_to_string (attribute_trashed_on_q);
8237 }
8238
8239 if (reversed != NULL((void*)0)) {
8240 *reversed = res;
8241 }
8242 }
8243
8244 return retval;
8245}
8246
8247static int
8248compare_by_display_name_cover (gconstpointer a, gconstpointer b)
8249{
8250 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())))))
);
8251}
8252
8253/**
8254 * baul_file_list_sort_by_display_name
8255 *
8256 * Sort the list of files by file name.
8257 * @list: GList of files.
8258 **/
8259GList *
8260baul_file_list_sort_by_display_name (GList *list)
8261{
8262 return g_list_sort (list, compare_by_display_name_cover);
8263}
8264
8265static GList *ready_data_list = NULL((void*)0);
8266
8267typedef struct
8268{
8269 GList *file_list;
8270 GList *remaining_files;
8271 BaulFileListCallback callback;
8272 gpointer callback_data;
8273} FileListReadyData;
8274
8275static void
8276file_list_ready_data_free (FileListReadyData *data)
8277{
8278 GList *l;
8279
8280 l = g_list_find (ready_data_list, data);
8281 if (l != NULL((void*)0)) {
8282 ready_data_list = g_list_delete_link (ready_data_list, l);
8283
8284 baul_file_list_free (data->file_list);
8285 g_list_free (data->remaining_files);
8286 g_free (data);
8287 }
8288}
8289
8290static FileListReadyData *
8291file_list_ready_data_new (GList *file_list,
8292 BaulFileListCallback callback,
8293 gpointer callback_data)
8294{
8295 FileListReadyData *data;
8296
8297 data = g_new0 (FileListReadyData, 1)((FileListReadyData *) g_malloc0_n ((1), sizeof (FileListReadyData
)))
;
8298 data->file_list = baul_file_list_copy (file_list);
8299 data->remaining_files = g_list_copy (file_list);
8300 data->callback = callback;
8301 data->callback_data = callback_data;
8302
8303 ready_data_list = g_list_prepend (ready_data_list, data);
8304
8305 return data;
8306}
8307
8308static void
8309file_list_file_ready_callback (BaulFile *file,
8310 gpointer user_data)
8311{
8312 FileListReadyData *data;
8313
8314 data = user_data;
8315 data->remaining_files = g_list_remove (data->remaining_files, file);
8316
8317 if (data->remaining_files == NULL((void*)0)) {
8318 if (data->callback) {
8319 (*data->callback) (data->file_list, data->callback_data);
8320 }
8321
8322 file_list_ready_data_free (data);
8323 }
8324}
8325
8326void
8327baul_file_list_call_when_ready (GList *file_list,
8328 BaulFileAttributes attributes,
8329 BaulFileListHandle **handle,
8330 BaulFileListCallback callback,
8331 gpointer callback_data)
8332{
8333 GList *l;
8334 FileListReadyData *data;
8335 BaulFile *file = NULL((void*)0);
8336
8337 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)
;
8338
8339 data = file_list_ready_data_new
8340 (file_list, callback, callback_data);
8341
8342 if (handle) {
8343 *handle = (BaulFileListHandle *) data;
8344 }
8345
8346
8347 l = file_list;
8348 while (l != NULL((void*)0)) {
8349 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
8350 /* Need to do this here, as the list can be modified by this call */
8351 l = l->next;
8352
8353 if (file)
8354 baul_file_call_when_ready (file,
8355 attributes,
8356 file_list_file_ready_callback,
8357 data);
8358 }
8359}
8360
8361void
8362baul_file_list_cancel_call_when_ready (BaulFileListHandle *handle)
8363{
8364 GList *l;
8365 FileListReadyData *data;
8366
8367 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)
;
8368
8369 data = (FileListReadyData *) handle;
8370
8371 l = g_list_find (ready_data_list, data);
8372 if (l != NULL((void*)0)) {
8373 BaulFile *file = NULL((void*)0);
8374
8375 for (l = data->remaining_files; l != NULL((void*)0); l = l->next) {
8376 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
8377
8378 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)
8379 (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)
8380 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)
;
8381 }
8382
8383 file_list_ready_data_free (data);
8384 }
8385}
8386
8387static char *
8388try_to_make_utf8 (const char *text, int *length)
8389{
8390 static const char *encodings_to_try[2];
8391 static int n_encodings_to_try = 0;
8392 gsize converted_length;
8393 GError *conversion_error;
8394 char *utf8_text;
8395 int i;
8396
8397 if (n_encodings_to_try == 0) {
8398 const char *charset;
8399 gboolean charset_is_utf8;
8400
8401 charset_is_utf8 = g_get_charset (&charset);
8402 if (!charset_is_utf8) {
8403 encodings_to_try[n_encodings_to_try++] = charset;
8404 }
8405
8406 if (g_ascii_strcasecmp (charset, "ISO-8859-1") != 0) {
8407 encodings_to_try[n_encodings_to_try++] = "ISO-8859-1";
8408 }
8409 }
8410
8411 utf8_text = NULL((void*)0);
8412 for (i = 0; i < n_encodings_to_try; i++) {
8413 conversion_error = NULL((void*)0);
8414 utf8_text = g_convert (text, *length,
8415 "UTF-8", encodings_to_try[i],
8416 NULL((void*)0), &converted_length, &conversion_error);
8417 if (utf8_text != NULL((void*)0)) {
8418 *length = converted_length;
8419 break;
8420 }
8421 g_error_free (conversion_error);
8422 }
8423
8424 return utf8_text;
8425}
8426
8427
8428
8429/* Extract the top left part of the read-in text. */
8430char *
8431baul_extract_top_left_text (const char *text,
8432 gboolean large,
8433 int length)
8434{
8435 GString* buffer;
8436 const gchar *in;
8437 const gchar *end;
8438 int line, i;
8439 gunichar c;
8440 char *text_copy;
8441 const char *utf8_end;
8442 gboolean validated;
8443 int max_bytes, max_lines, max_cols;
8444
8445 if (large) {
8446 max_bytes = BAUL_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_BYTES10000;
8447 max_lines = BAUL_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_LINES24;
8448 max_cols = BAUL_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE80;
8449 } else {
8450 max_bytes = BAUL_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES1024;
8451 max_lines = BAUL_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES5;
8452 max_cols = BAUL_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE10;
8453 }
8454
8455
8456
8457 text_copy = NULL((void*)0);
8458 if (text != NULL((void*)0)) {
8459 /* Might be a partial utf8 character at the end if we didn't read whole file */
8460 validated = g_utf8_validate (text, length, &utf8_end);
8461 if (!validated &&
8462 !(length >= max_bytes &&
8463 text + length - utf8_end < 6)) {
8464 text_copy = try_to_make_utf8 (text, &length);
8465 text = text_copy;
8466 } else if (!validated) {
8467 length = utf8_end - text;
8468 }
8469 }
8470
8471 if (text == NULL((void*)0) || length == 0) {
8472 return NULL((void*)0);
8473 }
8474
8475 buffer = g_string_new ("");
8476 end = text + length; in = text;
8477
8478 for (line = 0; line < max_lines; line++) {
8479 /* Extract one line. */
8480 for (i = 0; i < max_cols; ) {
8481 if (*in == '\n') {
8482 break;
8483 }
8484
8485 c = g_utf8_get_char (in);
8486
8487 if (g_unichar_isprint (c)) {
8488 g_string_append_unichar (buffer, c);
8489 i++;
8490 }
8491
8492 in = g_utf8_next_char (in)(char *)((in) + g_utf8_skip[*(const guchar *)(in)]);
8493 if (in == end) {
8494 goto done;
8495 }
8496 }
8497
8498 /* Skip the rest of the line. */
8499 while (*in != '\n') {
8500 if (++in == end) {
8501 goto done;
8502 }
8503 }
8504 if (++in == end) {
8505 goto done;
8506 }
8507
8508 /* Put a new-line separator in. */
8509 g_string_append_c(buffer, '\n')g_string_append_c_inline (buffer, '\n');
8510 }
8511 done:
8512 g_free (text_copy);
8513
8514 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))))
;
8515}
8516
8517static void
8518thumbnail_limit_changed_callback (gpointer user_data)
8519{
8520 g_settings_get (baul_preferences,
8521 BAUL_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT"thumbnail-limit",
8522 "t", &cached_thumbnail_limit);
8523
8524 /* Tell the world that icons might have changed. We could invent a narrower-scope
8525 * signal to mean only "thumbnails might have changed" if this ends up being slow
8526 * for some reason.
8527 */
8528 emit_change_signals_for_all_files_in_all_directories ();
8529}
8530
8531static void
8532thumbnail_size_changed_callback (gpointer user_data)
8533{
8534 cached_thumbnail_size = g_settings_get_int (baul_icon_view_preferences, BAUL_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE"thumbnail-size");
8535
8536 /* Tell the world that icons might have changed. We could invent a narrower-scope
8537 * signal to mean only "thumbnails might have changed" if this ends up being slow
8538 * for some reason.
8539 */
8540 emit_change_signals_for_all_files_in_all_directories ();
8541}
8542
8543static void
8544show_thumbnails_changed_callback (gpointer user_data)
8545{
8546 show_image_thumbs = g_settings_get_enum (baul_preferences, BAUL_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS"show-image-thumbnails");
8547
8548 /* Tell the world that icons might have changed. We could invent a narrower-scope
8549 * signal to mean only "thumbnails might have changed" if this ends up being slow
8550 * for some reason.
8551 */
8552 emit_change_signals_for_all_files_in_all_directories ();
8553}
8554
8555static void
8556mime_type_data_changed_callback (GObject *signaller, gpointer user_data)
8557{
8558 /* Tell the world that icons might have changed. We could invent a narrower-scope
8559 * signal to mean only "thumbnails might have changed" if this ends up being slow
8560 * for some reason.
8561 */
8562 emit_change_signals_for_all_files_in_all_directories ();
8563}
8564
8565static void
8566icon_theme_changed_callback (CtkIconTheme *icon_theme,
8567 gpointer user_data)
8568{
8569 /* Clear all pixmap caches as the icon => pixmap lookup changed */
8570 baul_icon_info_clear_caches ();
8571
8572 /* Tell the world that icons might have changed. We could invent a narrower-scope
8573 * signal to mean only "thumbnails might have changed" if this ends up being slow
8574 * for some reason.
8575 */
8576 emit_change_signals_for_all_files_in_all_directories ();
8577}
8578
8579static void
8580baul_file_class_init (BaulFileClass *class)
8581{
8582 CtkIconTheme *icon_theme;
8583
8584 baul_file_info_getter = baul_file_get_internal;
8585
8586 attribute_name_q = g_quark_from_static_string ("name");
8587 attribute_size_q = g_quark_from_static_string ("size");
8588 attribute_size_on_disk_q = g_quark_from_static_string ("size_on_disk");
8589 attribute_type_q = g_quark_from_static_string ("type");
8590 attribute_modification_date_q = g_quark_from_static_string ("modification_date");
8591 attribute_date_modified_q = g_quark_from_static_string ("date_modified");
8592 attribute_accessed_date_q = g_quark_from_static_string ("accessed_date");
8593 attribute_date_accessed_q = g_quark_from_static_string ("date_accessed");
8594 attribute_emblems_q = g_quark_from_static_string ("emblems");
8595 attribute_extension_q = g_quark_from_static_string ("extension");
8596 attribute_mime_type_q = g_quark_from_static_string ("mime_type");
8597 attribute_size_detail_q = g_quark_from_static_string ("size_detail");
8598 attribute_size_on_disk_detail_q = g_quark_from_static_string ("size_on_disk_detail");
8599 attribute_deep_size_q = g_quark_from_static_string ("deep_size");
8600 attribute_deep_size_on_disk_q = g_quark_from_static_string ("deep_size_on_disk");
8601 attribute_deep_file_count_q = g_quark_from_static_string ("deep_file_count");
8602 attribute_deep_directory_count_q = g_quark_from_static_string ("deep_directory_count");
8603 attribute_deep_total_count_q = g_quark_from_static_string ("deep_total_count");
8604 attribute_date_changed_q = g_quark_from_static_string ("date_changed");
8605 attribute_trashed_on_q = g_quark_from_static_string ("trashed_on");
8606 attribute_trash_orig_path_q = g_quark_from_static_string ("trash_orig_path");
8607 attribute_date_permissions_q = g_quark_from_static_string ("date_permissions");
8608 attribute_permissions_q = g_quark_from_static_string ("permissions");
8609 attribute_selinux_context_q = g_quark_from_static_string ("selinux_context");
8610 attribute_octal_permissions_q = g_quark_from_static_string ("octal_permissions");
8611 attribute_owner_q = g_quark_from_static_string ("owner");
8612 attribute_group_q = g_quark_from_static_string ("group");
8613 attribute_uri_q = g_quark_from_static_string ("uri");
8614 attribute_where_q = g_quark_from_static_string ("where");
8615 attribute_link_target_q = g_quark_from_static_string ("link_target");
8616 attribute_volume_q = g_quark_from_static_string ("volume");
8617 attribute_free_space_q = g_quark_from_static_string ("free_space");
8618
8619 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
->finalize = finalize;
8620 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
->constructor = baul_file_constructor;
8621
8622 signals[CHANGED] =
8623 g_signal_new ("changed",
8624 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8625 G_SIGNAL_RUN_LAST,
8626 G_STRUCT_OFFSET (BaulFileClass, changed)((glong) __builtin_offsetof(BaulFileClass, changed)),
8627 NULL((void*)0), NULL((void*)0),
8628 g_cclosure_marshal_VOID__VOID,
8629 G_TYPE_NONE((GType) ((1) << (2))), 0);
8630
8631 signals[UPDATED_DEEP_COUNT_IN_PROGRESS] =
8632 g_signal_new ("updated_deep_count_in_progress",
8633 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8634 G_SIGNAL_RUN_LAST,
8635 G_STRUCT_OFFSET (BaulFileClass, updated_deep_count_in_progress)((glong) __builtin_offsetof(BaulFileClass, updated_deep_count_in_progress
))
,
8636 NULL((void*)0), NULL((void*)0),
8637 g_cclosure_marshal_VOID__VOID,
8638 G_TYPE_NONE((GType) ((1) << (2))), 0);
8639
8640 eel_g_settings_add_auto_enum (baul_preferences,
8641 BAUL_PREFERENCES_DATE_FORMAT"date-format",
8642 &date_format_pref);
8643
8644 thumbnail_limit_changed_callback (NULL((void*)0));
8645 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)
8646 "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)
8647 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)
8648 NULL)g_signal_connect_data ((baul_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8649 thumbnail_size_changed_callback (NULL((void*)0));
8650 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)
8651 "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)
8652 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)
8653 NULL)g_signal_connect_data ((baul_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8654 show_thumbnails_changed_callback (NULL((void*)0));
8655 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)
8656 "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)
8657 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)
8658 NULL)g_signal_connect_data ((baul_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8659
8660 icon_theme = ctk_icon_theme_get_default ();
8661 g_signal_connect_object (icon_theme,
8662 "changed",
8663 G_CALLBACK (icon_theme_changed_callback)((GCallback) (icon_theme_changed_callback)),
8664 NULL((void*)0), 0);
8665
8666 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)
8667 "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)
8668 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)
8669 NULL)g_signal_connect_data ((baul_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
;
8670}
8671
8672static void
8673baul_file_add_emblem (BaulFile *file,
8674 const char *emblem_name)
8675{
8676 if (file->details->pending_info_providers) {
8677 file->details->pending_extension_emblems = g_list_prepend (file->details->pending_extension_emblems,
8678 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8679 } else {
8680 file->details->extension_emblems = g_list_prepend (file->details->extension_emblems,
8681 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8682 }
8683
8684 baul_file_changed (file);
8685}
8686
8687static void
8688baul_file_add_string_attribute (BaulFile *file,
8689 const char *attribute_name,
8690 const char *value)
8691{
8692 if (file->details->pending_info_providers) {
8693 /* Lazily create hashtable */
8694 if (!file->details->pending_extension_attributes) {
8695 file->details->pending_extension_attributes =
8696 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8697 NULL((void*)0),
8698 (GDestroyNotify)g_free);
8699 }
8700 g_hash_table_insert (file->details->pending_extension_attributes,
8701 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8702 g_strdup (value)g_strdup_inline (value));
8703 } else {
8704 if (!file->details->extension_attributes) {
8705 file->details->extension_attributes =
8706 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8707 NULL((void*)0),
8708 (GDestroyNotify)g_free);
8709 }
8710 g_hash_table_insert (file->details->extension_attributes,
8711 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8712 g_strdup (value)g_strdup_inline (value));
8713 }
8714
8715 baul_file_changed (file);
8716}
8717
8718static void
8719baul_file_invalidate_extension_info (BaulFile *file)
8720{
8721 baul_file_invalidate_attributes (file, BAUL_FILE_ATTRIBUTE_EXTENSION_INFO);
8722}
8723
8724void
8725baul_file_info_providers_done (BaulFile *file)
8726{
8727 g_list_free_full (file->details->extension_emblems, g_free);
8728 file->details->extension_emblems = file->details->pending_extension_emblems;
8729 file->details->pending_extension_emblems = NULL((void*)0);
8730
8731 if (file->details->extension_attributes) {
8732 g_hash_table_destroy (file->details->extension_attributes);
8733 }
8734
8735 file->details->extension_attributes = file->details->pending_extension_attributes;
8736 file->details->pending_extension_attributes = NULL((void*)0);
8737
8738 baul_file_changed (file);
8739}
8740
8741static void
8742baul_file_info_iface_init (BaulFileInfoIface *iface)
8743{
8744 iface->is_gone = baul_file_is_gone;
8745 iface->get_name = baul_file_get_name;
8746 iface->get_file_type = baul_file_get_file_type;
8747 iface->get_location = baul_file_get_location;
8748 iface->get_uri = baul_file_get_uri;
8749 iface->get_parent_location = baul_file_get_parent_location;
8750 iface->get_parent_uri = baul_file_get_parent_uri;
8751 iface->get_parent_info = baul_file_get_parent;
8752 iface->get_mount = baul_file_get_mount;
8753 iface->get_uri_scheme = baul_file_get_uri_scheme;
8754 iface->get_activation_uri = baul_file_get_activation_uri;
8755 iface->get_mime_type = baul_file_get_mime_type;
8756 iface->is_mime_type = baul_file_is_mime_type;
8757 iface->is_directory = baul_file_is_directory;
8758 iface->can_write = baul_file_can_write;
8759 iface->add_emblem = baul_file_add_emblem;
8760 iface->get_string_attribute = baul_file_get_string_attribute;
8761 iface->add_string_attribute = baul_file_add_string_attribute;
8762 iface->invalidate_extension_info = baul_file_invalidate_extension_info;
8763}
8764
8765#if !defined (BAUL_OMIT_SELF_CHECK)
8766
8767void
8768baul_self_check_file (void)
8769{
8770 BaulFile *file_1;
8771 BaulFile *file_2;
8772 GList *list;
8773
8774 /* refcount checks */
8775
8776 EEL_CHECK_INTEGER_RESULT (baul_directory_number_outstanding (), 0)do { eel_before_check ("baul_directory_number_outstanding ()"
, "baul-file.c", 8776); eel_check_integer_result (baul_directory_number_outstanding
(), 0); } while (0)
;
8777
8778 file_1 = baul_file_get_by_uri ("file:///home/");
8779
8780 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", 8780); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1
)), (((GType) ((20) << (2))))))))->ref_count, 1); } while
(0)
;
8781 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", 8781); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1
->details->directory)), (((GType) ((20) << (2))))
))))->ref_count, 1); } while (0)
;
8782 EEL_CHECK_INTEGER_RESULT (baul_directory_number_outstanding (), 1)do { eel_before_check ("baul_directory_number_outstanding ()"
, "baul-file.c", 8782); eel_check_integer_result (baul_directory_number_outstanding
(), 1); } while (0)
;
8783
8784 baul_file_unref (file_1);
8785
8786 EEL_CHECK_INTEGER_RESULT (baul_directory_number_outstanding (), 0)do { eel_before_check ("baul_directory_number_outstanding ()"
, "baul-file.c", 8786); eel_check_integer_result (baul_directory_number_outstanding
(), 0); } while (0)
;
8787
8788 file_1 = baul_file_get_by_uri ("file:///etc");
8789 file_2 = baul_file_get_by_uri ("file:///usr");
8790
8791 list = NULL((void*)0);
8792 list = g_list_prepend (list, file_1);
8793 list = g_list_prepend (list, file_2);
8794
8795 baul_file_list_ref (list);
8796
8797 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", 8797); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1
)), (((GType) ((20) << (2))))))))->ref_count, 2); } while
(0)
;
8798 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", 8798); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_2
)), (((GType) ((20) << (2))))))))->ref_count, 2); } while
(0)
;
8799
8800 baul_file_list_unref (list);
8801
8802 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", 8802); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1
)), (((GType) ((20) << (2))))))))->ref_count, 1); } while
(0)
;
8803 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", 8803); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_2
)), (((GType) ((20) << (2))))))))->ref_count, 1); } while
(0)
;
8804
8805 baul_file_list_free (list);
8806
8807 EEL_CHECK_INTEGER_RESULT (baul_directory_number_outstanding (), 0)do { eel_before_check ("baul_directory_number_outstanding ()"
, "baul-file.c", 8807); eel_check_integer_result (baul_directory_number_outstanding
(), 0); } while (0)
;
8808
8809
8810 /* name checks */
8811 file_1 = baul_file_get_by_uri ("file:///home/");
8812
8813 EEL_CHECK_STRING_RESULT (baul_file_get_name (file_1), "home")do { eel_before_check ("baul_file_get_name (file_1)", "baul-file.c"
, 8813); eel_check_string_result (baul_file_get_name (file_1)
, "home"); } while (0)
;
8814
8815 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", 8815); eel_check_boolean_result (baul_file_get_by_uri
("file:///home/") == file_1, (!(0))); } while (0)
;
8816 baul_file_unref (file_1);
8817
8818 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", 8818); eel_check_boolean_result (baul_file_get_by_uri
("file:///home") == file_1, (!(0))); } while (0)
;
8819 baul_file_unref (file_1);
8820
8821 baul_file_unref (file_1);
8822
8823 file_1 = baul_file_get_by_uri ("file:///home");
8824 EEL_CHECK_STRING_RESULT (baul_file_get_name (file_1), "home")do { eel_before_check ("baul_file_get_name (file_1)", "baul-file.c"
, 8824); eel_check_string_result (baul_file_get_name (file_1)
, "home"); } while (0)
;
8825 baul_file_unref (file_1);
8826
8827#if 0
8828 /* ALEX: I removed this, because it was breaking distchecks.
8829 * It used to work, but when canonical uris changed from
8830 * foo: to foo:/// it broke. I don't expect it to matter
8831 * in real life */
8832 file_1 = baul_file_get_by_uri (":");
8833 EEL_CHECK_STRING_RESULT (baul_file_get_name (file_1), ":")do { eel_before_check ("baul_file_get_name (file_1)", "baul-file.c"
, 8833); eel_check_string_result (baul_file_get_name (file_1)
, ":"); } while (0)
;
8834 baul_file_unref (file_1);
8835#endif
8836
8837 file_1 = baul_file_get_by_uri ("eazel:");
8838 EEL_CHECK_STRING_RESULT (baul_file_get_name (file_1), "eazel")do { eel_before_check ("baul_file_get_name (file_1)", "baul-file.c"
, 8838); eel_check_string_result (baul_file_get_name (file_1)
, "eazel"); } while (0)
;
8839 baul_file_unref (file_1);
8840
8841 /* sorting */
8842 file_1 = baul_file_get_by_uri ("file:///etc");
8843 file_2 = baul_file_get_by_uri ("file:///usr");
8844
8845 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", 8845); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_1
)), (((GType) ((20) << (2))))))))->ref_count, 1); } while
(0)
;
8846 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", 8846); eel_check_integer_result (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((file_2
)), (((GType) ((20) << (2))))))))->ref_count, 1); } while
(0)
;
8847
8848 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", 8848); 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)
;
8849 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", 8849); 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)
;
8850 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", 8850); 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)
;
8851 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", 8851); 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)
;
8852 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", 8852); 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)
;
8853 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", 8853); 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)
;
8854
8855 baul_file_unref (file_1);
8856 baul_file_unref (file_2);
8857}
8858
8859#endif /* !BAUL_OMIT_SELF_CHECK */