Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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