Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2006-2007 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: Alexander Larsson <alexl@redhat.com>
21 : : */
22 : :
23 : : /**
24 : : * GFileInfo:
25 : : *
26 : : * Stores information about a file system object referenced by a [iface@Gio.File].
27 : : *
28 : : * Functionality for manipulating basic metadata for files. `GFileInfo`
29 : : * implements methods for getting information that all files should
30 : : * contain, and allows for manipulation of extended attributes.
31 : : *
32 : : * See the [file attributes](file-attributes.html) document for more
33 : : * information on how GIO handles file attributes.
34 : : *
35 : : * To obtain a `GFileInfo` for a [iface@Gio.File], use
36 : : * [method@Gio.File.query_info] (or its async variant). To obtain a `GFileInfo`
37 : : * for a file input or output stream, use [method@Gio.FileInputStream.query_info]
38 : : * or [method@Gio.FileOutputStream.query_info] (or their async variants).
39 : : *
40 : : * To change the actual attributes of a file, you should then set the
41 : : * attribute in the `GFileInfo` and call [method@Gio.File.set_attributes_from_info]
42 : : * or [method@Gio.File.set_attributes_async] on a `GFile`.
43 : : *
44 : : * However, not all attributes can be changed in the file. For instance,
45 : : * the actual size of a file cannot be changed via [method@Gio.FileInfo.set_size].
46 : : * You may call [method@Gio.File.query_settable_attributes] and
47 : : * [method@Gio.File.query_writable_namespaces] to discover the settable attributes
48 : : * of a particular file at runtime.
49 : : *
50 : : * The direct accessors, such as [method@Gio.FileInfo.get_name], are slightly more
51 : : * optimized than the generic attribute accessors, such as
52 : : * [method@Gio.FileInfo.get_attribute_byte_string].This optimization will matter
53 : : * only if calling the API in a tight loop.
54 : : *
55 : : * It is an error to call these accessors without specifying their required file
56 : : * attributes when creating the `GFileInfo`. Use
57 : : * [method@Gio.FileInfo.has_attribute] or [method@Gio.FileInfo.list_attributes]
58 : : * to check what attributes are specified for a `GFileInfo`.
59 : : *
60 : : * [struct@Gio.FileAttributeMatcher] allows for searching through a `GFileInfo`
61 : : * for attributes.
62 : : **/
63 : :
64 : : #include "config.h"
65 : :
66 : : #include <string.h>
67 : :
68 : : #include "gfileinfo.h"
69 : : #include "gfileinfo-priv.h"
70 : : #include "gfileattribute-priv.h"
71 : : #include "gicon.h"
72 : : #include "glibintl.h"
73 : :
74 : :
75 : : /* We use this nasty thing, because NULL is a valid attribute matcher (matches nothing) */
76 : : #define NO_ATTRIBUTE_MASK ((GFileAttributeMatcher *)1)
77 : :
78 : : typedef struct {
79 : : guint32 attribute;
80 : : GFileAttributeValue value;
81 : : } GFileAttribute;
82 : :
83 : : struct _GFileInfo
84 : : {
85 : : GObject parent_instance;
86 : :
87 : : GArray *attributes;
88 : : GFileAttributeMatcher *mask;
89 : : };
90 : :
91 : : struct _GFileInfoClass
92 : : {
93 : : GObjectClass parent_class;
94 : : };
95 : :
96 : :
97 : 12208 : G_DEFINE_TYPE (GFileInfo, g_file_info, G_TYPE_OBJECT)
98 : :
99 : : typedef struct {
100 : : guint32 id;
101 : : guint32 attribute_id_counter;
102 : : } NSInfo;
103 : :
104 : : G_LOCK_DEFINE_STATIC (attribute_hash);
105 : : static int namespace_id_counter = 0;
106 : : static GHashTable *ns_hash = NULL;
107 : : static GHashTable *attribute_hash = NULL;
108 : : static char ***global_attributes = NULL;
109 : :
110 : : /* Attribute ids are 32bit, we split it up like this:
111 : : * |------------|--------------------|
112 : : * 12 bit 20 bit
113 : : * namespace attribute id
114 : : *
115 : : * This way the attributes gets sorted in namespace order
116 : : */
117 : :
118 : : #define NS_POS 20
119 : : #define NS_MASK ((guint32)((1<<12) - 1))
120 : : #define ID_POS 0
121 : : #define ID_MASK ((guint32)((1<<20) - 1))
122 : :
123 : : #define GET_NS(_attr_id) \
124 : : (((guint32) (_attr_id) >> NS_POS) & NS_MASK)
125 : : #define GET_ID(_attr_id) \
126 : : (((guint32)(_attr_id) >> ID_POS) & ID_MASK)
127 : :
128 : : #define MAKE_ATTR_ID(_ns, _id) \
129 : : ( ((((guint32) _ns) & NS_MASK) << NS_POS) | \
130 : : ((((guint32) _id) & ID_MASK) << ID_POS) )
131 : :
132 : : static NSInfo *
133 : 3470 : _lookup_namespace (const char *namespace)
134 : : {
135 : : NSInfo *ns_info;
136 : :
137 : 3470 : ns_info = g_hash_table_lookup (ns_hash, namespace);
138 : 3470 : if (ns_info == NULL)
139 : : {
140 : 321 : ns_info = g_new0 (NSInfo, 1);
141 : 321 : ns_info->id = ++namespace_id_counter;
142 : 321 : g_hash_table_insert (ns_hash, g_strdup (namespace), ns_info);
143 : 321 : global_attributes = g_realloc (global_attributes, (ns_info->id + 1) * sizeof (char **));
144 : 321 : global_attributes[ns_info->id] = g_new (char *, 1);
145 : 321 : global_attributes[ns_info->id][0] = g_strconcat (namespace, "::*", NULL);
146 : : }
147 : 3470 : return ns_info;
148 : : }
149 : :
150 : : static guint32
151 : 6863 : _lookup_attribute (const char *attribute)
152 : : {
153 : : guint32 attr_id, id;
154 : : char *ns;
155 : : const char *colon;
156 : : NSInfo *ns_info;
157 : :
158 : 6863 : attr_id = GPOINTER_TO_UINT (g_hash_table_lookup (attribute_hash, attribute));
159 : :
160 : 6863 : if (attr_id != 0)
161 : 4921 : return attr_id;
162 : :
163 : 1942 : colon = strstr (attribute, "::");
164 : 1942 : if (colon)
165 : 1942 : ns = g_strndup (attribute, colon - attribute);
166 : : else
167 : 0 : ns = g_strdup ("");
168 : :
169 : 1942 : ns_info = _lookup_namespace (ns);
170 : 1942 : g_free (ns);
171 : :
172 : 1942 : id = ++ns_info->attribute_id_counter;
173 : 1942 : global_attributes[ns_info->id] = g_realloc (global_attributes[ns_info->id], (id + 1) * sizeof (char *));
174 : 1942 : global_attributes[ns_info->id][id] = g_strdup (attribute);
175 : :
176 : 1942 : attr_id = MAKE_ATTR_ID (ns_info->id, id);
177 : :
178 : 1942 : g_hash_table_insert (attribute_hash, global_attributes[ns_info->id][id], GUINT_TO_POINTER (attr_id));
179 : :
180 : 1942 : return attr_id;
181 : : }
182 : :
183 : : static void
184 : 6471 : ensure_attribute_hash (void)
185 : : {
186 : 6471 : if (attribute_hash != NULL)
187 : 6451 : return;
188 : :
189 : 20 : ns_hash = g_hash_table_new (g_str_hash, g_str_equal);
190 : 20 : attribute_hash = g_hash_table_new (g_str_hash, g_str_equal);
191 : :
192 : : #define REGISTER_ATTRIBUTE(name) G_STMT_START{\
193 : : guint _u G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */; \
194 : : _u = _lookup_attribute (G_FILE_ATTRIBUTE_ ## name); \
195 : : /* use for generating the ID: g_print ("#define G_FILE_ATTRIBUTE_ID_%s (%u + %u)\n", #name + 17, _u & ~ID_MASK, _u & ID_MASK); */ \
196 : : g_assert (_u == G_FILE_ATTRIBUTE_ID_ ## name); \
197 : : }G_STMT_END
198 : :
199 : 20 : REGISTER_ATTRIBUTE (STANDARD_TYPE);
200 : 20 : REGISTER_ATTRIBUTE (STANDARD_IS_HIDDEN);
201 : 20 : REGISTER_ATTRIBUTE (STANDARD_IS_BACKUP);
202 : 20 : REGISTER_ATTRIBUTE (STANDARD_IS_SYMLINK);
203 : 20 : REGISTER_ATTRIBUTE (STANDARD_IS_VIRTUAL);
204 : 20 : REGISTER_ATTRIBUTE (STANDARD_NAME);
205 : 20 : REGISTER_ATTRIBUTE (STANDARD_DISPLAY_NAME);
206 : 20 : REGISTER_ATTRIBUTE (STANDARD_EDIT_NAME);
207 : 20 : REGISTER_ATTRIBUTE (STANDARD_COPY_NAME);
208 : 20 : REGISTER_ATTRIBUTE (STANDARD_DESCRIPTION);
209 : 20 : REGISTER_ATTRIBUTE (STANDARD_ICON);
210 : 20 : REGISTER_ATTRIBUTE (STANDARD_CONTENT_TYPE);
211 : 20 : REGISTER_ATTRIBUTE (STANDARD_FAST_CONTENT_TYPE);
212 : 20 : REGISTER_ATTRIBUTE (STANDARD_SIZE);
213 : 20 : REGISTER_ATTRIBUTE (STANDARD_ALLOCATED_SIZE);
214 : 20 : REGISTER_ATTRIBUTE (STANDARD_SYMLINK_TARGET);
215 : 20 : REGISTER_ATTRIBUTE (STANDARD_TARGET_URI);
216 : 20 : REGISTER_ATTRIBUTE (STANDARD_SORT_ORDER);
217 : 20 : REGISTER_ATTRIBUTE (STANDARD_SYMBOLIC_ICON);
218 : 20 : REGISTER_ATTRIBUTE (STANDARD_IS_VOLATILE);
219 : 20 : REGISTER_ATTRIBUTE (ETAG_VALUE);
220 : 20 : REGISTER_ATTRIBUTE (ID_FILE);
221 : 20 : REGISTER_ATTRIBUTE (ID_FILESYSTEM);
222 : 20 : REGISTER_ATTRIBUTE (ACCESS_CAN_READ);
223 : 20 : REGISTER_ATTRIBUTE (ACCESS_CAN_WRITE);
224 : 20 : REGISTER_ATTRIBUTE (ACCESS_CAN_EXECUTE);
225 : 20 : REGISTER_ATTRIBUTE (ACCESS_CAN_DELETE);
226 : 20 : REGISTER_ATTRIBUTE (ACCESS_CAN_TRASH);
227 : 20 : REGISTER_ATTRIBUTE (ACCESS_CAN_RENAME);
228 : 20 : REGISTER_ATTRIBUTE (MOUNTABLE_CAN_MOUNT);
229 : 20 : REGISTER_ATTRIBUTE (MOUNTABLE_CAN_UNMOUNT);
230 : 20 : REGISTER_ATTRIBUTE (MOUNTABLE_CAN_EJECT);
231 : 20 : REGISTER_ATTRIBUTE (MOUNTABLE_UNIX_DEVICE);
232 : 20 : REGISTER_ATTRIBUTE (MOUNTABLE_UNIX_DEVICE_FILE);
233 : 20 : REGISTER_ATTRIBUTE (MOUNTABLE_HAL_UDI);
234 : 20 : REGISTER_ATTRIBUTE (MOUNTABLE_CAN_START);
235 : 20 : REGISTER_ATTRIBUTE (MOUNTABLE_CAN_START_DEGRADED);
236 : 20 : REGISTER_ATTRIBUTE (MOUNTABLE_CAN_STOP);
237 : 20 : REGISTER_ATTRIBUTE (MOUNTABLE_START_STOP_TYPE);
238 : 20 : REGISTER_ATTRIBUTE (MOUNTABLE_CAN_POLL);
239 : 20 : REGISTER_ATTRIBUTE (MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC);
240 : 20 : REGISTER_ATTRIBUTE (TIME_MODIFIED);
241 : 20 : REGISTER_ATTRIBUTE (TIME_MODIFIED_USEC);
242 : 20 : REGISTER_ATTRIBUTE (TIME_ACCESS);
243 : 20 : REGISTER_ATTRIBUTE (TIME_ACCESS_USEC);
244 : 20 : REGISTER_ATTRIBUTE (TIME_CHANGED);
245 : 20 : REGISTER_ATTRIBUTE (TIME_CHANGED_USEC);
246 : 20 : REGISTER_ATTRIBUTE (TIME_CREATED);
247 : 20 : REGISTER_ATTRIBUTE (TIME_CREATED_USEC);
248 : 20 : REGISTER_ATTRIBUTE (TIME_MODIFIED_NSEC);
249 : 20 : REGISTER_ATTRIBUTE (TIME_ACCESS_NSEC);
250 : 20 : REGISTER_ATTRIBUTE (TIME_CREATED_NSEC);
251 : 20 : REGISTER_ATTRIBUTE (TIME_CHANGED_NSEC);
252 : 20 : REGISTER_ATTRIBUTE (UNIX_DEVICE);
253 : 20 : REGISTER_ATTRIBUTE (UNIX_INODE);
254 : 20 : REGISTER_ATTRIBUTE (UNIX_MODE);
255 : 20 : REGISTER_ATTRIBUTE (UNIX_NLINK);
256 : 20 : REGISTER_ATTRIBUTE (UNIX_UID);
257 : 20 : REGISTER_ATTRIBUTE (UNIX_GID);
258 : 20 : REGISTER_ATTRIBUTE (UNIX_RDEV);
259 : 20 : REGISTER_ATTRIBUTE (UNIX_BLOCK_SIZE);
260 : 20 : REGISTER_ATTRIBUTE (UNIX_BLOCKS);
261 : 20 : REGISTER_ATTRIBUTE (UNIX_IS_MOUNTPOINT);
262 : 20 : REGISTER_ATTRIBUTE (DOS_IS_ARCHIVE);
263 : 20 : REGISTER_ATTRIBUTE (DOS_IS_SYSTEM);
264 : 20 : REGISTER_ATTRIBUTE (DOS_IS_MOUNTPOINT);
265 : 20 : REGISTER_ATTRIBUTE (DOS_REPARSE_POINT_TAG);
266 : 20 : REGISTER_ATTRIBUTE (OWNER_USER);
267 : 20 : REGISTER_ATTRIBUTE (OWNER_USER_REAL);
268 : 20 : REGISTER_ATTRIBUTE (OWNER_GROUP);
269 : 20 : REGISTER_ATTRIBUTE (THUMBNAIL_PATH);
270 : 20 : REGISTER_ATTRIBUTE (THUMBNAILING_FAILED);
271 : 20 : REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID);
272 : 20 : REGISTER_ATTRIBUTE (THUMBNAIL_PATH_NORMAL);
273 : 20 : REGISTER_ATTRIBUTE (THUMBNAILING_FAILED_NORMAL);
274 : 20 : REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID_NORMAL);
275 : 20 : REGISTER_ATTRIBUTE (THUMBNAIL_PATH_LARGE);
276 : 20 : REGISTER_ATTRIBUTE (THUMBNAILING_FAILED_LARGE);
277 : 20 : REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID_LARGE);
278 : 20 : REGISTER_ATTRIBUTE (THUMBNAIL_PATH_XLARGE);
279 : 20 : REGISTER_ATTRIBUTE (THUMBNAILING_FAILED_XLARGE);
280 : 20 : REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID_XLARGE);
281 : 20 : REGISTER_ATTRIBUTE (THUMBNAIL_PATH_XXLARGE);
282 : 20 : REGISTER_ATTRIBUTE (THUMBNAILING_FAILED_XXLARGE);
283 : 20 : REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID_XXLARGE);
284 : 20 : REGISTER_ATTRIBUTE (PREVIEW_ICON);
285 : 20 : REGISTER_ATTRIBUTE (FILESYSTEM_SIZE);
286 : 20 : REGISTER_ATTRIBUTE (FILESYSTEM_FREE);
287 : 20 : REGISTER_ATTRIBUTE (FILESYSTEM_TYPE);
288 : 20 : REGISTER_ATTRIBUTE (FILESYSTEM_READONLY);
289 : 20 : REGISTER_ATTRIBUTE (FILESYSTEM_USE_PREVIEW);
290 : 20 : REGISTER_ATTRIBUTE (GVFS_BACKEND);
291 : 20 : REGISTER_ATTRIBUTE (SELINUX_CONTEXT);
292 : 20 : REGISTER_ATTRIBUTE (TRASH_ITEM_COUNT);
293 : 20 : REGISTER_ATTRIBUTE (TRASH_ORIG_PATH);
294 : 20 : REGISTER_ATTRIBUTE (TRASH_DELETION_DATE);
295 : :
296 : : #undef REGISTER_ATTRIBUTE
297 : : }
298 : :
299 : : static guint32
300 : 1528 : lookup_namespace (const char *namespace)
301 : : {
302 : : NSInfo *ns_info;
303 : : guint32 id;
304 : :
305 : 1528 : G_LOCK (attribute_hash);
306 : :
307 : 1528 : ensure_attribute_hash ();
308 : :
309 : 1528 : ns_info = _lookup_namespace (namespace);
310 : 1528 : id = 0;
311 : 1528 : if (ns_info)
312 : 1528 : id = ns_info->id;
313 : :
314 : 1528 : G_UNLOCK (attribute_hash);
315 : :
316 : 1528 : return id;
317 : : }
318 : :
319 : : static char *
320 : 255 : get_attribute_for_id (int attribute)
321 : : {
322 : : char *s;
323 : 255 : G_LOCK (attribute_hash);
324 : 255 : s = global_attributes[GET_NS (attribute)][GET_ID (attribute)];
325 : 255 : G_UNLOCK (attribute_hash);
326 : 255 : return s;
327 : : }
328 : :
329 : : static guint32
330 : 4943 : lookup_attribute (const char *attribute)
331 : : {
332 : : guint32 attr_id;
333 : :
334 : 4943 : G_LOCK (attribute_hash);
335 : 4943 : ensure_attribute_hash ();
336 : :
337 : 4943 : attr_id = _lookup_attribute (attribute);
338 : :
339 : 4943 : G_UNLOCK (attribute_hash);
340 : :
341 : 4943 : return attr_id;
342 : : }
343 : :
344 : : static void
345 : 1143 : g_file_info_finalize (GObject *object)
346 : : {
347 : : GFileInfo *info;
348 : : guint i;
349 : : GFileAttribute *attrs;
350 : :
351 : 1143 : info = G_FILE_INFO (object);
352 : :
353 : 1143 : attrs = (GFileAttribute *)info->attributes->data;
354 : 7155 : for (i = 0; i < info->attributes->len; i++)
355 : 6012 : _g_file_attribute_value_clear (&attrs[i].value);
356 : 1143 : g_array_free (info->attributes, TRUE);
357 : :
358 : 1143 : if (info->mask != NO_ATTRIBUTE_MASK)
359 : 47 : g_file_attribute_matcher_unref (info->mask);
360 : :
361 : 1143 : G_OBJECT_CLASS (g_file_info_parent_class)->finalize (object);
362 : 1143 : }
363 : :
364 : : static void
365 : 21 : g_file_info_class_init (GFileInfoClass *klass)
366 : : {
367 : 21 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
368 : :
369 : 21 : gobject_class->finalize = g_file_info_finalize;
370 : 21 : }
371 : :
372 : : static void
373 : 1143 : g_file_info_init (GFileInfo *info)
374 : : {
375 : 1143 : info->mask = NO_ATTRIBUTE_MASK;
376 : 1143 : info->attributes = g_array_new (FALSE, FALSE,
377 : : sizeof (GFileAttribute));
378 : 1143 : }
379 : :
380 : : /**
381 : : * g_file_info_new:
382 : : *
383 : : * Creates a new file info structure.
384 : : *
385 : : * Returns: a #GFileInfo.
386 : : **/
387 : : GFileInfo *
388 : 1142 : g_file_info_new (void)
389 : : {
390 : 1142 : return g_object_new (G_TYPE_FILE_INFO, NULL);
391 : : }
392 : :
393 : : /**
394 : : * g_file_info_copy_into:
395 : : * @src_info: source to copy attributes from.
396 : : * @dest_info: destination to copy attributes to.
397 : : *
398 : : * First clears all of the [GFileAttribute](file-attributes.html#file-attributes) of
399 : : * @dest_info, and then copies all of the file attributes from @src_info to @dest_info.
400 : : **/
401 : : void
402 : 2 : g_file_info_copy_into (GFileInfo *src_info,
403 : : GFileInfo *dest_info)
404 : : {
405 : : GFileAttribute *source, *dest;
406 : : guint i;
407 : :
408 : 2 : g_return_if_fail (G_IS_FILE_INFO (src_info));
409 : 2 : g_return_if_fail (G_IS_FILE_INFO (dest_info));
410 : :
411 : 2 : dest = (GFileAttribute *)dest_info->attributes->data;
412 : 2 : for (i = 0; i < dest_info->attributes->len; i++)
413 : 0 : _g_file_attribute_value_clear (&dest[i].value);
414 : :
415 : 2 : g_array_set_size (dest_info->attributes,
416 : 2 : src_info->attributes->len);
417 : :
418 : 2 : source = (GFileAttribute *)src_info->attributes->data;
419 : 2 : dest = (GFileAttribute *)dest_info->attributes->data;
420 : :
421 : 10 : for (i = 0; i < src_info->attributes->len; i++)
422 : : {
423 : 8 : dest[i].attribute = source[i].attribute;
424 : 8 : dest[i].value.type = G_FILE_ATTRIBUTE_TYPE_INVALID;
425 : 8 : _g_file_attribute_value_set (&dest[i].value, &source[i].value);
426 : : }
427 : :
428 : 2 : if (dest_info->mask != NO_ATTRIBUTE_MASK)
429 : 0 : g_file_attribute_matcher_unref (dest_info->mask);
430 : :
431 : 2 : if (src_info->mask == NO_ATTRIBUTE_MASK)
432 : 2 : dest_info->mask = NO_ATTRIBUTE_MASK;
433 : : else
434 : 0 : dest_info->mask = g_file_attribute_matcher_ref (src_info->mask);
435 : : }
436 : :
437 : : /**
438 : : * g_file_info_dup:
439 : : * @other: a #GFileInfo.
440 : : *
441 : : * Duplicates a file info structure.
442 : : *
443 : : * Returns: (transfer full): a duplicate #GFileInfo of @other.
444 : : **/
445 : : GFileInfo *
446 : 1 : g_file_info_dup (GFileInfo *other)
447 : : {
448 : : GFileInfo *new;
449 : :
450 : 1 : g_return_val_if_fail (G_IS_FILE_INFO (other), NULL);
451 : :
452 : 1 : new = g_file_info_new ();
453 : 1 : g_file_info_copy_into (other, new);
454 : 1 : return new;
455 : : }
456 : :
457 : : /**
458 : : * g_file_info_set_attribute_mask:
459 : : * @info: a #GFileInfo.
460 : : * @mask: a #GFileAttributeMatcher.
461 : : *
462 : : * Sets @mask on @info to match specific attribute types.
463 : : **/
464 : : void
465 : 1119 : g_file_info_set_attribute_mask (GFileInfo *info,
466 : : GFileAttributeMatcher *mask)
467 : : {
468 : : GFileAttribute *attr;
469 : : guint i;
470 : :
471 : 1119 : g_return_if_fail (G_IS_FILE_INFO (info));
472 : :
473 : 1119 : if (mask != info->mask)
474 : : {
475 : 1119 : if (info->mask != NO_ATTRIBUTE_MASK)
476 : 0 : g_file_attribute_matcher_unref (info->mask);
477 : 1119 : info->mask = g_file_attribute_matcher_ref (mask);
478 : :
479 : : /* Remove non-matching attributes */
480 : 1123 : for (i = 0; i < info->attributes->len; i++)
481 : : {
482 : 4 : attr = &g_array_index (info->attributes, GFileAttribute, i);
483 : 4 : if (!_g_file_attribute_matcher_matches_id (mask,
484 : : attr->attribute))
485 : : {
486 : 2 : _g_file_attribute_value_clear (&attr->value);
487 : 2 : g_array_remove_index (info->attributes, i);
488 : 2 : i--;
489 : : }
490 : : }
491 : : }
492 : : }
493 : :
494 : : /**
495 : : * g_file_info_unset_attribute_mask:
496 : : * @info: #GFileInfo.
497 : : *
498 : : * Unsets a mask set by g_file_info_set_attribute_mask(), if one
499 : : * is set.
500 : : **/
501 : : void
502 : 1072 : g_file_info_unset_attribute_mask (GFileInfo *info)
503 : : {
504 : 1072 : g_return_if_fail (G_IS_FILE_INFO (info));
505 : :
506 : 1072 : if (info->mask != NO_ATTRIBUTE_MASK)
507 : 1072 : g_file_attribute_matcher_unref (info->mask);
508 : 1072 : info->mask = NO_ATTRIBUTE_MASK;
509 : : }
510 : :
511 : : /**
512 : : * g_file_info_clear_status:
513 : : * @info: a #GFileInfo.
514 : : *
515 : : * Clears the status information from @info.
516 : : **/
517 : : void
518 : 36 : g_file_info_clear_status (GFileInfo *info)
519 : : {
520 : : GFileAttribute *attrs;
521 : : guint i;
522 : :
523 : 36 : g_return_if_fail (G_IS_FILE_INFO (info));
524 : :
525 : 36 : attrs = (GFileAttribute *)info->attributes->data;
526 : 233 : for (i = 0; i < info->attributes->len; i++)
527 : 197 : attrs[i].value.status = G_FILE_ATTRIBUTE_STATUS_UNSET;
528 : : }
529 : :
530 : : static int
531 : 9076 : g_file_info_find_place (GFileInfo *info,
532 : : guint32 attribute)
533 : : {
534 : : int min, max, med;
535 : : GFileAttribute *attrs;
536 : : /* Binary search for the place where attribute would be, if it's
537 : : in the array */
538 : :
539 : 9076 : min = 0;
540 : 9076 : max = info->attributes->len;
541 : :
542 : 9076 : attrs = (GFileAttribute *)info->attributes->data;
543 : :
544 : 32623 : while (min < max)
545 : : {
546 : 26312 : med = min + (max - min) / 2;
547 : 26312 : if (attrs[med].attribute == attribute)
548 : : {
549 : 2765 : min = med;
550 : 2765 : break;
551 : : }
552 : 23547 : else if (attrs[med].attribute < attribute)
553 : 11449 : min = med + 1;
554 : : else /* attrs[med].attribute > attribute */
555 : 12098 : max = med;
556 : : }
557 : :
558 : 9076 : return min;
559 : : }
560 : :
561 : : static GFileAttributeValue *
562 : 2764 : g_file_info_find_value (GFileInfo *info,
563 : : guint32 attr_id)
564 : : {
565 : : GFileAttribute *attrs;
566 : : guint i;
567 : :
568 : 2764 : i = g_file_info_find_place (info, attr_id);
569 : 2764 : attrs = (GFileAttribute *)info->attributes->data;
570 : 2764 : if (i < info->attributes->len &&
571 : 2641 : attrs[i].attribute == attr_id)
572 : 2466 : return &attrs[i].value;
573 : :
574 : 298 : return NULL;
575 : : }
576 : :
577 : : static GFileAttributeValue *
578 : 1594 : g_file_info_find_value_by_name (GFileInfo *info,
579 : : const char *attribute)
580 : : {
581 : : guint32 attr_id;
582 : :
583 : 1594 : attr_id = lookup_attribute (attribute);
584 : 1594 : return g_file_info_find_value (info, attr_id);
585 : : }
586 : :
587 : : /**
588 : : * g_file_info_has_attribute:
589 : : * @info: a #GFileInfo.
590 : : * @attribute: a file attribute key.
591 : : *
592 : : * Checks if a file info structure has an attribute named @attribute.
593 : : *
594 : : * Returns: %TRUE if @info has an attribute named @attribute,
595 : : * %FALSE otherwise.
596 : : **/
597 : : gboolean
598 : 462 : g_file_info_has_attribute (GFileInfo *info,
599 : : const char *attribute)
600 : : {
601 : : GFileAttributeValue *value;
602 : :
603 : 462 : g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
604 : 462 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
605 : :
606 : 462 : value = g_file_info_find_value_by_name (info, attribute);
607 : 462 : return value != NULL;
608 : : }
609 : :
610 : : /**
611 : : * g_file_info_has_namespace:
612 : : * @info: a #GFileInfo.
613 : : * @name_space: a file attribute namespace.
614 : : *
615 : : * Checks if a file info structure has an attribute in the
616 : : * specified @name_space.
617 : : *
618 : : * Returns: %TRUE if @info has an attribute in @name_space,
619 : : * %FALSE otherwise.
620 : : *
621 : : * Since: 2.22
622 : : **/
623 : : gboolean
624 : 1 : g_file_info_has_namespace (GFileInfo *info,
625 : : const char *name_space)
626 : : {
627 : : GFileAttribute *attrs;
628 : : guint32 ns_id;
629 : : guint i;
630 : :
631 : 1 : g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
632 : 1 : g_return_val_if_fail (name_space != NULL, FALSE);
633 : :
634 : 1 : ns_id = lookup_namespace (name_space);
635 : :
636 : 1 : attrs = (GFileAttribute *)info->attributes->data;
637 : 1 : for (i = 0; i < info->attributes->len; i++)
638 : : {
639 : 1 : if (GET_NS (attrs[i].attribute) == ns_id)
640 : 1 : return TRUE;
641 : : }
642 : :
643 : 0 : return FALSE;
644 : : }
645 : :
646 : : /**
647 : : * g_file_info_list_attributes:
648 : : * @info: a #GFileInfo.
649 : : * @name_space: (nullable): a file attribute key's namespace, or %NULL to list
650 : : * all attributes.
651 : : *
652 : : * Lists the file info structure's attributes.
653 : : *
654 : : * Returns: (nullable) (array zero-terminated=1) (transfer full): a
655 : : * null-terminated array of strings of all of the possible attribute
656 : : * types for the given @name_space, or %NULL on error.
657 : : **/
658 : : char **
659 : 39 : g_file_info_list_attributes (GFileInfo *info,
660 : : const char *name_space)
661 : : {
662 : : GPtrArray *names;
663 : : GFileAttribute *attrs;
664 : : guint32 attribute;
665 : 39 : guint32 ns_id = (name_space) ? lookup_namespace (name_space) : 0;
666 : : guint i;
667 : :
668 : 39 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
669 : :
670 : 39 : names = g_ptr_array_new ();
671 : 39 : attrs = (GFileAttribute *)info->attributes->data;
672 : 241 : for (i = 0; i < info->attributes->len; i++)
673 : : {
674 : 202 : attribute = attrs[i].attribute;
675 : 202 : if (ns_id == 0 || GET_NS (attribute) == ns_id)
676 : 404 : g_ptr_array_add (names, g_strdup (get_attribute_for_id (attribute)));
677 : : }
678 : :
679 : : /* NULL terminate */
680 : 39 : g_ptr_array_add (names, NULL);
681 : :
682 : 39 : return (char **)g_ptr_array_free (names, FALSE);
683 : : }
684 : :
685 : : /**
686 : : * g_file_info_get_attribute_type:
687 : : * @info: a #GFileInfo.
688 : : * @attribute: a file attribute key.
689 : : *
690 : : * Gets the attribute type for an attribute key.
691 : : *
692 : : * Returns: a #GFileAttributeType for the given @attribute, or
693 : : * %G_FILE_ATTRIBUTE_TYPE_INVALID if the key is not set.
694 : : **/
695 : : GFileAttributeType
696 : 2 : g_file_info_get_attribute_type (GFileInfo *info,
697 : : const char *attribute)
698 : : {
699 : : GFileAttributeValue *value;
700 : :
701 : 2 : g_return_val_if_fail (G_IS_FILE_INFO (info), G_FILE_ATTRIBUTE_TYPE_INVALID);
702 : 2 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', G_FILE_ATTRIBUTE_TYPE_INVALID);
703 : :
704 : 2 : value = g_file_info_find_value_by_name (info, attribute);
705 : 2 : if (value)
706 : 1 : return value->type;
707 : : else
708 : 1 : return G_FILE_ATTRIBUTE_TYPE_INVALID;
709 : : }
710 : :
711 : : static void
712 : 7 : g_file_info_remove_value (GFileInfo *info,
713 : : guint32 attr_id)
714 : : {
715 : : GFileAttribute *attrs;
716 : : guint i;
717 : :
718 : 7 : if (info->mask != NO_ATTRIBUTE_MASK &&
719 : 0 : !_g_file_attribute_matcher_matches_id (info->mask, attr_id))
720 : 0 : return;
721 : :
722 : 7 : i = g_file_info_find_place (info, attr_id);
723 : :
724 : 7 : attrs = (GFileAttribute *)info->attributes->data;
725 : 7 : if (i < info->attributes->len &&
726 : 5 : attrs[i].attribute == attr_id)
727 : : {
728 : 5 : _g_file_attribute_value_clear (&attrs[i].value);
729 : 5 : g_array_remove_index (info->attributes, i);
730 : : }
731 : : }
732 : :
733 : : /**
734 : : * g_file_info_remove_attribute:
735 : : * @info: a #GFileInfo.
736 : : * @attribute: a file attribute key.
737 : : *
738 : : * Removes all cases of @attribute from @info if it exists.
739 : : **/
740 : : void
741 : 1 : g_file_info_remove_attribute (GFileInfo *info,
742 : : const char *attribute)
743 : : {
744 : : guint32 attr_id;
745 : :
746 : 1 : g_return_if_fail (G_IS_FILE_INFO (info));
747 : 1 : g_return_if_fail (attribute != NULL && *attribute != '\0');
748 : :
749 : 1 : attr_id = lookup_attribute (attribute);
750 : :
751 : 1 : g_file_info_remove_value (info, attr_id);
752 : : }
753 : :
754 : : /**
755 : : * g_file_info_get_attribute_data:
756 : : * @info: a #GFileInfo
757 : : * @attribute: a file attribute key
758 : : * @type: (out) (optional): return location for the attribute type, or %NULL
759 : : * @value_pp: (out) (optional) (not nullable): return location for the
760 : : * attribute value, or %NULL; the attribute value will not be %NULL
761 : : * @status: (out) (optional): return location for the attribute status, or %NULL
762 : : *
763 : : * Gets the attribute type, value and status for an attribute key.
764 : : *
765 : : * Returns: %TRUE if @info has an attribute named @attribute,
766 : : * %FALSE otherwise.
767 : : */
768 : : gboolean
769 : 0 : g_file_info_get_attribute_data (GFileInfo *info,
770 : : const char *attribute,
771 : : GFileAttributeType *type,
772 : : gpointer *value_pp,
773 : : GFileAttributeStatus *status)
774 : : {
775 : : GFileAttributeValue *value;
776 : :
777 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
778 : 0 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
779 : :
780 : 0 : value = g_file_info_find_value_by_name (info, attribute);
781 : 0 : if (value == NULL)
782 : 0 : return FALSE;
783 : :
784 : 0 : if (status)
785 : 0 : *status = value->status;
786 : :
787 : 0 : if (type)
788 : 0 : *type = value->type;
789 : :
790 : 0 : if (value_pp)
791 : 0 : *value_pp = _g_file_attribute_value_peek_as_pointer (value);
792 : :
793 : 0 : return TRUE;
794 : : }
795 : :
796 : : /**
797 : : * g_file_info_get_attribute_status:
798 : : * @info: a #GFileInfo
799 : : * @attribute: a file attribute key
800 : : *
801 : : * Gets the attribute status for an attribute key.
802 : : *
803 : : * Returns: a #GFileAttributeStatus for the given @attribute, or
804 : : * %G_FILE_ATTRIBUTE_STATUS_UNSET if the key is invalid.
805 : : *
806 : : */
807 : : GFileAttributeStatus
808 : 1 : g_file_info_get_attribute_status (GFileInfo *info,
809 : : const char *attribute)
810 : : {
811 : : GFileAttributeValue *val;
812 : :
813 : 1 : g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
814 : 1 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
815 : :
816 : 1 : val = g_file_info_find_value_by_name (info, attribute);
817 : 1 : if (val)
818 : 1 : return val->status;
819 : :
820 : 0 : return G_FILE_ATTRIBUTE_STATUS_UNSET;
821 : : }
822 : :
823 : : /**
824 : : * g_file_info_set_attribute_status:
825 : : * @info: a #GFileInfo
826 : : * @attribute: a file attribute key
827 : : * @status: a #GFileAttributeStatus
828 : : *
829 : : * Sets the attribute status for an attribute key. This is only
830 : : * needed by external code that implement g_file_set_attributes_from_info()
831 : : * or similar functions.
832 : : *
833 : : * The attribute must exist in @info for this to work. Otherwise %FALSE
834 : : * is returned and @info is unchanged.
835 : : *
836 : : * Returns: %TRUE if the status was changed, %FALSE if the key was not set.
837 : : *
838 : : * Since: 2.22
839 : : */
840 : : gboolean
841 : 0 : g_file_info_set_attribute_status (GFileInfo *info,
842 : : const char *attribute,
843 : : GFileAttributeStatus status)
844 : : {
845 : : GFileAttributeValue *val;
846 : :
847 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
848 : 0 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
849 : :
850 : 0 : val = g_file_info_find_value_by_name (info, attribute);
851 : 0 : if (val)
852 : : {
853 : 0 : val->status = status;
854 : 0 : return TRUE;
855 : : }
856 : :
857 : 0 : return FALSE;
858 : : }
859 : :
860 : : GFileAttributeValue *
861 : 558 : _g_file_info_get_attribute_value (GFileInfo *info,
862 : : const char *attribute)
863 : :
864 : : {
865 : 558 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
866 : 558 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
867 : :
868 : 558 : return g_file_info_find_value_by_name (info, attribute);
869 : : }
870 : :
871 : : /**
872 : : * g_file_info_get_attribute_as_string:
873 : : * @info: a #GFileInfo.
874 : : * @attribute: a file attribute key.
875 : : *
876 : : * Gets the value of an attribute, formatted as a human readable string.
877 : : *
878 : : * This escapes things as needed to make the string valid UTF-8 and readable by
879 : : * humans. It’s not meant to be a machine readable or reversible escaping
880 : : * format.
881 : : *
882 : : * To format file name attributes of type
883 : : * [enum@Gio.FileAttributeType.BYTE_STRING] for output as UTF-8, use
884 : : * [func@GLib.filename_to_utf8] instead:
885 : : * ```c
886 : : * const char *trash_orig_path_byte_string;
887 : : * g_autofree char *trash_orig_path_utf8 = NULL;
888 : : *
889 : : * trash_orig_path_byte_string = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH);
890 : : * trash_orig_path_utf8 = g_filename_to_utf8 (trash_orig_path_byte_string, -1, NULL, NULL, NULL);
891 : : * if (trash_orig_path_utf8 != NULL)
892 : : * g_message ("Some larger UTF-8 string with filename embedded as %s", trash_orig_path_utf8);
893 : : * ```
894 : : *
895 : : * Returns: (nullable): a UTF-8 string associated with the given @attribute, or
896 : : * %NULL if the attribute wasn’t set.
897 : : * When you're done with the string it must be freed with g_free().
898 : : **/
899 : : char *
900 : 1 : g_file_info_get_attribute_as_string (GFileInfo *info,
901 : : const char *attribute)
902 : : {
903 : : GFileAttributeValue *val;
904 : 1 : val = _g_file_info_get_attribute_value (info, attribute);
905 : 1 : if (val)
906 : 1 : return _g_file_attribute_value_as_string (val);
907 : 0 : return NULL;
908 : : }
909 : :
910 : :
911 : : /**
912 : : * g_file_info_get_attribute_object:
913 : : * @info: a #GFileInfo.
914 : : * @attribute: a file attribute key.
915 : : *
916 : : * Gets the value of a #GObject attribute. If the attribute does
917 : : * not contain a #GObject, %NULL will be returned.
918 : : *
919 : : * Returns: (transfer none) (nullable): a #GObject associated with the given @attribute,
920 : : * or %NULL otherwise.
921 : : **/
922 : : GObject *
923 : 0 : g_file_info_get_attribute_object (GFileInfo *info,
924 : : const char *attribute)
925 : : {
926 : : GFileAttributeValue *value;
927 : :
928 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
929 : 0 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
930 : :
931 : 0 : value = g_file_info_find_value_by_name (info, attribute);
932 : 0 : return _g_file_attribute_value_get_object (value);
933 : : }
934 : :
935 : : /**
936 : : * g_file_info_get_attribute_string:
937 : : * @info: a #GFileInfo.
938 : : * @attribute: a file attribute key.
939 : : *
940 : : * Gets the value of a string attribute. If the attribute does
941 : : * not contain a string, %NULL will be returned.
942 : : *
943 : : * Returns: (nullable): the contents of the @attribute value as a UTF-8 string,
944 : : * or %NULL otherwise.
945 : : **/
946 : : const char *
947 : 60 : g_file_info_get_attribute_string (GFileInfo *info,
948 : : const char *attribute)
949 : : {
950 : : GFileAttributeValue *value;
951 : :
952 : 60 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
953 : 60 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
954 : :
955 : 60 : value = g_file_info_find_value_by_name (info, attribute);
956 : 60 : return _g_file_attribute_value_get_string (value);
957 : : }
958 : :
959 : : /**
960 : : * g_file_info_get_attribute_byte_string:
961 : : * @info: a #GFileInfo.
962 : : * @attribute: a file attribute key.
963 : : *
964 : : * Gets the value of a byte string attribute. If the attribute does
965 : : * not contain a byte string, %NULL will be returned.
966 : : *
967 : : * Returns: (nullable): the contents of the @attribute value as a byte string, or
968 : : * %NULL otherwise.
969 : : **/
970 : : const char *
971 : 37 : g_file_info_get_attribute_byte_string (GFileInfo *info,
972 : : const char *attribute)
973 : : {
974 : : GFileAttributeValue *value;
975 : :
976 : 37 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
977 : 37 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
978 : :
979 : 37 : value = g_file_info_find_value_by_name (info, attribute);
980 : 37 : return _g_file_attribute_value_get_byte_string (value);
981 : : }
982 : :
983 : : /**
984 : : * g_file_info_get_attribute_file_path:
985 : : * @info: a #GFileInfo.
986 : : * @attribute: a file attribute key.
987 : : *
988 : : * Gets the value of a byte string attribute as a file path.
989 : : *
990 : : * If the attribute does not contain a byte string, `NULL` will be returned.
991 : : *
992 : : * This function is meant to be used by language bindings that have specific
993 : : * handling for Unix paths.
994 : : *
995 : : * Returns: (type filename) (nullable): the contents of the @attribute value as
996 : : * a file path, or %NULL otherwise.
997 : : *
998 : : * Since: 2.78
999 : : **/
1000 : : const char *
1001 : 4 : g_file_info_get_attribute_file_path (GFileInfo *info,
1002 : : const char *attribute)
1003 : : {
1004 : 4 : return g_file_info_get_attribute_byte_string (info, attribute);
1005 : : }
1006 : :
1007 : : /**
1008 : : * g_file_info_get_attribute_stringv:
1009 : : * @info: a #GFileInfo.
1010 : : * @attribute: a file attribute key.
1011 : : *
1012 : : * Gets the value of a stringv attribute. If the attribute does
1013 : : * not contain a stringv, %NULL will be returned.
1014 : : *
1015 : : * Returns: (transfer none) (nullable): the contents of the @attribute value as a stringv,
1016 : : * or %NULL otherwise. Do not free. These returned strings are UTF-8.
1017 : : *
1018 : : * Since: 2.22
1019 : : **/
1020 : : char **
1021 : 0 : g_file_info_get_attribute_stringv (GFileInfo *info,
1022 : : const char *attribute)
1023 : : {
1024 : : GFileAttributeValue *value;
1025 : :
1026 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1027 : 0 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
1028 : :
1029 : 0 : value = g_file_info_find_value_by_name (info, attribute);
1030 : 0 : return _g_file_attribute_value_get_stringv (value);
1031 : : }
1032 : :
1033 : : /**
1034 : : * g_file_info_get_attribute_boolean:
1035 : : * @info: a #GFileInfo.
1036 : : * @attribute: a file attribute key.
1037 : : *
1038 : : * Gets the value of a boolean attribute. If the attribute does not
1039 : : * contain a boolean value, %FALSE will be returned.
1040 : : *
1041 : : * Returns: the boolean value contained within the attribute.
1042 : : **/
1043 : : gboolean
1044 : 204 : g_file_info_get_attribute_boolean (GFileInfo *info,
1045 : : const char *attribute)
1046 : : {
1047 : : GFileAttributeValue *value;
1048 : :
1049 : 204 : g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1050 : 204 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
1051 : :
1052 : 204 : value = g_file_info_find_value_by_name (info, attribute);
1053 : 204 : return _g_file_attribute_value_get_boolean (value);
1054 : : }
1055 : :
1056 : : /**
1057 : : * g_file_info_get_attribute_uint32:
1058 : : * @info: a #GFileInfo.
1059 : : * @attribute: a file attribute key.
1060 : : *
1061 : : * Gets an unsigned 32-bit integer contained within the attribute. If the
1062 : : * attribute does not contain an unsigned 32-bit integer, or is invalid,
1063 : : * 0 will be returned.
1064 : : *
1065 : : * Returns: an unsigned 32-bit integer from the attribute.
1066 : : **/
1067 : : guint32
1068 : 263 : g_file_info_get_attribute_uint32 (GFileInfo *info,
1069 : : const char *attribute)
1070 : : {
1071 : : GFileAttributeValue *value;
1072 : :
1073 : 263 : g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1074 : 263 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
1075 : :
1076 : 263 : value = g_file_info_find_value_by_name (info, attribute);
1077 : 263 : return _g_file_attribute_value_get_uint32 (value);
1078 : : }
1079 : :
1080 : : /**
1081 : : * g_file_info_get_attribute_int32:
1082 : : * @info: a #GFileInfo.
1083 : : * @attribute: a file attribute key.
1084 : : *
1085 : : * Gets a signed 32-bit integer contained within the attribute. If the
1086 : : * attribute does not contain a signed 32-bit integer, or is invalid,
1087 : : * 0 will be returned.
1088 : : *
1089 : : * Returns: a signed 32-bit integer from the attribute.
1090 : : **/
1091 : : gint32
1092 : 0 : g_file_info_get_attribute_int32 (GFileInfo *info,
1093 : : const char *attribute)
1094 : : {
1095 : : GFileAttributeValue *value;
1096 : :
1097 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1098 : 0 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
1099 : :
1100 : 0 : value = g_file_info_find_value_by_name (info, attribute);
1101 : 0 : return _g_file_attribute_value_get_int32 (value);
1102 : : }
1103 : :
1104 : : /**
1105 : : * g_file_info_get_attribute_uint64:
1106 : : * @info: a #GFileInfo.
1107 : : * @attribute: a file attribute key.
1108 : : *
1109 : : * Gets a unsigned 64-bit integer contained within the attribute. If the
1110 : : * attribute does not contain an unsigned 64-bit integer, or is invalid,
1111 : : * 0 will be returned.
1112 : : *
1113 : : * Returns: a unsigned 64-bit integer from the attribute.
1114 : : **/
1115 : : guint64
1116 : 7 : g_file_info_get_attribute_uint64 (GFileInfo *info,
1117 : : const char *attribute)
1118 : : {
1119 : : GFileAttributeValue *value;
1120 : :
1121 : 7 : g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1122 : 7 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
1123 : :
1124 : 7 : value = g_file_info_find_value_by_name (info, attribute);
1125 : 7 : return _g_file_attribute_value_get_uint64 (value);
1126 : : }
1127 : :
1128 : : /**
1129 : : * g_file_info_get_attribute_int64:
1130 : : * @info: a #GFileInfo.
1131 : : * @attribute: a file attribute key.
1132 : : *
1133 : : * Gets a signed 64-bit integer contained within the attribute. If the
1134 : : * attribute does not contain a signed 64-bit integer, or is invalid,
1135 : : * 0 will be returned.
1136 : : *
1137 : : * Returns: a signed 64-bit integer from the attribute.
1138 : : **/
1139 : : gint64
1140 : 0 : g_file_info_get_attribute_int64 (GFileInfo *info,
1141 : : const char *attribute)
1142 : : {
1143 : : GFileAttributeValue *value;
1144 : :
1145 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1146 : 0 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
1147 : :
1148 : 0 : value = g_file_info_find_value_by_name (info, attribute);
1149 : 0 : return _g_file_attribute_value_get_int64 (value);
1150 : : }
1151 : :
1152 : : static GFileAttributeValue *
1153 : 23244 : g_file_info_create_value (GFileInfo *info,
1154 : : guint32 attr_id)
1155 : : {
1156 : : GFileAttribute *attrs;
1157 : : guint i;
1158 : :
1159 : 45423 : if (info->mask != NO_ATTRIBUTE_MASK &&
1160 : 22179 : !_g_file_attribute_matcher_matches_id (info->mask, attr_id))
1161 : 16939 : return NULL;
1162 : :
1163 : 6305 : i = g_file_info_find_place (info, attr_id);
1164 : :
1165 : 6305 : attrs = (GFileAttribute *)info->attributes->data;
1166 : 6305 : if (i < info->attributes->len &&
1167 : 3476 : attrs[i].attribute == attr_id)
1168 : 294 : return &attrs[i].value;
1169 : : else
1170 : : {
1171 : 6011 : GFileAttribute attr = { 0 };
1172 : 6011 : attr.attribute = attr_id;
1173 : 6011 : g_array_insert_val (info->attributes, i, attr);
1174 : :
1175 : 6011 : attrs = (GFileAttribute *)info->attributes->data;
1176 : 6011 : return &attrs[i].value;
1177 : : }
1178 : : }
1179 : :
1180 : : void
1181 : 0 : _g_file_info_set_attribute_by_id (GFileInfo *info,
1182 : : guint32 attribute,
1183 : : GFileAttributeType type,
1184 : : gpointer value_p)
1185 : : {
1186 : : GFileAttributeValue *value;
1187 : :
1188 : 0 : value = g_file_info_create_value (info, attribute);
1189 : :
1190 : 0 : if (value)
1191 : 0 : _g_file_attribute_value_set_from_pointer (value, type, value_p, TRUE);
1192 : 0 : }
1193 : :
1194 : : /**
1195 : : * g_file_info_set_attribute:
1196 : : * @info: a #GFileInfo.
1197 : : * @attribute: a file attribute key.
1198 : : * @type: a #GFileAttributeType
1199 : : * @value_p: (not nullable): pointer to the value
1200 : : *
1201 : : * Sets the @attribute to contain the given value, if possible. To unset the
1202 : : * attribute, use %G_FILE_ATTRIBUTE_TYPE_INVALID for @type.
1203 : : **/
1204 : : void
1205 : 0 : g_file_info_set_attribute (GFileInfo *info,
1206 : : const char *attribute,
1207 : : GFileAttributeType type,
1208 : : gpointer value_p)
1209 : : {
1210 : 0 : g_return_if_fail (G_IS_FILE_INFO (info));
1211 : 0 : g_return_if_fail (attribute != NULL && *attribute != '\0');
1212 : :
1213 : 0 : _g_file_info_set_attribute_by_id (info, lookup_attribute (attribute), type, value_p);
1214 : : }
1215 : :
1216 : : void
1217 : 0 : _g_file_info_set_attribute_object_by_id (GFileInfo *info,
1218 : : guint32 attribute,
1219 : : GObject *attr_value)
1220 : : {
1221 : : GFileAttributeValue *value;
1222 : :
1223 : 0 : value = g_file_info_create_value (info, attribute);
1224 : 0 : if (value)
1225 : 0 : _g_file_attribute_value_set_object (value, attr_value);
1226 : 0 : }
1227 : :
1228 : : /**
1229 : : * g_file_info_set_attribute_object:
1230 : : * @info: a #GFileInfo.
1231 : : * @attribute: a file attribute key.
1232 : : * @attr_value: a #GObject.
1233 : : *
1234 : : * Sets the @attribute to contain the given @attr_value,
1235 : : * if possible.
1236 : : **/
1237 : : void
1238 : 0 : g_file_info_set_attribute_object (GFileInfo *info,
1239 : : const char *attribute,
1240 : : GObject *attr_value)
1241 : : {
1242 : 0 : g_return_if_fail (G_IS_FILE_INFO (info));
1243 : 0 : g_return_if_fail (attribute != NULL && *attribute != '\0');
1244 : 0 : g_return_if_fail (G_IS_OBJECT (attr_value));
1245 : :
1246 : 0 : _g_file_info_set_attribute_object_by_id (info,
1247 : : lookup_attribute (attribute),
1248 : : attr_value);
1249 : : }
1250 : :
1251 : : void
1252 : 0 : _g_file_info_set_attribute_stringv_by_id (GFileInfo *info,
1253 : : guint32 attribute,
1254 : : char **attr_value)
1255 : : {
1256 : : GFileAttributeValue *value;
1257 : :
1258 : 0 : value = g_file_info_create_value (info, attribute);
1259 : 0 : if (value)
1260 : 0 : _g_file_attribute_value_set_stringv (value, attr_value);
1261 : 0 : }
1262 : :
1263 : : /**
1264 : : * g_file_info_set_attribute_stringv:
1265 : : * @info: a #GFileInfo.
1266 : : * @attribute: a file attribute key
1267 : : * @attr_value: (array zero-terminated=1) (element-type utf8): a %NULL
1268 : : * terminated array of UTF-8 strings.
1269 : : *
1270 : : * Sets the @attribute to contain the given @attr_value,
1271 : : * if possible.
1272 : : *
1273 : : * Sinze: 2.22
1274 : : **/
1275 : : void
1276 : 0 : g_file_info_set_attribute_stringv (GFileInfo *info,
1277 : : const char *attribute,
1278 : : char **attr_value)
1279 : : {
1280 : 0 : g_return_if_fail (G_IS_FILE_INFO (info));
1281 : 0 : g_return_if_fail (attribute != NULL && *attribute != '\0');
1282 : 0 : g_return_if_fail (attr_value != NULL);
1283 : :
1284 : 0 : _g_file_info_set_attribute_stringv_by_id (info,
1285 : : lookup_attribute (attribute),
1286 : : attr_value);
1287 : : }
1288 : :
1289 : : void
1290 : 773 : _g_file_info_set_attribute_string_by_id (GFileInfo *info,
1291 : : guint32 attribute,
1292 : : const char *attr_value)
1293 : : {
1294 : : GFileAttributeValue *value;
1295 : :
1296 : 773 : value = g_file_info_create_value (info, attribute);
1297 : 773 : if (value)
1298 : 773 : _g_file_attribute_value_set_string (value, attr_value);
1299 : 773 : }
1300 : :
1301 : : /**
1302 : : * g_file_info_set_attribute_string:
1303 : : * @info: a #GFileInfo.
1304 : : * @attribute: a file attribute key.
1305 : : * @attr_value: a UTF-8 string.
1306 : : *
1307 : : * Sets the @attribute to contain the given @attr_value,
1308 : : * if possible.
1309 : : **/
1310 : : void
1311 : 98 : g_file_info_set_attribute_string (GFileInfo *info,
1312 : : const char *attribute,
1313 : : const char *attr_value)
1314 : : {
1315 : 98 : g_return_if_fail (G_IS_FILE_INFO (info));
1316 : 98 : g_return_if_fail (attribute != NULL && *attribute != '\0');
1317 : 98 : g_return_if_fail (attr_value != NULL);
1318 : :
1319 : 98 : _g_file_info_set_attribute_string_by_id (info,
1320 : : lookup_attribute (attribute),
1321 : : attr_value);
1322 : : }
1323 : :
1324 : : void
1325 : 56 : _g_file_info_set_attribute_byte_string_by_id (GFileInfo *info,
1326 : : guint32 attribute,
1327 : : const char *attr_value)
1328 : : {
1329 : : GFileAttributeValue *value;
1330 : :
1331 : 56 : value = g_file_info_create_value (info, attribute);
1332 : 56 : if (value)
1333 : 56 : _g_file_attribute_value_set_byte_string (value, attr_value);
1334 : 56 : }
1335 : :
1336 : : /**
1337 : : * g_file_info_set_attribute_byte_string:
1338 : : * @info: a #GFileInfo.
1339 : : * @attribute: a file attribute key.
1340 : : * @attr_value: a byte string.
1341 : : *
1342 : : * Sets the @attribute to contain the given @attr_value,
1343 : : * if possible.
1344 : : **/
1345 : : void
1346 : 5 : g_file_info_set_attribute_byte_string (GFileInfo *info,
1347 : : const char *attribute,
1348 : : const char *attr_value)
1349 : : {
1350 : 5 : g_return_if_fail (G_IS_FILE_INFO (info));
1351 : 5 : g_return_if_fail (attribute != NULL && *attribute != '\0');
1352 : 5 : g_return_if_fail (attr_value != NULL);
1353 : :
1354 : 5 : _g_file_info_set_attribute_byte_string_by_id (info,
1355 : : lookup_attribute (attribute),
1356 : : attr_value);
1357 : : }
1358 : :
1359 : : /**
1360 : : * g_file_info_set_attribute_file_path:
1361 : : * @info: a #GFileInfo.
1362 : : * @attribute: a file attribute key.
1363 : : * @attr_value: (type filename): a file path.
1364 : : *
1365 : : * Sets the @attribute to contain the given @attr_value,
1366 : : * if possible.
1367 : : *
1368 : : * This function is meant to be used by language bindings that have specific
1369 : : * handling for Unix paths.
1370 : : *
1371 : : * Since: 2.78
1372 : : **/
1373 : : void
1374 : 2 : g_file_info_set_attribute_file_path (GFileInfo *info,
1375 : : const char *attribute,
1376 : : const char *attr_value)
1377 : : {
1378 : 2 : g_file_info_set_attribute_byte_string (info, attribute, attr_value);
1379 : 2 : }
1380 : :
1381 : : void
1382 : 1641 : _g_file_info_set_attribute_boolean_by_id (GFileInfo *info,
1383 : : guint32 attribute,
1384 : : gboolean attr_value)
1385 : : {
1386 : : GFileAttributeValue *value;
1387 : :
1388 : 1641 : value = g_file_info_create_value (info, attribute);
1389 : 1641 : if (value)
1390 : 1050 : _g_file_attribute_value_set_boolean (value, attr_value);
1391 : 1641 : }
1392 : :
1393 : : /**
1394 : : * g_file_info_set_attribute_boolean:
1395 : : * @info: a #GFileInfo.
1396 : : * @attribute: a file attribute key.
1397 : : * @attr_value: a boolean value.
1398 : : *
1399 : : * Sets the @attribute to contain the given @attr_value,
1400 : : * if possible.
1401 : : **/
1402 : : void
1403 : 1 : g_file_info_set_attribute_boolean (GFileInfo *info,
1404 : : const char *attribute,
1405 : : gboolean attr_value)
1406 : : {
1407 : 1 : g_return_if_fail (G_IS_FILE_INFO (info));
1408 : 1 : g_return_if_fail (attribute != NULL && *attribute != '\0');
1409 : :
1410 : 1 : _g_file_info_set_attribute_boolean_by_id (info,
1411 : : lookup_attribute (attribute),
1412 : : attr_value);
1413 : : }
1414 : :
1415 : : void
1416 : 11001 : _g_file_info_set_attribute_uint32_by_id (GFileInfo *info,
1417 : : guint32 attribute,
1418 : : guint32 attr_value)
1419 : : {
1420 : : GFileAttributeValue *value;
1421 : :
1422 : 11001 : value = g_file_info_create_value (info, attribute);
1423 : 11001 : if (value)
1424 : 1550 : _g_file_attribute_value_set_uint32 (value, attr_value);
1425 : 11001 : }
1426 : :
1427 : : /**
1428 : : * g_file_info_set_attribute_uint32:
1429 : : * @info: a #GFileInfo.
1430 : : * @attribute: a file attribute key.
1431 : : * @attr_value: an unsigned 32-bit integer.
1432 : : *
1433 : : * Sets the @attribute to contain the given @attr_value,
1434 : : * if possible.
1435 : : **/
1436 : : void
1437 : 8 : g_file_info_set_attribute_uint32 (GFileInfo *info,
1438 : : const char *attribute,
1439 : : guint32 attr_value)
1440 : : {
1441 : 8 : g_return_if_fail (G_IS_FILE_INFO (info));
1442 : 8 : g_return_if_fail (attribute != NULL && *attribute != '\0');
1443 : :
1444 : 8 : _g_file_info_set_attribute_uint32_by_id (info,
1445 : : lookup_attribute (attribute),
1446 : : attr_value);
1447 : : }
1448 : :
1449 : : void
1450 : 1 : _g_file_info_set_attribute_int32_by_id (GFileInfo *info,
1451 : : guint32 attribute,
1452 : : gint32 attr_value)
1453 : : {
1454 : : GFileAttributeValue *value;
1455 : :
1456 : 1 : value = g_file_info_create_value (info, attribute);
1457 : 1 : if (value)
1458 : 1 : _g_file_attribute_value_set_int32 (value, attr_value);
1459 : 1 : }
1460 : :
1461 : : /**
1462 : : * g_file_info_set_attribute_int32:
1463 : : * @info: a #GFileInfo.
1464 : : * @attribute: a file attribute key.
1465 : : * @attr_value: a signed 32-bit integer
1466 : : *
1467 : : * Sets the @attribute to contain the given @attr_value,
1468 : : * if possible.
1469 : : **/
1470 : : void
1471 : 1 : g_file_info_set_attribute_int32 (GFileInfo *info,
1472 : : const char *attribute,
1473 : : gint32 attr_value)
1474 : : {
1475 : 1 : g_return_if_fail (G_IS_FILE_INFO (info));
1476 : 1 : g_return_if_fail (attribute != NULL && *attribute != '\0');
1477 : :
1478 : 1 : _g_file_info_set_attribute_int32_by_id (info,
1479 : : lookup_attribute (attribute),
1480 : : attr_value);
1481 : : }
1482 : :
1483 : : void
1484 : 5135 : _g_file_info_set_attribute_uint64_by_id (GFileInfo *info,
1485 : : guint32 attribute,
1486 : : guint64 attr_value)
1487 : : {
1488 : : GFileAttributeValue *value;
1489 : :
1490 : 5135 : value = g_file_info_create_value (info, attribute);
1491 : 5135 : if (value)
1492 : 617 : _g_file_attribute_value_set_uint64 (value, attr_value);
1493 : 5135 : }
1494 : :
1495 : : /**
1496 : : * g_file_info_set_attribute_uint64:
1497 : : * @info: a #GFileInfo.
1498 : : * @attribute: a file attribute key.
1499 : : * @attr_value: an unsigned 64-bit integer.
1500 : : *
1501 : : * Sets the @attribute to contain the given @attr_value,
1502 : : * if possible.
1503 : : **/
1504 : : void
1505 : 5 : g_file_info_set_attribute_uint64 (GFileInfo *info,
1506 : : const char *attribute,
1507 : : guint64 attr_value)
1508 : : {
1509 : 5 : g_return_if_fail (G_IS_FILE_INFO (info));
1510 : 5 : g_return_if_fail (attribute != NULL && *attribute != '\0');
1511 : :
1512 : 5 : _g_file_info_set_attribute_uint64_by_id (info,
1513 : : lookup_attribute (attribute),
1514 : : attr_value);
1515 : : }
1516 : :
1517 : : void
1518 : 0 : _g_file_info_set_attribute_int64_by_id (GFileInfo *info,
1519 : : guint32 attribute,
1520 : : gint64 attr_value)
1521 : : {
1522 : : GFileAttributeValue *value;
1523 : :
1524 : 0 : value = g_file_info_create_value (info, attribute);
1525 : 0 : if (value)
1526 : 0 : _g_file_attribute_value_set_int64 (value, attr_value);
1527 : 0 : }
1528 : :
1529 : : /**
1530 : : * g_file_info_set_attribute_int64:
1531 : : * @info: a #GFileInfo.
1532 : : * @attribute: attribute name to set.
1533 : : * @attr_value: int64 value to set attribute to.
1534 : : *
1535 : : * Sets the @attribute to contain the given @attr_value,
1536 : : * if possible.
1537 : : *
1538 : : **/
1539 : : void
1540 : 0 : g_file_info_set_attribute_int64 (GFileInfo *info,
1541 : : const char *attribute,
1542 : : gint64 attr_value)
1543 : : {
1544 : 0 : g_return_if_fail (G_IS_FILE_INFO (info));
1545 : 0 : g_return_if_fail (attribute != NULL && *attribute != '\0');
1546 : :
1547 : 0 : _g_file_info_set_attribute_int64_by_id (info,
1548 : : lookup_attribute (attribute),
1549 : : attr_value);
1550 : : }
1551 : :
1552 : : /* Helper getters */
1553 : : #define get_required_attribute(value_ptr, info, attribute_name, error_value) \
1554 : : G_STMT_START { \
1555 : : static guint32 attr = 0; \
1556 : : \
1557 : : if (attr == 0) \
1558 : : attr = lookup_attribute (attribute_name); \
1559 : : \
1560 : : *value_ptr = g_file_info_find_value (info, attr); \
1561 : : if (G_UNLIKELY (*value_ptr == NULL)) \
1562 : : { \
1563 : : g_critical ("GFileInfo created without " attribute_name); \
1564 : : g_return_val_if_reached (error_value); \
1565 : : } \
1566 : : } G_STMT_END
1567 : :
1568 : : /**
1569 : : * g_file_info_get_deletion_date:
1570 : : * @info: a #GFileInfo.
1571 : : *
1572 : : * Returns the #GDateTime representing the deletion date of the file, as
1573 : : * available in %G_FILE_ATTRIBUTE_TRASH_DELETION_DATE. If the
1574 : : * %G_FILE_ATTRIBUTE_TRASH_DELETION_DATE attribute is unset, %NULL is returned.
1575 : : *
1576 : : * Returns: (nullable): a #GDateTime, or %NULL.
1577 : : *
1578 : : * Since: 2.36
1579 : : **/
1580 : : GDateTime *
1581 : 0 : g_file_info_get_deletion_date (GFileInfo *info)
1582 : : {
1583 : : static guint32 attr = 0;
1584 : : GFileAttributeValue *value;
1585 : : const char *date_str;
1586 : 0 : GTimeZone *local_tz = NULL;
1587 : 0 : GDateTime *dt = NULL;
1588 : :
1589 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1590 : :
1591 : 0 : if (attr == 0)
1592 : 0 : attr = lookup_attribute (G_FILE_ATTRIBUTE_TRASH_DELETION_DATE);
1593 : :
1594 : 0 : value = g_file_info_find_value (info, attr);
1595 : 0 : date_str = _g_file_attribute_value_get_string (value);
1596 : 0 : if (!date_str)
1597 : 0 : return NULL;
1598 : :
1599 : 0 : local_tz = g_time_zone_new_local ();
1600 : 0 : dt = g_date_time_new_from_iso8601 (date_str, local_tz);
1601 : 0 : g_time_zone_unref (local_tz);
1602 : :
1603 : 0 : return g_steal_pointer (&dt);
1604 : : }
1605 : :
1606 : : /**
1607 : : * g_file_info_get_file_type:
1608 : : * @info: a #GFileInfo.
1609 : : *
1610 : : * Gets a file's type (whether it is a regular file, symlink, etc).
1611 : : * This is different from the file's content type, see g_file_info_get_content_type().
1612 : : *
1613 : : * It is an error to call this if the #GFileInfo does not contain
1614 : : * %G_FILE_ATTRIBUTE_STANDARD_TYPE.
1615 : : *
1616 : : * Returns: a #GFileType for the given file.
1617 : : **/
1618 : : GFileType
1619 : 483 : g_file_info_get_file_type (GFileInfo *info)
1620 : : {
1621 : : GFileAttributeValue *value;
1622 : :
1623 : 483 : g_return_val_if_fail (G_IS_FILE_INFO (info), G_FILE_TYPE_UNKNOWN);
1624 : :
1625 : 483 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_TYPE_UNKNOWN);
1626 : 483 : return (GFileType)_g_file_attribute_value_get_uint32 (value);
1627 : : }
1628 : :
1629 : : /**
1630 : : * g_file_info_get_is_hidden:
1631 : : * @info: a #GFileInfo.
1632 : : *
1633 : : * Checks if a file is hidden.
1634 : : *
1635 : : * It is an error to call this if the #GFileInfo does not contain
1636 : : * %G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN.
1637 : : *
1638 : : * Returns: %TRUE if the file is a hidden file, %FALSE otherwise.
1639 : : **/
1640 : : gboolean
1641 : 0 : g_file_info_get_is_hidden (GFileInfo *info)
1642 : : {
1643 : : GFileAttributeValue *value;
1644 : :
1645 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1646 : :
1647 : 0 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN, FALSE);
1648 : 0 : return _g_file_attribute_value_get_boolean (value);
1649 : : }
1650 : :
1651 : : /**
1652 : : * g_file_info_get_is_backup:
1653 : : * @info: a #GFileInfo.
1654 : : *
1655 : : * Checks if a file is a backup file.
1656 : : *
1657 : : * It is an error to call this if the #GFileInfo does not contain
1658 : : * %G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP.
1659 : : *
1660 : : * Returns: %TRUE if file is a backup file, %FALSE otherwise.
1661 : : **/
1662 : : gboolean
1663 : 0 : g_file_info_get_is_backup (GFileInfo *info)
1664 : : {
1665 : : GFileAttributeValue *value;
1666 : :
1667 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1668 : :
1669 : 0 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP, FALSE);
1670 : 0 : return _g_file_attribute_value_get_boolean (value);
1671 : : }
1672 : :
1673 : : /**
1674 : : * g_file_info_get_is_symlink:
1675 : : * @info: a #GFileInfo.
1676 : : *
1677 : : * Checks if a file is a symlink.
1678 : : *
1679 : : * It is an error to call this if the #GFileInfo does not contain
1680 : : * %G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK.
1681 : : *
1682 : : * Returns: %TRUE if the given @info is a symlink.
1683 : : **/
1684 : : gboolean
1685 : 43 : g_file_info_get_is_symlink (GFileInfo *info)
1686 : : {
1687 : : GFileAttributeValue *value;
1688 : :
1689 : 43 : g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1690 : :
1691 : 43 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK, FALSE);
1692 : 43 : return _g_file_attribute_value_get_boolean (value);
1693 : : }
1694 : :
1695 : : /**
1696 : : * g_file_info_get_name:
1697 : : * @info: a #GFileInfo.
1698 : : *
1699 : : * Gets the name for a file. This is guaranteed to always be set.
1700 : : *
1701 : : * It is an error to call this if the #GFileInfo does not contain
1702 : : * %G_FILE_ATTRIBUTE_STANDARD_NAME.
1703 : : *
1704 : : * Returns: (type filename) (not nullable): a string containing the file name.
1705 : : **/
1706 : : const char *
1707 : 224 : g_file_info_get_name (GFileInfo *info)
1708 : : {
1709 : : GFileAttributeValue *value;
1710 : :
1711 : 224 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1712 : :
1713 : 224 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_NAME, NULL);
1714 : 224 : return _g_file_attribute_value_get_byte_string (value);
1715 : : }
1716 : :
1717 : : /**
1718 : : * g_file_info_get_display_name:
1719 : : * @info: a #GFileInfo.
1720 : : *
1721 : : * Gets a display name for a file. This is guaranteed to always be set.
1722 : : *
1723 : : * It is an error to call this if the #GFileInfo does not contain
1724 : : * %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME.
1725 : : *
1726 : : * Returns: (not nullable): a string containing the display name.
1727 : : **/
1728 : : const char *
1729 : 100 : g_file_info_get_display_name (GFileInfo *info)
1730 : : {
1731 : : GFileAttributeValue *value;
1732 : :
1733 : 100 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1734 : :
1735 : 100 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, NULL);
1736 : 100 : return _g_file_attribute_value_get_string (value);
1737 : : }
1738 : :
1739 : : /**
1740 : : * g_file_info_get_edit_name:
1741 : : * @info: a #GFileInfo.
1742 : : *
1743 : : * Gets the edit name for a file.
1744 : : *
1745 : : * It is an error to call this if the #GFileInfo does not contain
1746 : : * %G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME.
1747 : : *
1748 : : * Returns: a string containing the edit name.
1749 : : **/
1750 : : const char *
1751 : 42 : g_file_info_get_edit_name (GFileInfo *info)
1752 : : {
1753 : : GFileAttributeValue *value;
1754 : :
1755 : 42 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1756 : :
1757 : 42 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME, NULL);
1758 : 42 : return _g_file_attribute_value_get_string (value);
1759 : : }
1760 : :
1761 : : /**
1762 : : * g_file_info_get_icon:
1763 : : * @info: a #GFileInfo.
1764 : : *
1765 : : * Gets the icon for a file.
1766 : : *
1767 : : * It is an error to call this if the #GFileInfo does not contain
1768 : : * %G_FILE_ATTRIBUTE_STANDARD_ICON.
1769 : : *
1770 : : * Returns: (nullable) (transfer none): #GIcon for the given @info.
1771 : : **/
1772 : : GIcon *
1773 : 0 : g_file_info_get_icon (GFileInfo *info)
1774 : : {
1775 : : GFileAttributeValue *value;
1776 : : GObject *obj;
1777 : :
1778 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1779 : :
1780 : 0 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_ICON, NULL);
1781 : :
1782 : 0 : obj = _g_file_attribute_value_get_object (value);
1783 : 0 : if (G_IS_ICON (obj))
1784 : 0 : return G_ICON (obj);
1785 : 0 : return NULL;
1786 : : }
1787 : :
1788 : : /**
1789 : : * g_file_info_get_symbolic_icon:
1790 : : * @info: a #GFileInfo.
1791 : : *
1792 : : * Gets the symbolic icon for a file.
1793 : : *
1794 : : * It is an error to call this if the #GFileInfo does not contain
1795 : : * %G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON.
1796 : : *
1797 : : * Returns: (nullable) (transfer none): #GIcon for the given @info.
1798 : : *
1799 : : * Since: 2.34
1800 : : **/
1801 : : GIcon *
1802 : 0 : g_file_info_get_symbolic_icon (GFileInfo *info)
1803 : : {
1804 : : GFileAttributeValue *value;
1805 : : GObject *obj;
1806 : :
1807 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1808 : :
1809 : 0 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON, NULL);
1810 : :
1811 : 0 : obj = _g_file_attribute_value_get_object (value);
1812 : 0 : if (G_IS_ICON (obj))
1813 : 0 : return G_ICON (obj);
1814 : 0 : return NULL;
1815 : : }
1816 : :
1817 : : /**
1818 : : * g_file_info_get_content_type:
1819 : : * @info: a #GFileInfo.
1820 : : *
1821 : : * Gets the file's content type.
1822 : : *
1823 : : * It is an error to call this if the #GFileInfo does not contain
1824 : : * %G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE.
1825 : : *
1826 : : * Returns: (nullable): a string containing the file's content type,
1827 : : * or %NULL if unknown.
1828 : : **/
1829 : : const char *
1830 : 8 : g_file_info_get_content_type (GFileInfo *info)
1831 : : {
1832 : : GFileAttributeValue *value;
1833 : :
1834 : 8 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1835 : :
1836 : 8 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, NULL);
1837 : 8 : return _g_file_attribute_value_get_string (value);
1838 : : }
1839 : :
1840 : : /**
1841 : : * g_file_info_get_size:
1842 : : * @info: a #GFileInfo.
1843 : : *
1844 : : * Gets the file's size (in bytes). The size is retrieved through the value of
1845 : : * the %G_FILE_ATTRIBUTE_STANDARD_SIZE attribute and is converted
1846 : : * from #guint64 to #goffset before returning the result.
1847 : : *
1848 : : * It is an error to call this if the #GFileInfo does not contain
1849 : : * %G_FILE_ATTRIBUTE_STANDARD_SIZE.
1850 : : *
1851 : : * Returns: a #goffset containing the file's size (in bytes).
1852 : : **/
1853 : : goffset
1854 : 187 : g_file_info_get_size (GFileInfo *info)
1855 : : {
1856 : : GFileAttributeValue *value;
1857 : :
1858 : 187 : g_return_val_if_fail (G_IS_FILE_INFO (info), (goffset) 0);
1859 : :
1860 : 187 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SIZE, (goffset) 0);
1861 : 187 : return (goffset) _g_file_attribute_value_get_uint64 (value);
1862 : : }
1863 : :
1864 : : /**
1865 : : * g_file_info_get_modification_time:
1866 : : * @info: a #GFileInfo.
1867 : : * @result: (out caller-allocates): a #GTimeVal.
1868 : : *
1869 : : * Gets the modification time of the current @info and sets it
1870 : : * in @result.
1871 : : *
1872 : : * It is an error to call this if the #GFileInfo does not contain
1873 : : * %G_FILE_ATTRIBUTE_TIME_MODIFIED. If %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC is
1874 : : * provided it will be used too.
1875 : : *
1876 : : * Deprecated: 2.62: Use g_file_info_get_modification_date_time() instead, as
1877 : : * #GTimeVal is deprecated due to the year 2038 problem.
1878 : : **/
1879 : : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1880 : : void
1881 : 0 : g_file_info_get_modification_time (GFileInfo *info,
1882 : : GTimeVal *result)
1883 : : {
1884 : : static guint32 attr_mtime = 0, attr_mtime_usec;
1885 : : GFileAttributeValue *value;
1886 : :
1887 : 0 : g_return_if_fail (G_IS_FILE_INFO (info));
1888 : 0 : g_return_if_fail (result != NULL);
1889 : :
1890 : 0 : if (attr_mtime == 0)
1891 : : {
1892 : 0 : attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1893 : 0 : attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1894 : : }
1895 : :
1896 : 0 : value = g_file_info_find_value (info, attr_mtime);
1897 : :
1898 : 0 : if (G_UNLIKELY (value == NULL))
1899 : : {
1900 : 0 : g_critical ("GFileInfo created without " G_FILE_ATTRIBUTE_TIME_MODIFIED);
1901 : 0 : result->tv_sec = result->tv_usec = 0;
1902 : : g_return_if_reached ();
1903 : : }
1904 : :
1905 : 0 : result->tv_sec = _g_file_attribute_value_get_uint64 (value);
1906 : 0 : value = g_file_info_find_value (info, attr_mtime_usec);
1907 : 0 : result->tv_usec = _g_file_attribute_value_get_uint32 (value);
1908 : : }
1909 : : G_GNUC_END_IGNORE_DEPRECATIONS
1910 : :
1911 : : /**
1912 : : * g_file_info_get_modification_date_time:
1913 : : * @info: a #GFileInfo.
1914 : : *
1915 : : * Gets the modification time of the current @info and returns it as a
1916 : : * #GDateTime.
1917 : : *
1918 : : * It is an error to call this if the #GFileInfo does not contain
1919 : : * %G_FILE_ATTRIBUTE_TIME_MODIFIED. If %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC is
1920 : : * provided, the resulting #GDateTime will additionally have microsecond
1921 : : * precision.
1922 : : *
1923 : : * If nanosecond precision is needed, %G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC must
1924 : : * be queried separately using g_file_info_get_attribute_uint32().
1925 : : *
1926 : : * Returns: (transfer full) (nullable): modification time, or %NULL if unknown
1927 : : * Since: 2.62
1928 : : */
1929 : : GDateTime *
1930 : 4 : g_file_info_get_modification_date_time (GFileInfo *info)
1931 : : {
1932 : : static guint32 attr_mtime = 0, attr_mtime_usec;
1933 : : GFileAttributeValue *value, *value_usec;
1934 : 4 : GDateTime *dt = NULL, *dt2 = NULL;
1935 : :
1936 : 4 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1937 : :
1938 : 4 : if (attr_mtime == 0)
1939 : : {
1940 : 1 : attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1941 : 1 : attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1942 : : }
1943 : :
1944 : 4 : value = g_file_info_find_value (info, attr_mtime);
1945 : 4 : if (value == NULL)
1946 : 0 : return NULL;
1947 : :
1948 : 4 : dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value));
1949 : :
1950 : 4 : value_usec = g_file_info_find_value (info, attr_mtime_usec);
1951 : 4 : if (value_usec == NULL)
1952 : 1 : return g_steal_pointer (&dt);
1953 : :
1954 : 3 : dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec));
1955 : 3 : g_date_time_unref (dt);
1956 : :
1957 : 3 : return g_steal_pointer (&dt2);
1958 : : }
1959 : :
1960 : : /**
1961 : : * g_file_info_get_access_date_time:
1962 : : * @info: a #GFileInfo.
1963 : : *
1964 : : * Gets the access time of the current @info and returns it as a
1965 : : * #GDateTime.
1966 : : *
1967 : : * It is an error to call this if the #GFileInfo does not contain
1968 : : * %G_FILE_ATTRIBUTE_TIME_ACCESS. If %G_FILE_ATTRIBUTE_TIME_ACCESS_USEC is
1969 : : * provided, the resulting #GDateTime will additionally have microsecond
1970 : : * precision.
1971 : : *
1972 : : * If nanosecond precision is needed, %G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC must
1973 : : * be queried separately using g_file_info_get_attribute_uint32().
1974 : : *
1975 : : * Returns: (transfer full) (nullable): access time, or %NULL if unknown
1976 : : * Since: 2.70
1977 : : */
1978 : : GDateTime *
1979 : 5 : g_file_info_get_access_date_time (GFileInfo *info)
1980 : : {
1981 : : static guint32 attr_atime = 0, attr_atime_usec;
1982 : : GFileAttributeValue *value, *value_usec;
1983 : 5 : GDateTime *dt = NULL, *dt2 = NULL;
1984 : :
1985 : 5 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1986 : :
1987 : 5 : if (attr_atime == 0)
1988 : : {
1989 : 1 : attr_atime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS);
1990 : 1 : attr_atime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_USEC);
1991 : : }
1992 : :
1993 : 5 : value = g_file_info_find_value (info, attr_atime);
1994 : 5 : if (value == NULL)
1995 : 0 : return NULL;
1996 : :
1997 : 5 : dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value));
1998 : :
1999 : 5 : value_usec = g_file_info_find_value (info, attr_atime_usec);
2000 : 5 : if (value_usec == NULL)
2001 : 1 : return g_steal_pointer (&dt);
2002 : :
2003 : 4 : dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec));
2004 : 4 : g_date_time_unref (dt);
2005 : :
2006 : 4 : return g_steal_pointer (&dt2);
2007 : : }
2008 : :
2009 : : /**
2010 : : * g_file_info_get_creation_date_time:
2011 : : * @info: a #GFileInfo.
2012 : : *
2013 : : * Gets the creation time of the current @info and returns it as a
2014 : : * #GDateTime.
2015 : : *
2016 : : * It is an error to call this if the #GFileInfo does not contain
2017 : : * %G_FILE_ATTRIBUTE_TIME_CREATED. If %G_FILE_ATTRIBUTE_TIME_CREATED_USEC is
2018 : : * provided, the resulting #GDateTime will additionally have microsecond
2019 : : * precision.
2020 : : *
2021 : : * If nanosecond precision is needed, %G_FILE_ATTRIBUTE_TIME_CREATED_NSEC must
2022 : : * be queried separately using g_file_info_get_attribute_uint32().
2023 : : *
2024 : : * Returns: (transfer full) (nullable): creation time, or %NULL if unknown
2025 : : * Since: 2.70
2026 : : */
2027 : : GDateTime *
2028 : 4 : g_file_info_get_creation_date_time (GFileInfo *info)
2029 : : {
2030 : : static guint32 attr_ctime = 0, attr_ctime_usec;
2031 : : GFileAttributeValue *value, *value_usec;
2032 : 4 : GDateTime *dt = NULL, *dt2 = NULL;
2033 : :
2034 : 4 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
2035 : :
2036 : 4 : if (attr_ctime == 0)
2037 : : {
2038 : 1 : attr_ctime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED);
2039 : 1 : attr_ctime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_USEC);
2040 : : }
2041 : :
2042 : 4 : value = g_file_info_find_value (info, attr_ctime);
2043 : 4 : if (value == NULL)
2044 : 0 : return NULL;
2045 : :
2046 : 4 : dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value));
2047 : :
2048 : 4 : value_usec = g_file_info_find_value (info, attr_ctime_usec);
2049 : 4 : if (value_usec == NULL)
2050 : 1 : return g_steal_pointer (&dt);
2051 : :
2052 : 3 : dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec));
2053 : 3 : g_date_time_unref (dt);
2054 : :
2055 : 3 : return g_steal_pointer (&dt2);
2056 : : }
2057 : :
2058 : : /**
2059 : : * g_file_info_get_symlink_target:
2060 : : * @info: a #GFileInfo.
2061 : : *
2062 : : * Gets the symlink target for a given #GFileInfo.
2063 : : *
2064 : : * It is an error to call this if the #GFileInfo does not contain
2065 : : * %G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET.
2066 : : *
2067 : : * Returns: (type filename) (nullable): a string containing the symlink target.
2068 : : **/
2069 : : const char *
2070 : 53 : g_file_info_get_symlink_target (GFileInfo *info)
2071 : : {
2072 : : GFileAttributeValue *value;
2073 : :
2074 : 53 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
2075 : :
2076 : 53 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET, NULL);
2077 : 53 : return _g_file_attribute_value_get_byte_string (value);
2078 : : }
2079 : :
2080 : : /**
2081 : : * g_file_info_get_etag:
2082 : : * @info: a #GFileInfo.
2083 : : *
2084 : : * Gets the [entity tag][iface@Gio.File#entity-tags] for a given
2085 : : * #GFileInfo. See %G_FILE_ATTRIBUTE_ETAG_VALUE.
2086 : : *
2087 : : * It is an error to call this if the #GFileInfo does not contain
2088 : : * %G_FILE_ATTRIBUTE_ETAG_VALUE.
2089 : : *
2090 : : * Returns: (nullable): a string containing the value of the "etag:value" attribute.
2091 : : **/
2092 : : const char *
2093 : 4 : g_file_info_get_etag (GFileInfo *info)
2094 : : {
2095 : : GFileAttributeValue *value;
2096 : :
2097 : 4 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
2098 : :
2099 : 4 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_ETAG_VALUE, NULL);
2100 : 4 : return _g_file_attribute_value_get_string (value);
2101 : : }
2102 : :
2103 : : /**
2104 : : * g_file_info_get_sort_order:
2105 : : * @info: a #GFileInfo.
2106 : : *
2107 : : * Gets the value of the sort_order attribute from the #GFileInfo.
2108 : : * See %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
2109 : : *
2110 : : * It is an error to call this if the #GFileInfo does not contain
2111 : : * %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
2112 : : *
2113 : : * Returns: a #gint32 containing the value of the "standard::sort_order" attribute.
2114 : : **/
2115 : : gint32
2116 : 0 : g_file_info_get_sort_order (GFileInfo *info)
2117 : : {
2118 : : GFileAttributeValue *value;
2119 : :
2120 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
2121 : :
2122 : 0 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER, 0);
2123 : 0 : return _g_file_attribute_value_get_int32 (value);
2124 : : }
2125 : :
2126 : : /* Helper setters: */
2127 : : /**
2128 : : * g_file_info_set_file_type:
2129 : : * @info: a #GFileInfo.
2130 : : * @type: a #GFileType.
2131 : : *
2132 : : * Sets the file type in a #GFileInfo to @type.
2133 : : * See %G_FILE_ATTRIBUTE_STANDARD_TYPE.
2134 : : **/
2135 : : void
2136 : 1130 : g_file_info_set_file_type (GFileInfo *info,
2137 : : GFileType type)
2138 : : {
2139 : : static guint32 attr = 0;
2140 : : GFileAttributeValue *value;
2141 : :
2142 : 1130 : g_return_if_fail (G_IS_FILE_INFO (info));
2143 : :
2144 : 1130 : if (attr == 0)
2145 : 11 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_TYPE);
2146 : :
2147 : 1130 : value = g_file_info_create_value (info, attr);
2148 : 1130 : if (value)
2149 : 762 : _g_file_attribute_value_set_uint32 (value, type);
2150 : : }
2151 : :
2152 : : /**
2153 : : * g_file_info_set_is_hidden:
2154 : : * @info: a #GFileInfo.
2155 : : * @is_hidden: a #gboolean.
2156 : : *
2157 : : * Sets the "is_hidden" attribute in a #GFileInfo according to @is_hidden.
2158 : : * See %G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN.
2159 : : **/
2160 : : void
2161 : 76 : g_file_info_set_is_hidden (GFileInfo *info,
2162 : : gboolean is_hidden)
2163 : : {
2164 : : static guint32 attr = 0;
2165 : : GFileAttributeValue *value;
2166 : :
2167 : 76 : g_return_if_fail (G_IS_FILE_INFO (info));
2168 : :
2169 : 76 : if (attr == 0)
2170 : 1 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
2171 : :
2172 : 76 : value = g_file_info_create_value (info, attr);
2173 : 76 : if (value)
2174 : 76 : _g_file_attribute_value_set_boolean (value, is_hidden);
2175 : : }
2176 : :
2177 : : /**
2178 : : * g_file_info_set_is_symlink:
2179 : : * @info: a #GFileInfo.
2180 : : * @is_symlink: a #gboolean.
2181 : : *
2182 : : * Sets the "is_symlink" attribute in a #GFileInfo according to @is_symlink.
2183 : : * See %G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK.
2184 : : **/
2185 : : void
2186 : 690 : g_file_info_set_is_symlink (GFileInfo *info,
2187 : : gboolean is_symlink)
2188 : : {
2189 : : static guint32 attr = 0;
2190 : : GFileAttributeValue *value;
2191 : :
2192 : 690 : g_return_if_fail (G_IS_FILE_INFO (info));
2193 : :
2194 : 690 : if (attr == 0)
2195 : 9 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
2196 : :
2197 : 690 : value = g_file_info_create_value (info, attr);
2198 : 690 : if (value)
2199 : 100 : _g_file_attribute_value_set_boolean (value, is_symlink);
2200 : : }
2201 : :
2202 : : /**
2203 : : * g_file_info_set_name:
2204 : : * @info: a #GFileInfo.
2205 : : * @name: (type filename): a string containing a name.
2206 : : *
2207 : : * Sets the name attribute for the current #GFileInfo.
2208 : : * See %G_FILE_ATTRIBUTE_STANDARD_NAME.
2209 : : **/
2210 : : void
2211 : 1452 : g_file_info_set_name (GFileInfo *info,
2212 : : const char *name)
2213 : : {
2214 : : static guint32 attr = 0;
2215 : : GFileAttributeValue *value;
2216 : :
2217 : 1452 : g_return_if_fail (G_IS_FILE_INFO (info));
2218 : 1452 : g_return_if_fail (name != NULL);
2219 : :
2220 : 1452 : if (attr == 0)
2221 : 12 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_NAME);
2222 : :
2223 : 1452 : value = g_file_info_create_value (info, attr);
2224 : 1452 : if (value)
2225 : 478 : _g_file_attribute_value_set_byte_string (value, name);
2226 : : }
2227 : :
2228 : : /**
2229 : : * g_file_info_set_display_name:
2230 : : * @info: a #GFileInfo.
2231 : : * @display_name: a string containing a display name.
2232 : : *
2233 : : * Sets the display name for the current #GFileInfo.
2234 : : * See %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME.
2235 : : **/
2236 : : void
2237 : 135 : g_file_info_set_display_name (GFileInfo *info,
2238 : : const char *display_name)
2239 : : {
2240 : : static guint32 attr = 0;
2241 : : GFileAttributeValue *value;
2242 : :
2243 : 135 : g_return_if_fail (G_IS_FILE_INFO (info));
2244 : 135 : g_return_if_fail (display_name != NULL);
2245 : :
2246 : 135 : if (attr == 0)
2247 : 2 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
2248 : :
2249 : 135 : value = g_file_info_create_value (info, attr);
2250 : 135 : if (value)
2251 : 135 : _g_file_attribute_value_set_string (value, display_name);
2252 : : }
2253 : :
2254 : : /**
2255 : : * g_file_info_set_edit_name:
2256 : : * @info: a #GFileInfo.
2257 : : * @edit_name: a string containing an edit name.
2258 : : *
2259 : : * Sets the edit name for the current file.
2260 : : * See %G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME.
2261 : : **/
2262 : : void
2263 : 131 : g_file_info_set_edit_name (GFileInfo *info,
2264 : : const char *edit_name)
2265 : : {
2266 : : static guint32 attr = 0;
2267 : : GFileAttributeValue *value;
2268 : :
2269 : 131 : g_return_if_fail (G_IS_FILE_INFO (info));
2270 : 131 : g_return_if_fail (edit_name != NULL);
2271 : :
2272 : 131 : if (attr == 0)
2273 : 1 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
2274 : :
2275 : 131 : value = g_file_info_create_value (info, attr);
2276 : 131 : if (value)
2277 : 131 : _g_file_attribute_value_set_string (value, edit_name);
2278 : : }
2279 : :
2280 : : /**
2281 : : * g_file_info_set_icon:
2282 : : * @info: a #GFileInfo.
2283 : : * @icon: a #GIcon.
2284 : : *
2285 : : * Sets the icon for a given #GFileInfo.
2286 : : * See %G_FILE_ATTRIBUTE_STANDARD_ICON.
2287 : : **/
2288 : : void
2289 : 76 : g_file_info_set_icon (GFileInfo *info,
2290 : : GIcon *icon)
2291 : : {
2292 : : static guint32 attr = 0;
2293 : : GFileAttributeValue *value;
2294 : :
2295 : 76 : g_return_if_fail (G_IS_FILE_INFO (info));
2296 : 76 : g_return_if_fail (G_IS_ICON (icon));
2297 : :
2298 : 76 : if (attr == 0)
2299 : 1 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_ICON);
2300 : :
2301 : 76 : value = g_file_info_create_value (info, attr);
2302 : 76 : if (value)
2303 : 76 : _g_file_attribute_value_set_object (value, G_OBJECT (icon));
2304 : : }
2305 : :
2306 : : /**
2307 : : * g_file_info_set_symbolic_icon:
2308 : : * @info: a #GFileInfo.
2309 : : * @icon: a #GIcon.
2310 : : *
2311 : : * Sets the symbolic icon for a given #GFileInfo.
2312 : : * See %G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON.
2313 : : *
2314 : : * Since: 2.34
2315 : : **/
2316 : : void
2317 : 76 : g_file_info_set_symbolic_icon (GFileInfo *info,
2318 : : GIcon *icon)
2319 : : {
2320 : : static guint32 attr = 0;
2321 : : GFileAttributeValue *value;
2322 : :
2323 : 76 : g_return_if_fail (G_IS_FILE_INFO (info));
2324 : 76 : g_return_if_fail (G_IS_ICON (icon));
2325 : :
2326 : 76 : if (attr == 0)
2327 : 1 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON);
2328 : :
2329 : 76 : value = g_file_info_create_value (info, attr);
2330 : 76 : if (value)
2331 : 76 : _g_file_attribute_value_set_object (value, G_OBJECT (icon));
2332 : : }
2333 : :
2334 : : /**
2335 : : * g_file_info_set_content_type:
2336 : : * @info: a #GFileInfo.
2337 : : * @content_type: a [content type](content-types.html#content-types).
2338 : : *
2339 : : * Sets the content type attribute for a given #GFileInfo.
2340 : : * See %G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE.
2341 : : **/
2342 : : void
2343 : 84 : g_file_info_set_content_type (GFileInfo *info,
2344 : : const char *content_type)
2345 : : {
2346 : : static guint32 attr = 0;
2347 : : GFileAttributeValue *value;
2348 : :
2349 : 84 : g_return_if_fail (G_IS_FILE_INFO (info));
2350 : 84 : g_return_if_fail (content_type != NULL);
2351 : :
2352 : 84 : if (attr == 0)
2353 : 4 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
2354 : :
2355 : 84 : value = g_file_info_create_value (info, attr);
2356 : 84 : if (value)
2357 : 84 : _g_file_attribute_value_set_string (value, content_type);
2358 : : }
2359 : :
2360 : : /**
2361 : : * g_file_info_set_size:
2362 : : * @info: a #GFileInfo.
2363 : : * @size: a #goffset containing the file's size.
2364 : : *
2365 : : * Sets the %G_FILE_ATTRIBUTE_STANDARD_SIZE attribute in the file info
2366 : : * to the given size.
2367 : : **/
2368 : : void
2369 : 737 : g_file_info_set_size (GFileInfo *info,
2370 : : goffset size)
2371 : : {
2372 : : static guint32 attr = 0;
2373 : : GFileAttributeValue *value;
2374 : :
2375 : 737 : g_return_if_fail (G_IS_FILE_INFO (info));
2376 : :
2377 : 737 : if (attr == 0)
2378 : 10 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SIZE);
2379 : :
2380 : 737 : value = g_file_info_create_value (info, attr);
2381 : 737 : if (value)
2382 : 290 : _g_file_attribute_value_set_uint64 (value, size);
2383 : : }
2384 : :
2385 : : /**
2386 : : * g_file_info_set_modification_time:
2387 : : * @info: a #GFileInfo.
2388 : : * @mtime: a #GTimeVal.
2389 : : *
2390 : : * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED and
2391 : : * %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC attributes in the file info to the
2392 : : * given time value.
2393 : : *
2394 : : * %G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC will be cleared.
2395 : : *
2396 : : * Deprecated: 2.62: Use g_file_info_set_modification_date_time() instead, as
2397 : : * #GTimeVal is deprecated due to the year 2038 problem.
2398 : : **/
2399 : : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2400 : : void
2401 : 0 : g_file_info_set_modification_time (GFileInfo *info,
2402 : : GTimeVal *mtime)
2403 : : {
2404 : : static guint32 attr_mtime = 0, attr_mtime_usec = 0, attr_mtime_nsec = 0;
2405 : : GFileAttributeValue *value;
2406 : :
2407 : 0 : g_return_if_fail (G_IS_FILE_INFO (info));
2408 : 0 : g_return_if_fail (mtime != NULL);
2409 : :
2410 : 0 : if (attr_mtime == 0)
2411 : : {
2412 : 0 : attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
2413 : 0 : attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
2414 : 0 : attr_mtime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
2415 : : }
2416 : :
2417 : 0 : value = g_file_info_create_value (info, attr_mtime);
2418 : 0 : if (value)
2419 : 0 : _g_file_attribute_value_set_uint64 (value, mtime->tv_sec);
2420 : 0 : value = g_file_info_create_value (info, attr_mtime_usec);
2421 : 0 : if (value)
2422 : 0 : _g_file_attribute_value_set_uint32 (value, mtime->tv_usec);
2423 : :
2424 : : /* nsecs can’t be known from a #GTimeVal, so remove them */
2425 : 0 : g_file_info_remove_value (info, attr_mtime_nsec);
2426 : : }
2427 : : G_GNUC_END_IGNORE_DEPRECATIONS
2428 : :
2429 : : /**
2430 : : * g_file_info_set_modification_date_time:
2431 : : * @info: a #GFileInfo.
2432 : : * @mtime: (not nullable): a #GDateTime.
2433 : : *
2434 : : * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED and
2435 : : * %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC attributes in the file info to the
2436 : : * given date/time value.
2437 : : *
2438 : : * %G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC will be cleared.
2439 : : *
2440 : : * Since: 2.62
2441 : : */
2442 : : void
2443 : 2 : g_file_info_set_modification_date_time (GFileInfo *info,
2444 : : GDateTime *mtime)
2445 : : {
2446 : : static guint32 attr_mtime = 0, attr_mtime_usec = 0, attr_mtime_nsec = 0;
2447 : : GFileAttributeValue *value;
2448 : :
2449 : 2 : g_return_if_fail (G_IS_FILE_INFO (info));
2450 : 2 : g_return_if_fail (mtime != NULL);
2451 : :
2452 : 2 : if (attr_mtime == 0)
2453 : : {
2454 : 1 : attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
2455 : 1 : attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
2456 : 1 : attr_mtime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
2457 : : }
2458 : :
2459 : 2 : value = g_file_info_create_value (info, attr_mtime);
2460 : 2 : if (value)
2461 : 2 : _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (mtime));
2462 : 2 : value = g_file_info_create_value (info, attr_mtime_usec);
2463 : 2 : if (value)
2464 : 2 : _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (mtime));
2465 : :
2466 : : /* nsecs can’t be known from a #GDateTime, so remove them */
2467 : 2 : g_file_info_remove_value (info, attr_mtime_nsec);
2468 : : }
2469 : :
2470 : : /**
2471 : : * g_file_info_set_access_date_time:
2472 : : * @info: a #GFileInfo.
2473 : : * @atime: (not nullable): a #GDateTime.
2474 : : *
2475 : : * Sets the %G_FILE_ATTRIBUTE_TIME_ACCESS and
2476 : : * %G_FILE_ATTRIBUTE_TIME_ACCESS_USEC attributes in the file info to the
2477 : : * given date/time value.
2478 : : *
2479 : : * %G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC will be cleared.
2480 : : *
2481 : : * Since: 2.70
2482 : : */
2483 : : void
2484 : 2 : g_file_info_set_access_date_time (GFileInfo *info,
2485 : : GDateTime *atime)
2486 : : {
2487 : : static guint32 attr_atime = 0, attr_atime_usec = 0, attr_atime_nsec = 0;
2488 : : GFileAttributeValue *value;
2489 : :
2490 : 2 : g_return_if_fail (G_IS_FILE_INFO (info));
2491 : 2 : g_return_if_fail (atime != NULL);
2492 : :
2493 : 2 : if (attr_atime == 0)
2494 : : {
2495 : 1 : attr_atime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS);
2496 : 1 : attr_atime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_USEC);
2497 : 1 : attr_atime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC);
2498 : : }
2499 : :
2500 : 2 : value = g_file_info_create_value (info, attr_atime);
2501 : 2 : if (value)
2502 : 2 : _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (atime));
2503 : 2 : value = g_file_info_create_value (info, attr_atime_usec);
2504 : 2 : if (value)
2505 : 2 : _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (atime));
2506 : :
2507 : : /* nsecs can’t be known from a #GDateTime, so remove them */
2508 : 2 : g_file_info_remove_value (info, attr_atime_nsec);
2509 : : }
2510 : :
2511 : : /**
2512 : : * g_file_info_set_creation_date_time:
2513 : : * @info: a #GFileInfo.
2514 : : * @creation_time: (not nullable): a #GDateTime.
2515 : : *
2516 : : * Sets the %G_FILE_ATTRIBUTE_TIME_CREATED and
2517 : : * %G_FILE_ATTRIBUTE_TIME_CREATED_USEC attributes in the file info to the
2518 : : * given date/time value.
2519 : : *
2520 : : * %G_FILE_ATTRIBUTE_TIME_CREATED_NSEC will be cleared.
2521 : : *
2522 : : * Since: 2.70
2523 : : */
2524 : : void
2525 : 2 : g_file_info_set_creation_date_time (GFileInfo *info,
2526 : : GDateTime *creation_time)
2527 : : {
2528 : : static guint32 attr_ctime = 0, attr_ctime_usec = 0, attr_ctime_nsec = 0;
2529 : : GFileAttributeValue *value;
2530 : :
2531 : 2 : g_return_if_fail (G_IS_FILE_INFO (info));
2532 : 2 : g_return_if_fail (creation_time != NULL);
2533 : :
2534 : 2 : if (attr_ctime == 0)
2535 : : {
2536 : 1 : attr_ctime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED);
2537 : 1 : attr_ctime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_USEC);
2538 : 1 : attr_ctime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_NSEC);
2539 : : }
2540 : :
2541 : 2 : value = g_file_info_create_value (info, attr_ctime);
2542 : 2 : if (value)
2543 : 2 : _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (creation_time));
2544 : 2 : value = g_file_info_create_value (info, attr_ctime_usec);
2545 : 2 : if (value)
2546 : 2 : _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (creation_time));
2547 : :
2548 : : /* nsecs can’t be known from a #GDateTime, so remove them */
2549 : 2 : g_file_info_remove_value (info, attr_ctime_nsec);
2550 : : }
2551 : :
2552 : : /**
2553 : : * g_file_info_set_symlink_target:
2554 : : * @info: a #GFileInfo.
2555 : : * @symlink_target: (type filename): a static string containing a path to a symlink target.
2556 : : *
2557 : : * Sets the %G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET attribute in the file info
2558 : : * to the given symlink target.
2559 : : **/
2560 : : void
2561 : 38 : g_file_info_set_symlink_target (GFileInfo *info,
2562 : : const char *symlink_target)
2563 : : {
2564 : : static guint32 attr = 0;
2565 : : GFileAttributeValue *value;
2566 : :
2567 : 38 : g_return_if_fail (G_IS_FILE_INFO (info));
2568 : 38 : g_return_if_fail (symlink_target != NULL);
2569 : :
2570 : 38 : if (attr == 0)
2571 : 2 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET);
2572 : :
2573 : 38 : value = g_file_info_create_value (info, attr);
2574 : 38 : if (value)
2575 : 38 : _g_file_attribute_value_set_byte_string (value, symlink_target);
2576 : : }
2577 : :
2578 : : /**
2579 : : * g_file_info_set_sort_order:
2580 : : * @info: a #GFileInfo.
2581 : : * @sort_order: a sort order integer.
2582 : : *
2583 : : * Sets the sort order attribute in the file info structure. See
2584 : : * %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
2585 : : **/
2586 : : void
2587 : 0 : g_file_info_set_sort_order (GFileInfo *info,
2588 : : gint32 sort_order)
2589 : : {
2590 : : static guint32 attr = 0;
2591 : : GFileAttributeValue *value;
2592 : :
2593 : 0 : g_return_if_fail (G_IS_FILE_INFO (info));
2594 : :
2595 : 0 : if (attr == 0)
2596 : 0 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER);
2597 : :
2598 : 0 : value = g_file_info_create_value (info, attr);
2599 : 0 : if (value)
2600 : 0 : _g_file_attribute_value_set_int32 (value, sort_order);
2601 : : }
2602 : :
2603 : :
2604 : : typedef struct {
2605 : : guint32 id;
2606 : : guint32 mask;
2607 : : } SubMatcher;
2608 : :
2609 : : struct _GFileAttributeMatcher {
2610 : : gboolean all;
2611 : : gint ref;
2612 : :
2613 : : GArray *sub_matchers;
2614 : :
2615 : : /* Iterator */
2616 : : guint32 iterator_ns;
2617 : : gint iterator_pos;
2618 : : };
2619 : :
2620 : 4 : G_DEFINE_BOXED_TYPE (GFileAttributeMatcher, g_file_attribute_matcher,
2621 : : g_file_attribute_matcher_ref,
2622 : : g_file_attribute_matcher_unref)
2623 : :
2624 : : static gint
2625 : 3440 : compare_sub_matchers (gconstpointer a,
2626 : : gconstpointer b)
2627 : : {
2628 : 3440 : const SubMatcher *suba = a;
2629 : 3440 : const SubMatcher *subb = b;
2630 : : int diff;
2631 : :
2632 : 3440 : diff = suba->id - subb->id;
2633 : :
2634 : 3440 : if (diff)
2635 : 3437 : return diff;
2636 : :
2637 : 3 : return suba->mask - subb->mask;
2638 : : }
2639 : :
2640 : : static gboolean
2641 : 2548 : sub_matcher_matches (SubMatcher *matcher,
2642 : : SubMatcher *submatcher)
2643 : : {
2644 : 2548 : if ((matcher->mask & submatcher->mask) != matcher->mask)
2645 : 128 : return FALSE;
2646 : :
2647 : 2420 : return matcher->id == (submatcher->id & matcher->mask);
2648 : : }
2649 : :
2650 : : /* Call this function after modifying a matcher.
2651 : : * It will ensure all the invariants other functions rely on.
2652 : : */
2653 : : static GFileAttributeMatcher *
2654 : 1572 : matcher_optimize (GFileAttributeMatcher *matcher)
2655 : : {
2656 : : SubMatcher *submatcher, *compare;
2657 : : guint i, j;
2658 : :
2659 : : /* remove sub_matchers if we match everything anyway */
2660 : 1572 : if (matcher->all)
2661 : : {
2662 : 64 : if (matcher->sub_matchers)
2663 : : {
2664 : 64 : g_array_free (matcher->sub_matchers, TRUE);
2665 : 64 : matcher->sub_matchers = NULL;
2666 : : }
2667 : 64 : return matcher;
2668 : : }
2669 : :
2670 : 1508 : if (matcher->sub_matchers->len == 0)
2671 : : {
2672 : 222 : g_file_attribute_matcher_unref (matcher);
2673 : 222 : return NULL;
2674 : : }
2675 : :
2676 : : /* sort sub_matchers by id (and then mask), so we can bsearch
2677 : : * and compare matchers in O(N) instead of O(N²) */
2678 : 1286 : g_array_sort (matcher->sub_matchers, compare_sub_matchers);
2679 : :
2680 : : /* remove duplicates and specific matches when we match the whole namespace */
2681 : 1286 : j = 0;
2682 : 1286 : compare = &g_array_index (matcher->sub_matchers, SubMatcher, j);
2683 : :
2684 : 3330 : for (i = 1; i < matcher->sub_matchers->len; i++)
2685 : : {
2686 : 2044 : submatcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
2687 : 2044 : if (sub_matcher_matches (compare, submatcher))
2688 : 7 : continue;
2689 : :
2690 : 2037 : j++;
2691 : 2037 : compare++;
2692 : :
2693 : 2037 : if (j < i)
2694 : 1 : *compare = *submatcher;
2695 : : }
2696 : :
2697 : 1286 : g_array_set_size (matcher->sub_matchers, j + 1);
2698 : :
2699 : 1286 : return matcher;
2700 : : }
2701 : :
2702 : : /**
2703 : : * g_file_attribute_matcher_new:
2704 : : * @attributes: an attribute string to match.
2705 : : *
2706 : : * Creates a new file attribute matcher, which matches attributes
2707 : : * against a given string. #GFileAttributeMatchers are reference
2708 : : * counted structures, and are created with a reference count of 1. If
2709 : : * the number of references falls to 0, the #GFileAttributeMatcher is
2710 : : * automatically destroyed.
2711 : : *
2712 : : * The @attributes string should be formatted with specific keys separated
2713 : : * from namespaces with a double colon. Several "namespace::key" strings may be
2714 : : * concatenated with a single comma (e.g. "standard::type,standard::is-hidden").
2715 : : * The wildcard "*" may be used to match all keys and namespaces, or
2716 : : * "namespace::*" will match all keys in a given namespace.
2717 : : *
2718 : : * ## Examples of file attribute matcher strings and results
2719 : : *
2720 : : * - `"*"`: matches all attributes.
2721 : : * - `"standard::is-hidden"`: matches only the key is-hidden in the
2722 : : * standard namespace.
2723 : : * - `"standard::type,unix::*"`: matches the type key in the standard
2724 : : * namespace and all keys in the unix namespace.
2725 : : *
2726 : : * Returns: a #GFileAttributeMatcher
2727 : : */
2728 : : GFileAttributeMatcher *
2729 : 1325 : g_file_attribute_matcher_new (const char *attributes)
2730 : : {
2731 : : char **split;
2732 : : char *colon;
2733 : : int i;
2734 : : GFileAttributeMatcher *matcher;
2735 : :
2736 : 1325 : if (attributes == NULL || *attributes == '\0')
2737 : 2 : return NULL;
2738 : :
2739 : 1323 : matcher = g_malloc0 (sizeof (GFileAttributeMatcher));
2740 : 1323 : matcher->ref = 1;
2741 : 1323 : matcher->sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
2742 : :
2743 : 1323 : split = g_strsplit (attributes, ",", -1);
2744 : :
2745 : 4691 : for (i = 0; split[i] != NULL; i++)
2746 : : {
2747 : 3368 : if (strcmp (split[i], "*") == 0)
2748 : 65 : matcher->all = TRUE;
2749 : : else
2750 : : {
2751 : : SubMatcher s;
2752 : :
2753 : 3303 : colon = strstr (split[i], "::");
2754 : 3303 : if (colon != NULL &&
2755 : 3276 : !(colon[2] == 0 ||
2756 : 3276 : (colon[2] == '*' &&
2757 : 182 : colon[3] == 0)))
2758 : : {
2759 : 3094 : s.id = lookup_attribute (split[i]);
2760 : 3094 : s.mask = 0xffffffff;
2761 : : }
2762 : : else
2763 : : {
2764 : 209 : if (colon)
2765 : 182 : *colon = 0;
2766 : :
2767 : 209 : s.id = lookup_namespace (split[i]) << NS_POS;
2768 : 209 : s.mask = NS_MASK << NS_POS;
2769 : : }
2770 : :
2771 : 3303 : g_array_append_val (matcher->sub_matchers, s);
2772 : : }
2773 : : }
2774 : :
2775 : 1323 : g_strfreev (split);
2776 : :
2777 : 1323 : matcher = matcher_optimize (matcher);
2778 : :
2779 : 1323 : return matcher;
2780 : : }
2781 : :
2782 : : /**
2783 : : * g_file_attribute_matcher_subtract:
2784 : : * @matcher: (nullable): Matcher to subtract from
2785 : : * @subtract: (nullable): The matcher to subtract
2786 : : *
2787 : : * Subtracts all attributes of @subtract from @matcher and returns
2788 : : * a matcher that supports those attributes.
2789 : : *
2790 : : * Note that currently it is not possible to remove a single
2791 : : * attribute when the @matcher matches the whole namespace - or remove
2792 : : * a namespace or attribute when the matcher matches everything. This
2793 : : * is a limitation of the current implementation, but may be fixed
2794 : : * in the future.
2795 : : *
2796 : : * Returns: (nullable): A file attribute matcher matching all attributes of
2797 : : * @matcher that are not matched by @subtract
2798 : : **/
2799 : : GFileAttributeMatcher *
2800 : 284 : g_file_attribute_matcher_subtract (GFileAttributeMatcher *matcher,
2801 : : GFileAttributeMatcher *subtract)
2802 : : {
2803 : : GFileAttributeMatcher *result;
2804 : : guint mi, si;
2805 : : SubMatcher *msub, *ssub;
2806 : :
2807 : 284 : if (matcher == NULL)
2808 : 2 : return NULL;
2809 : 282 : if (subtract == NULL)
2810 : 0 : return g_file_attribute_matcher_ref (matcher);
2811 : 282 : if (subtract->all)
2812 : 10 : return NULL;
2813 : 272 : if (matcher->all)
2814 : 23 : return g_file_attribute_matcher_ref (matcher);
2815 : :
2816 : 249 : result = g_malloc0 (sizeof (GFileAttributeMatcher));
2817 : 249 : result->ref = 1;
2818 : 249 : result->sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
2819 : :
2820 : 249 : si = 0;
2821 : 249 : g_assert (subtract->sub_matchers->len > 0);
2822 : 249 : ssub = &g_array_index (subtract->sub_matchers, SubMatcher, si);
2823 : :
2824 : 521 : for (mi = 0; mi < matcher->sub_matchers->len; mi++)
2825 : : {
2826 : 288 : msub = &g_array_index (matcher->sub_matchers, SubMatcher, mi);
2827 : :
2828 : 504 : retry:
2829 : 504 : if (sub_matcher_matches (ssub, msub))
2830 : 259 : continue;
2831 : :
2832 : 245 : si++;
2833 : 245 : if (si >= subtract->sub_matchers->len)
2834 : 16 : break;
2835 : :
2836 : 229 : ssub = &g_array_index (subtract->sub_matchers, SubMatcher, si);
2837 : 229 : if (ssub->id <= msub->id)
2838 : 216 : goto retry;
2839 : :
2840 : 13 : g_array_append_val (result->sub_matchers, *msub);
2841 : : }
2842 : :
2843 : 249 : if (mi < matcher->sub_matchers->len)
2844 : 16 : g_array_append_vals (result->sub_matchers,
2845 : 16 : &g_array_index (matcher->sub_matchers, SubMatcher, mi),
2846 : 16 : matcher->sub_matchers->len - mi);
2847 : :
2848 : 249 : result = matcher_optimize (result);
2849 : :
2850 : 249 : return result;
2851 : : }
2852 : :
2853 : : /**
2854 : : * g_file_attribute_matcher_ref:
2855 : : * @matcher: a #GFileAttributeMatcher.
2856 : : *
2857 : : * References a file attribute matcher.
2858 : : *
2859 : : * Returns: a #GFileAttributeMatcher.
2860 : : **/
2861 : : GFileAttributeMatcher *
2862 : 1142 : g_file_attribute_matcher_ref (GFileAttributeMatcher *matcher)
2863 : : {
2864 : 1142 : if (matcher)
2865 : : {
2866 : 805 : g_return_val_if_fail (matcher->ref > 0, NULL);
2867 : 805 : g_atomic_int_inc (&matcher->ref);
2868 : : }
2869 : 1142 : return matcher;
2870 : : }
2871 : :
2872 : : /**
2873 : : * g_file_attribute_matcher_unref:
2874 : : * @matcher: a #GFileAttributeMatcher.
2875 : : *
2876 : : * Unreferences @matcher. If the reference count falls below 1,
2877 : : * the @matcher is automatically freed.
2878 : : *
2879 : : **/
2880 : : void
2881 : 2948 : g_file_attribute_matcher_unref (GFileAttributeMatcher *matcher)
2882 : : {
2883 : 2948 : if (matcher)
2884 : : {
2885 : 2376 : g_return_if_fail (matcher->ref > 0);
2886 : :
2887 : 2376 : if (g_atomic_int_dec_and_test (&matcher->ref))
2888 : : {
2889 : 1571 : if (matcher->sub_matchers)
2890 : 1507 : g_array_free (matcher->sub_matchers, TRUE);
2891 : :
2892 : 1571 : g_free (matcher);
2893 : : }
2894 : : }
2895 : : }
2896 : :
2897 : : /**
2898 : : * g_file_attribute_matcher_matches_only:
2899 : : * @matcher: a #GFileAttributeMatcher.
2900 : : * @attribute: a file attribute key.
2901 : : *
2902 : : * Checks if an attribute matcher only matches a given attribute. Always
2903 : : * returns %FALSE if "*" was used when creating the matcher.
2904 : : *
2905 : : * Returns: %TRUE if the matcher only matches @attribute. %FALSE otherwise.
2906 : : **/
2907 : : gboolean
2908 : 1 : g_file_attribute_matcher_matches_only (GFileAttributeMatcher *matcher,
2909 : : const char *attribute)
2910 : : {
2911 : : SubMatcher *sub_matcher;
2912 : : guint32 id;
2913 : :
2914 : 1 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
2915 : :
2916 : 1 : if (matcher == NULL ||
2917 : 1 : matcher->all)
2918 : 0 : return FALSE;
2919 : :
2920 : 1 : if (matcher->sub_matchers->len != 1)
2921 : 1 : return FALSE;
2922 : :
2923 : 0 : id = lookup_attribute (attribute);
2924 : :
2925 : 0 : sub_matcher = &g_array_index (matcher->sub_matchers, SubMatcher, 0);
2926 : :
2927 : 0 : return sub_matcher->id == id &&
2928 : 0 : sub_matcher->mask == 0xffffffff;
2929 : : }
2930 : :
2931 : : static gboolean
2932 : 43979 : matcher_matches_id (GFileAttributeMatcher *matcher,
2933 : : guint32 id)
2934 : : {
2935 : : SubMatcher *sub_matchers;
2936 : : guint i;
2937 : :
2938 : 43979 : if (matcher->sub_matchers)
2939 : : {
2940 : 43979 : sub_matchers = (SubMatcher *)matcher->sub_matchers->data;
2941 : 134940 : for (i = 0; i < matcher->sub_matchers->len; i++)
2942 : : {
2943 : 93041 : if (sub_matchers[i].id == (id & sub_matchers[i].mask))
2944 : 2080 : return TRUE;
2945 : : }
2946 : : }
2947 : :
2948 : 41899 : return FALSE;
2949 : : }
2950 : :
2951 : : gboolean
2952 : 51266 : _g_file_attribute_matcher_matches_id (GFileAttributeMatcher *matcher,
2953 : : guint32 id)
2954 : : {
2955 : : /* We return a NULL matcher for an empty match string, so handle this */
2956 : 51266 : if (matcher == NULL)
2957 : 1368 : return FALSE;
2958 : :
2959 : 49898 : if (matcher->all)
2960 : 5957 : return TRUE;
2961 : :
2962 : 43941 : return matcher_matches_id (matcher, id);
2963 : : }
2964 : :
2965 : : /**
2966 : : * g_file_attribute_matcher_matches:
2967 : : * @matcher: a #GFileAttributeMatcher.
2968 : : * @attribute: a file attribute key.
2969 : : *
2970 : : * Checks if an attribute will be matched by an attribute matcher. If
2971 : : * the matcher was created with the "*" matching string, this function
2972 : : * will always return %TRUE.
2973 : : *
2974 : : * Returns: %TRUE if @attribute matches @matcher. %FALSE otherwise.
2975 : : **/
2976 : : gboolean
2977 : 40 : g_file_attribute_matcher_matches (GFileAttributeMatcher *matcher,
2978 : : const char *attribute)
2979 : : {
2980 : 40 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
2981 : :
2982 : : /* We return a NULL matcher for an empty match string, so handle this */
2983 : 40 : if (matcher == NULL)
2984 : 0 : return FALSE;
2985 : :
2986 : 40 : if (matcher->all)
2987 : 2 : return TRUE;
2988 : :
2989 : 38 : return matcher_matches_id (matcher, lookup_attribute (attribute));
2990 : : }
2991 : :
2992 : : /* return TRUE -> all */
2993 : : /**
2994 : : * g_file_attribute_matcher_enumerate_namespace:
2995 : : * @matcher: a #GFileAttributeMatcher.
2996 : : * @ns: a string containing a file attribute namespace.
2997 : : *
2998 : : * Checks if the matcher will match all of the keys in a given namespace.
2999 : : * This will always return %TRUE if a wildcard character is in use (e.g. if
3000 : : * matcher was created with "standard::*" and @ns is "standard", or if matcher was created
3001 : : * using "*" and namespace is anything.)
3002 : : *
3003 : : * TODO: this is awkwardly worded.
3004 : : *
3005 : : * Returns: %TRUE if the matcher matches all of the entries
3006 : : * in the given @ns, %FALSE otherwise.
3007 : : **/
3008 : : gboolean
3009 : 1470 : g_file_attribute_matcher_enumerate_namespace (GFileAttributeMatcher *matcher,
3010 : : const char *ns)
3011 : : {
3012 : : SubMatcher *sub_matchers;
3013 : : guint ns_id;
3014 : : guint i;
3015 : :
3016 : 1470 : g_return_val_if_fail (ns != NULL && *ns != '\0', FALSE);
3017 : :
3018 : : /* We return a NULL matcher for an empty match string, so handle this */
3019 : 1470 : if (matcher == NULL)
3020 : 0 : return FALSE;
3021 : :
3022 : 1470 : if (matcher->all)
3023 : 152 : return TRUE;
3024 : :
3025 : 1318 : ns_id = lookup_namespace (ns) << NS_POS;
3026 : :
3027 : 1318 : if (matcher->sub_matchers)
3028 : : {
3029 : 1318 : sub_matchers = (SubMatcher *)matcher->sub_matchers->data;
3030 : 4572 : for (i = 0; i < matcher->sub_matchers->len; i++)
3031 : : {
3032 : 3326 : if (sub_matchers[i].id == ns_id)
3033 : 72 : return TRUE;
3034 : : }
3035 : : }
3036 : :
3037 : 1246 : matcher->iterator_ns = ns_id;
3038 : 1246 : matcher->iterator_pos = 0;
3039 : :
3040 : 1246 : return FALSE;
3041 : : }
3042 : :
3043 : : /**
3044 : : * g_file_attribute_matcher_enumerate_next:
3045 : : * @matcher: a #GFileAttributeMatcher.
3046 : : *
3047 : : * Gets the next matched attribute from a #GFileAttributeMatcher.
3048 : : *
3049 : : * Returns: (nullable): a string containing the next attribute or, %NULL if
3050 : : * no more attribute exist.
3051 : : **/
3052 : : const char *
3053 : 1247 : g_file_attribute_matcher_enumerate_next (GFileAttributeMatcher *matcher)
3054 : : {
3055 : : guint i;
3056 : : SubMatcher *sub_matcher;
3057 : :
3058 : : /* We return a NULL matcher for an empty match string, so handle this */
3059 : 1247 : if (matcher == NULL)
3060 : 0 : return NULL;
3061 : :
3062 : : while (1)
3063 : : {
3064 : 4108 : i = matcher->iterator_pos++;
3065 : :
3066 : 4108 : if (matcher->sub_matchers == NULL)
3067 : 0 : return NULL;
3068 : :
3069 : 4108 : if (i < matcher->sub_matchers->len)
3070 : 2862 : sub_matcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
3071 : : else
3072 : 1246 : return NULL;
3073 : :
3074 : 2862 : if (sub_matcher->mask == 0xffffffff &&
3075 : 2656 : (sub_matcher->id & (NS_MASK << NS_POS)) == matcher->iterator_ns)
3076 : 1 : return get_attribute_for_id (sub_matcher->id);
3077 : : }
3078 : : }
3079 : :
3080 : : /**
3081 : : * g_file_attribute_matcher_to_string:
3082 : : * @matcher: (nullable): a #GFileAttributeMatcher.
3083 : : *
3084 : : * Prints what the matcher is matching against. The format will be
3085 : : * equal to the format passed to g_file_attribute_matcher_new().
3086 : : * The output however, might not be identical, as the matcher may
3087 : : * decide to use a different order or omit needless parts.
3088 : : *
3089 : : * Returns: a string describing the attributes the matcher matches
3090 : : * against or %NULL if @matcher was %NULL.
3091 : : *
3092 : : * Since: 2.32
3093 : : **/
3094 : : char *
3095 : 69 : g_file_attribute_matcher_to_string (GFileAttributeMatcher *matcher)
3096 : : {
3097 : : GString *string;
3098 : : guint i;
3099 : :
3100 : 69 : if (matcher == NULL)
3101 : 19 : return NULL;
3102 : :
3103 : 50 : if (matcher->all)
3104 : 11 : return g_strdup ("*");
3105 : :
3106 : 39 : string = g_string_new ("");
3107 : 91 : for (i = 0; i < matcher->sub_matchers->len; i++)
3108 : : {
3109 : 52 : SubMatcher *submatcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
3110 : :
3111 : 52 : if (i > 0)
3112 : : g_string_append_c (string, ',');
3113 : :
3114 : 52 : g_string_append (string, get_attribute_for_id (submatcher->id));
3115 : : }
3116 : :
3117 : 39 : return g_string_free (string, FALSE);
3118 : : }
|