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 : 12267 : 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 : 3476 : _lookup_namespace (const char *namespace)
134 : : {
135 : : NSInfo *ns_info;
136 : :
137 : 3476 : ns_info = g_hash_table_lookup (ns_hash, namespace);
138 : 3476 : 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 : 3476 : return ns_info;
148 : : }
149 : :
150 : : static guint32
151 : 6890 : _lookup_attribute (const char *attribute)
152 : : {
153 : : guint32 attr_id, id;
154 : : char *ns;
155 : : const char *colon;
156 : : NSInfo *ns_info;
157 : :
158 : 6890 : attr_id = GPOINTER_TO_UINT (g_hash_table_lookup (attribute_hash, attribute));
159 : :
160 : 6890 : if (attr_id != 0)
161 : 4948 : 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 : 6504 : ensure_attribute_hash (void)
185 : : {
186 : 6504 : if (attribute_hash != NULL)
187 : 6484 : 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 : 1534 : lookup_namespace (const char *namespace)
301 : : {
302 : : NSInfo *ns_info;
303 : : guint32 id;
304 : :
305 : 1534 : G_LOCK (attribute_hash);
306 : :
307 : 1534 : ensure_attribute_hash ();
308 : :
309 : 1534 : ns_info = _lookup_namespace (namespace);
310 : 1534 : id = 0;
311 : 1534 : if (ns_info)
312 : 1534 : id = ns_info->id;
313 : :
314 : 1534 : G_UNLOCK (attribute_hash);
315 : :
316 : 1534 : return id;
317 : : }
318 : :
319 : : static char *
320 : 257 : get_attribute_for_id (int attribute)
321 : : {
322 : : char *s;
323 : 257 : G_LOCK (attribute_hash);
324 : 257 : s = global_attributes[GET_NS (attribute)][GET_ID (attribute)];
325 : 257 : G_UNLOCK (attribute_hash);
326 : 257 : return s;
327 : : }
328 : :
329 : : static guint32
330 : 4970 : lookup_attribute (const char *attribute)
331 : : {
332 : : guint32 attr_id;
333 : :
334 : 4970 : G_LOCK (attribute_hash);
335 : 4970 : ensure_attribute_hash ();
336 : :
337 : 4970 : attr_id = _lookup_attribute (attribute);
338 : :
339 : 4970 : G_UNLOCK (attribute_hash);
340 : :
341 : 4970 : return attr_id;
342 : : }
343 : :
344 : : static void
345 : 1146 : g_file_info_finalize (GObject *object)
346 : : {
347 : : GFileInfo *info;
348 : : guint i;
349 : : GFileAttribute *attrs;
350 : :
351 : 1146 : info = G_FILE_INFO (object);
352 : :
353 : 1146 : attrs = (GFileAttribute *)info->attributes->data;
354 : 7161 : for (i = 0; i < info->attributes->len; i++)
355 : 6015 : _g_file_attribute_value_clear (&attrs[i].value);
356 : 1146 : g_array_free (info->attributes, TRUE);
357 : :
358 : 1146 : if (info->mask != NO_ATTRIBUTE_MASK)
359 : 47 : g_file_attribute_matcher_unref (info->mask);
360 : :
361 : 1146 : G_OBJECT_CLASS (g_file_info_parent_class)->finalize (object);
362 : 1146 : }
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 : 1146 : g_file_info_init (GFileInfo *info)
374 : : {
375 : 1146 : info->mask = NO_ATTRIBUTE_MASK;
376 : 1146 : info->attributes = g_array_new (FALSE, FALSE,
377 : : sizeof (GFileAttribute));
378 : 1146 : }
379 : :
380 : : /**
381 : : * g_file_info_new:
382 : : *
383 : : * Creates a new file info structure.
384 : : *
385 : : * Returns: a #GFileInfo.
386 : : **/
387 : : GFileInfo *
388 : 1145 : g_file_info_new (void)
389 : : {
390 : 1145 : 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 : 1122 : g_file_info_set_attribute_mask (GFileInfo *info,
466 : : GFileAttributeMatcher *mask)
467 : : {
468 : : GFileAttribute *attr;
469 : : guint i;
470 : :
471 : 1122 : g_return_if_fail (G_IS_FILE_INFO (info));
472 : :
473 : 1122 : if (mask != info->mask)
474 : : {
475 : 1122 : if (info->mask != NO_ATTRIBUTE_MASK)
476 : 0 : g_file_attribute_matcher_unref (info->mask);
477 : 1122 : info->mask = g_file_attribute_matcher_ref (mask);
478 : :
479 : : /* Remove non-matching attributes */
480 : 1126 : 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 : 1075 : g_file_info_unset_attribute_mask (GFileInfo *info)
503 : : {
504 : 1075 : g_return_if_fail (G_IS_FILE_INFO (info));
505 : :
506 : 1075 : if (info->mask != NO_ATTRIBUTE_MASK)
507 : 1075 : g_file_attribute_matcher_unref (info->mask);
508 : 1075 : 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 : 38 : g_file_info_clear_status (GFileInfo *info)
519 : : {
520 : : GFileAttribute *attrs;
521 : : guint i;
522 : :
523 : 38 : g_return_if_fail (G_IS_FILE_INFO (info));
524 : :
525 : 38 : attrs = (GFileAttribute *)info->attributes->data;
526 : 237 : for (i = 0; i < info->attributes->len; i++)
527 : 199 : attrs[i].value.status = G_FILE_ATTRIBUTE_STATUS_UNSET;
528 : : }
529 : :
530 : : static int
531 : 9105 : 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 : 9105 : min = 0;
540 : 9105 : max = info->attributes->len;
541 : :
542 : 9105 : attrs = (GFileAttribute *)info->attributes->data;
543 : :
544 : 32670 : while (min < max)
545 : : {
546 : 26338 : med = min + (max - min) / 2;
547 : 26338 : if (attrs[med].attribute == attribute)
548 : : {
549 : 2773 : min = med;
550 : 2773 : break;
551 : : }
552 : 23565 : else if (attrs[med].attribute < attribute)
553 : 11467 : min = med + 1;
554 : : else /* attrs[med].attribute > attribute */
555 : 12098 : max = med;
556 : : }
557 : :
558 : 9105 : return min;
559 : : }
560 : :
561 : : static GFileAttributeValue *
562 : 2788 : g_file_info_find_value (GFileInfo *info,
563 : : guint32 attr_id)
564 : : {
565 : : GFileAttribute *attrs;
566 : : guint i;
567 : :
568 : 2788 : i = g_file_info_find_place (info, attr_id);
569 : 2788 : attrs = (GFileAttribute *)info->attributes->data;
570 : 2788 : if (i < info->attributes->len &&
571 : 2647 : attrs[i].attribute == attr_id)
572 : 2472 : return &attrs[i].value;
573 : :
574 : 316 : return NULL;
575 : : }
576 : :
577 : : static GFileAttributeValue *
578 : 1616 : g_file_info_find_value_by_name (GFileInfo *info,
579 : : const char *attribute)
580 : : {
581 : : guint32 attr_id;
582 : :
583 : 1616 : attr_id = lookup_attribute (attribute);
584 : 1616 : 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 : 41 : g_file_info_list_attributes (GFileInfo *info,
660 : : const char *name_space)
661 : : {
662 : : GPtrArray *names;
663 : : GFileAttribute *attrs;
664 : : guint32 attribute;
665 : 41 : guint32 ns_id = (name_space) ? lookup_namespace (name_space) : 0;
666 : : guint i;
667 : :
668 : 41 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
669 : :
670 : 41 : names = g_ptr_array_new ();
671 : 41 : attrs = (GFileAttribute *)info->attributes->data;
672 : 245 : for (i = 0; i < info->attributes->len; i++)
673 : : {
674 : 204 : attribute = attrs[i].attribute;
675 : 204 : if (ns_id == 0 || GET_NS (attribute) == ns_id)
676 : 408 : g_ptr_array_add (names, g_strdup (get_attribute_for_id (attribute)));
677 : : }
678 : :
679 : : /* NULL terminate */
680 : 41 : g_ptr_array_add (names, NULL);
681 : :
682 : 41 : 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 : 580 : _g_file_info_get_attribute_value (GFileInfo *info,
862 : : const char *attribute)
863 : :
864 : : {
865 : 580 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
866 : 580 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
867 : :
868 : 580 : 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 : 23330 : g_file_info_create_value (GFileInfo *info,
1154 : : guint32 attr_id)
1155 : : {
1156 : : GFileAttribute *attrs;
1157 : : guint i;
1158 : :
1159 : 45593 : if (info->mask != NO_ATTRIBUTE_MASK &&
1160 : 22263 : !_g_file_attribute_matcher_matches_id (info->mask, attr_id))
1161 : 17020 : return NULL;
1162 : :
1163 : 6310 : i = g_file_info_find_place (info, attr_id);
1164 : :
1165 : 6310 : attrs = (GFileAttribute *)info->attributes->data;
1166 : 6310 : if (i < info->attributes->len &&
1167 : 3478 : attrs[i].attribute == attr_id)
1168 : 296 : return &attrs[i].value;
1169 : : else
1170 : : {
1171 : 6014 : GFileAttribute attr = { 0 };
1172 : 6014 : attr.attribute = attr_id;
1173 : 6014 : g_array_insert_val (info->attributes, i, attr);
1174 : :
1175 : 6014 : attrs = (GFileAttribute *)info->attributes->data;
1176 : 6014 : 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 : 1644 : _g_file_info_set_attribute_boolean_by_id (GFileInfo *info,
1383 : : guint32 attribute,
1384 : : gboolean attr_value)
1385 : : {
1386 : : GFileAttributeValue *value;
1387 : :
1388 : 1644 : value = g_file_info_create_value (info, attribute);
1389 : 1644 : if (value)
1390 : 1050 : _g_file_attribute_value_set_boolean (value, attr_value);
1391 : 1644 : }
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 : 11046 : _g_file_info_set_attribute_uint32_by_id (GFileInfo *info,
1417 : : guint32 attribute,
1418 : : guint32 attr_value)
1419 : : {
1420 : : GFileAttributeValue *value;
1421 : :
1422 : 11046 : value = g_file_info_create_value (info, attribute);
1423 : 11046 : if (value)
1424 : 1550 : _g_file_attribute_value_set_uint32 (value, attr_value);
1425 : 11046 : }
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 : 5156 : _g_file_info_set_attribute_uint64_by_id (GFileInfo *info,
1485 : : guint32 attribute,
1486 : : guint64 attr_value)
1487 : : {
1488 : : GFileAttributeValue *value;
1489 : :
1490 : 5156 : value = g_file_info_create_value (info, attribute);
1491 : 5156 : if (value)
1492 : 617 : _g_file_attribute_value_set_uint64 (value, attr_value);
1493 : 5156 : }
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 : : * The exact semantics of what constitutes a backup file are
1658 : : * backend-specific. For local files, a file is considered a backup
1659 : : * if its name ends with `~` and it is a regular file. This follows
1660 : : * the POSIX convention used by text editors such as Emacs.
1661 : : *
1662 : : * It is an error to call this if the #GFileInfo does not contain
1663 : : * %G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP.
1664 : : *
1665 : : * Returns: %TRUE if file is a backup file, %FALSE otherwise.
1666 : : **/
1667 : : gboolean
1668 : 0 : g_file_info_get_is_backup (GFileInfo *info)
1669 : : {
1670 : : GFileAttributeValue *value;
1671 : :
1672 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1673 : :
1674 : 0 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP, FALSE);
1675 : 0 : return _g_file_attribute_value_get_boolean (value);
1676 : : }
1677 : :
1678 : : /**
1679 : : * g_file_info_get_is_symlink:
1680 : : * @info: a #GFileInfo.
1681 : : *
1682 : : * Checks if a file is a symlink.
1683 : : *
1684 : : * It is an error to call this if the #GFileInfo does not contain
1685 : : * %G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK.
1686 : : *
1687 : : * Returns: %TRUE if the given @info is a symlink.
1688 : : **/
1689 : : gboolean
1690 : 43 : g_file_info_get_is_symlink (GFileInfo *info)
1691 : : {
1692 : : GFileAttributeValue *value;
1693 : :
1694 : 43 : g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1695 : :
1696 : 43 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK, FALSE);
1697 : 43 : return _g_file_attribute_value_get_boolean (value);
1698 : : }
1699 : :
1700 : : /**
1701 : : * g_file_info_get_name:
1702 : : * @info: a #GFileInfo.
1703 : : *
1704 : : * Gets the name for a file. This is guaranteed to always be set.
1705 : : *
1706 : : * It is an error to call this if the #GFileInfo does not contain
1707 : : * %G_FILE_ATTRIBUTE_STANDARD_NAME.
1708 : : *
1709 : : * Returns: (type filename) (not nullable): a string containing the file name.
1710 : : **/
1711 : : const char *
1712 : 224 : g_file_info_get_name (GFileInfo *info)
1713 : : {
1714 : : GFileAttributeValue *value;
1715 : :
1716 : 224 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1717 : :
1718 : 224 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_NAME, NULL);
1719 : 224 : return _g_file_attribute_value_get_byte_string (value);
1720 : : }
1721 : :
1722 : : /**
1723 : : * g_file_info_get_display_name:
1724 : : * @info: a #GFileInfo.
1725 : : *
1726 : : * Gets a display name for a file. This is guaranteed to always be set.
1727 : : *
1728 : : * It is an error to call this if the #GFileInfo does not contain
1729 : : * %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME.
1730 : : *
1731 : : * Returns: (not nullable): a string containing the display name.
1732 : : **/
1733 : : const char *
1734 : 100 : g_file_info_get_display_name (GFileInfo *info)
1735 : : {
1736 : : GFileAttributeValue *value;
1737 : :
1738 : 100 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1739 : :
1740 : 100 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, NULL);
1741 : 100 : return _g_file_attribute_value_get_string (value);
1742 : : }
1743 : :
1744 : : /**
1745 : : * g_file_info_get_edit_name:
1746 : : * @info: a #GFileInfo.
1747 : : *
1748 : : * Gets the edit name for a file.
1749 : : *
1750 : : * It is an error to call this if the #GFileInfo does not contain
1751 : : * %G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME.
1752 : : *
1753 : : * Returns: a string containing the edit name.
1754 : : **/
1755 : : const char *
1756 : 42 : g_file_info_get_edit_name (GFileInfo *info)
1757 : : {
1758 : : GFileAttributeValue *value;
1759 : :
1760 : 42 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1761 : :
1762 : 42 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME, NULL);
1763 : 42 : return _g_file_attribute_value_get_string (value);
1764 : : }
1765 : :
1766 : : /**
1767 : : * g_file_info_get_icon:
1768 : : * @info: a #GFileInfo.
1769 : : *
1770 : : * Gets the icon for a file.
1771 : : *
1772 : : * It is an error to call this if the #GFileInfo does not contain
1773 : : * %G_FILE_ATTRIBUTE_STANDARD_ICON.
1774 : : *
1775 : : * Returns: (nullable) (transfer none): #GIcon for the given @info.
1776 : : **/
1777 : : GIcon *
1778 : 0 : g_file_info_get_icon (GFileInfo *info)
1779 : : {
1780 : : GFileAttributeValue *value;
1781 : : GObject *obj;
1782 : :
1783 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1784 : :
1785 : 0 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_ICON, NULL);
1786 : :
1787 : 0 : obj = _g_file_attribute_value_get_object (value);
1788 : 0 : if (G_IS_ICON (obj))
1789 : 0 : return G_ICON (obj);
1790 : 0 : return NULL;
1791 : : }
1792 : :
1793 : : /**
1794 : : * g_file_info_get_symbolic_icon:
1795 : : * @info: a #GFileInfo.
1796 : : *
1797 : : * Gets the symbolic icon for a file.
1798 : : *
1799 : : * It is an error to call this if the #GFileInfo does not contain
1800 : : * %G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON.
1801 : : *
1802 : : * Returns: (nullable) (transfer none): #GIcon for the given @info.
1803 : : *
1804 : : * Since: 2.34
1805 : : **/
1806 : : GIcon *
1807 : 0 : g_file_info_get_symbolic_icon (GFileInfo *info)
1808 : : {
1809 : : GFileAttributeValue *value;
1810 : : GObject *obj;
1811 : :
1812 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1813 : :
1814 : 0 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON, NULL);
1815 : :
1816 : 0 : obj = _g_file_attribute_value_get_object (value);
1817 : 0 : if (G_IS_ICON (obj))
1818 : 0 : return G_ICON (obj);
1819 : 0 : return NULL;
1820 : : }
1821 : :
1822 : : /**
1823 : : * g_file_info_get_content_type:
1824 : : * @info: a #GFileInfo.
1825 : : *
1826 : : * Gets the file's content type.
1827 : : *
1828 : : * It is an error to call this if the #GFileInfo does not contain
1829 : : * %G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE.
1830 : : *
1831 : : * Returns: (nullable): a string containing the file's content type,
1832 : : * or %NULL if unknown.
1833 : : **/
1834 : : const char *
1835 : 8 : g_file_info_get_content_type (GFileInfo *info)
1836 : : {
1837 : : GFileAttributeValue *value;
1838 : :
1839 : 8 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1840 : :
1841 : 8 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, NULL);
1842 : 8 : return _g_file_attribute_value_get_string (value);
1843 : : }
1844 : :
1845 : : /**
1846 : : * g_file_info_get_size:
1847 : : * @info: a #GFileInfo.
1848 : : *
1849 : : * Gets the file's size (in bytes). The size is retrieved through the value of
1850 : : * the %G_FILE_ATTRIBUTE_STANDARD_SIZE attribute and is converted
1851 : : * from #guint64 to #goffset before returning the result.
1852 : : *
1853 : : * It is an error to call this if the #GFileInfo does not contain
1854 : : * %G_FILE_ATTRIBUTE_STANDARD_SIZE.
1855 : : *
1856 : : * Returns: a #goffset containing the file's size (in bytes).
1857 : : **/
1858 : : goffset
1859 : 187 : g_file_info_get_size (GFileInfo *info)
1860 : : {
1861 : : GFileAttributeValue *value;
1862 : :
1863 : 187 : g_return_val_if_fail (G_IS_FILE_INFO (info), (goffset) 0);
1864 : :
1865 : 187 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SIZE, (goffset) 0);
1866 : 187 : return (goffset) _g_file_attribute_value_get_uint64 (value);
1867 : : }
1868 : :
1869 : : /**
1870 : : * g_file_info_get_modification_time:
1871 : : * @info: a #GFileInfo.
1872 : : * @result: (out caller-allocates): a #GTimeVal.
1873 : : *
1874 : : * Gets the modification time of the current @info and sets it
1875 : : * in @result.
1876 : : *
1877 : : * It is an error to call this if the #GFileInfo does not contain
1878 : : * %G_FILE_ATTRIBUTE_TIME_MODIFIED. If %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC is
1879 : : * provided it will be used too.
1880 : : *
1881 : : * Deprecated: 2.62: Use g_file_info_get_modification_date_time() instead, as
1882 : : * #GTimeVal is deprecated due to the year 2038 problem.
1883 : : **/
1884 : : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1885 : : void
1886 : 0 : g_file_info_get_modification_time (GFileInfo *info,
1887 : : GTimeVal *result)
1888 : : {
1889 : : static guint32 attr_mtime = 0, attr_mtime_usec;
1890 : : GFileAttributeValue *value;
1891 : :
1892 : 0 : g_return_if_fail (G_IS_FILE_INFO (info));
1893 : 0 : g_return_if_fail (result != NULL);
1894 : :
1895 : 0 : if (attr_mtime == 0)
1896 : : {
1897 : 0 : attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1898 : 0 : attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1899 : : }
1900 : :
1901 : 0 : value = g_file_info_find_value (info, attr_mtime);
1902 : :
1903 : 0 : if (G_UNLIKELY (value == NULL))
1904 : : {
1905 : 0 : g_critical ("GFileInfo created without " G_FILE_ATTRIBUTE_TIME_MODIFIED);
1906 : 0 : result->tv_sec = result->tv_usec = 0;
1907 : : g_return_if_reached ();
1908 : : }
1909 : :
1910 : 0 : result->tv_sec = _g_file_attribute_value_get_uint64 (value);
1911 : 0 : value = g_file_info_find_value (info, attr_mtime_usec);
1912 : 0 : result->tv_usec = _g_file_attribute_value_get_uint32 (value);
1913 : : }
1914 : : G_GNUC_END_IGNORE_DEPRECATIONS
1915 : :
1916 : : /**
1917 : : * g_file_info_get_modification_date_time:
1918 : : * @info: a #GFileInfo.
1919 : : *
1920 : : * Gets the modification time of the current @info and returns it as a
1921 : : * #GDateTime.
1922 : : *
1923 : : * It is an error to call this if the #GFileInfo does not contain
1924 : : * %G_FILE_ATTRIBUTE_TIME_MODIFIED. If %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC is
1925 : : * provided, the resulting #GDateTime will additionally have microsecond
1926 : : * precision.
1927 : : *
1928 : : * If nanosecond precision is needed, %G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC must
1929 : : * be queried separately using g_file_info_get_attribute_uint32().
1930 : : *
1931 : : * Returns: (transfer full) (nullable): modification time, or %NULL if unknown
1932 : : * Since: 2.62
1933 : : */
1934 : : GDateTime *
1935 : 4 : g_file_info_get_modification_date_time (GFileInfo *info)
1936 : : {
1937 : : static guint32 attr_mtime = 0, attr_mtime_usec;
1938 : : GFileAttributeValue *value, *value_usec;
1939 : 4 : GDateTime *dt = NULL, *dt2 = NULL;
1940 : :
1941 : 4 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1942 : :
1943 : 4 : if (attr_mtime == 0)
1944 : : {
1945 : 1 : attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1946 : 1 : attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1947 : : }
1948 : :
1949 : 4 : value = g_file_info_find_value (info, attr_mtime);
1950 : 4 : if (value == NULL)
1951 : 0 : return NULL;
1952 : :
1953 : 4 : dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value));
1954 : :
1955 : 4 : value_usec = g_file_info_find_value (info, attr_mtime_usec);
1956 : 4 : if (value_usec == NULL)
1957 : 1 : return g_steal_pointer (&dt);
1958 : :
1959 : 3 : dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec));
1960 : 3 : g_date_time_unref (dt);
1961 : :
1962 : 3 : return g_steal_pointer (&dt2);
1963 : : }
1964 : :
1965 : : /**
1966 : : * g_file_info_get_access_date_time:
1967 : : * @info: a #GFileInfo.
1968 : : *
1969 : : * Gets the access time of the current @info and returns it as a
1970 : : * #GDateTime.
1971 : : *
1972 : : * It is an error to call this if the #GFileInfo does not contain
1973 : : * %G_FILE_ATTRIBUTE_TIME_ACCESS. If %G_FILE_ATTRIBUTE_TIME_ACCESS_USEC is
1974 : : * provided, the resulting #GDateTime will additionally have microsecond
1975 : : * precision.
1976 : : *
1977 : : * If nanosecond precision is needed, %G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC must
1978 : : * be queried separately using g_file_info_get_attribute_uint32().
1979 : : *
1980 : : * Returns: (transfer full) (nullable): access time, or %NULL if unknown
1981 : : * Since: 2.70
1982 : : */
1983 : : GDateTime *
1984 : 5 : g_file_info_get_access_date_time (GFileInfo *info)
1985 : : {
1986 : : static guint32 attr_atime = 0, attr_atime_usec;
1987 : : GFileAttributeValue *value, *value_usec;
1988 : 5 : GDateTime *dt = NULL, *dt2 = NULL;
1989 : :
1990 : 5 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1991 : :
1992 : 5 : if (attr_atime == 0)
1993 : : {
1994 : 1 : attr_atime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS);
1995 : 1 : attr_atime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_USEC);
1996 : : }
1997 : :
1998 : 5 : value = g_file_info_find_value (info, attr_atime);
1999 : 5 : if (value == NULL)
2000 : 0 : return NULL;
2001 : :
2002 : 5 : dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value));
2003 : :
2004 : 5 : value_usec = g_file_info_find_value (info, attr_atime_usec);
2005 : 5 : if (value_usec == NULL)
2006 : 1 : return g_steal_pointer (&dt);
2007 : :
2008 : 4 : dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec));
2009 : 4 : g_date_time_unref (dt);
2010 : :
2011 : 4 : return g_steal_pointer (&dt2);
2012 : : }
2013 : :
2014 : : /**
2015 : : * g_file_info_get_creation_date_time:
2016 : : * @info: a #GFileInfo.
2017 : : *
2018 : : * Gets the creation time of the current @info and returns it as a
2019 : : * #GDateTime.
2020 : : *
2021 : : * It is an error to call this if the #GFileInfo does not contain
2022 : : * %G_FILE_ATTRIBUTE_TIME_CREATED. If %G_FILE_ATTRIBUTE_TIME_CREATED_USEC is
2023 : : * provided, the resulting #GDateTime will additionally have microsecond
2024 : : * precision.
2025 : : *
2026 : : * If nanosecond precision is needed, %G_FILE_ATTRIBUTE_TIME_CREATED_NSEC must
2027 : : * be queried separately using g_file_info_get_attribute_uint32().
2028 : : *
2029 : : * Returns: (transfer full) (nullable): creation time, or %NULL if unknown
2030 : : * Since: 2.70
2031 : : */
2032 : : GDateTime *
2033 : 4 : g_file_info_get_creation_date_time (GFileInfo *info)
2034 : : {
2035 : : static guint32 attr_ctime = 0, attr_ctime_usec;
2036 : : GFileAttributeValue *value, *value_usec;
2037 : 4 : GDateTime *dt = NULL, *dt2 = NULL;
2038 : :
2039 : 4 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
2040 : :
2041 : 4 : if (attr_ctime == 0)
2042 : : {
2043 : 1 : attr_ctime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED);
2044 : 1 : attr_ctime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_USEC);
2045 : : }
2046 : :
2047 : 4 : value = g_file_info_find_value (info, attr_ctime);
2048 : 4 : if (value == NULL)
2049 : 0 : return NULL;
2050 : :
2051 : 4 : dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value));
2052 : :
2053 : 4 : value_usec = g_file_info_find_value (info, attr_ctime_usec);
2054 : 4 : if (value_usec == NULL)
2055 : 1 : return g_steal_pointer (&dt);
2056 : :
2057 : 3 : dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec));
2058 : 3 : g_date_time_unref (dt);
2059 : :
2060 : 3 : return g_steal_pointer (&dt2);
2061 : : }
2062 : :
2063 : : /**
2064 : : * g_file_info_get_symlink_target:
2065 : : * @info: a #GFileInfo.
2066 : : *
2067 : : * Gets the symlink target for a given #GFileInfo.
2068 : : *
2069 : : * It is an error to call this if the #GFileInfo does not contain
2070 : : * %G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET.
2071 : : *
2072 : : * Returns: (type filename) (nullable): a string containing the symlink target.
2073 : : **/
2074 : : const char *
2075 : 55 : g_file_info_get_symlink_target (GFileInfo *info)
2076 : : {
2077 : : GFileAttributeValue *value;
2078 : :
2079 : 55 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
2080 : :
2081 : 55 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET, NULL);
2082 : 55 : return _g_file_attribute_value_get_byte_string (value);
2083 : : }
2084 : :
2085 : : /**
2086 : : * g_file_info_get_etag:
2087 : : * @info: a #GFileInfo.
2088 : : *
2089 : : * Gets the [entity tag][iface@Gio.File#entity-tags] for a given
2090 : : * #GFileInfo. See %G_FILE_ATTRIBUTE_ETAG_VALUE.
2091 : : *
2092 : : * It is an error to call this if the #GFileInfo does not contain
2093 : : * %G_FILE_ATTRIBUTE_ETAG_VALUE.
2094 : : *
2095 : : * Returns: (nullable): a string containing the value of the "etag:value" attribute.
2096 : : **/
2097 : : const char *
2098 : 4 : g_file_info_get_etag (GFileInfo *info)
2099 : : {
2100 : : GFileAttributeValue *value;
2101 : :
2102 : 4 : g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
2103 : :
2104 : 4 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_ETAG_VALUE, NULL);
2105 : 4 : return _g_file_attribute_value_get_string (value);
2106 : : }
2107 : :
2108 : : /**
2109 : : * g_file_info_get_sort_order:
2110 : : * @info: a #GFileInfo.
2111 : : *
2112 : : * Gets the value of the sort_order attribute from the #GFileInfo.
2113 : : * See %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
2114 : : *
2115 : : * It is an error to call this if the #GFileInfo does not contain
2116 : : * %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
2117 : : *
2118 : : * Returns: a #gint32 containing the value of the "standard::sort_order" attribute.
2119 : : **/
2120 : : gint32
2121 : 0 : g_file_info_get_sort_order (GFileInfo *info)
2122 : : {
2123 : : GFileAttributeValue *value;
2124 : :
2125 : 0 : g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
2126 : :
2127 : 0 : get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER, 0);
2128 : 0 : return _g_file_attribute_value_get_int32 (value);
2129 : : }
2130 : :
2131 : : /* Helper setters: */
2132 : : /**
2133 : : * g_file_info_set_file_type:
2134 : : * @info: a #GFileInfo.
2135 : : * @type: a #GFileType.
2136 : : *
2137 : : * Sets the file type in a #GFileInfo to @type.
2138 : : * See %G_FILE_ATTRIBUTE_STANDARD_TYPE.
2139 : : **/
2140 : : void
2141 : 1133 : g_file_info_set_file_type (GFileInfo *info,
2142 : : GFileType type)
2143 : : {
2144 : : static guint32 attr = 0;
2145 : : GFileAttributeValue *value;
2146 : :
2147 : 1133 : g_return_if_fail (G_IS_FILE_INFO (info));
2148 : :
2149 : 1133 : if (attr == 0)
2150 : 11 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_TYPE);
2151 : :
2152 : 1133 : value = g_file_info_create_value (info, attr);
2153 : 1133 : if (value)
2154 : 762 : _g_file_attribute_value_set_uint32 (value, type);
2155 : : }
2156 : :
2157 : : /**
2158 : : * g_file_info_set_is_hidden:
2159 : : * @info: a #GFileInfo.
2160 : : * @is_hidden: a #gboolean.
2161 : : *
2162 : : * Sets the "is_hidden" attribute in a #GFileInfo according to @is_hidden.
2163 : : * See %G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN.
2164 : : **/
2165 : : void
2166 : 76 : g_file_info_set_is_hidden (GFileInfo *info,
2167 : : gboolean is_hidden)
2168 : : {
2169 : : static guint32 attr = 0;
2170 : : GFileAttributeValue *value;
2171 : :
2172 : 76 : g_return_if_fail (G_IS_FILE_INFO (info));
2173 : :
2174 : 76 : if (attr == 0)
2175 : 1 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
2176 : :
2177 : 76 : value = g_file_info_create_value (info, attr);
2178 : 76 : if (value)
2179 : 76 : _g_file_attribute_value_set_boolean (value, is_hidden);
2180 : : }
2181 : :
2182 : : /**
2183 : : * g_file_info_set_is_symlink:
2184 : : * @info: a #GFileInfo.
2185 : : * @is_symlink: a #gboolean.
2186 : : *
2187 : : * Sets the "is_symlink" attribute in a #GFileInfo according to @is_symlink.
2188 : : * See %G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK.
2189 : : **/
2190 : : void
2191 : 693 : g_file_info_set_is_symlink (GFileInfo *info,
2192 : : gboolean is_symlink)
2193 : : {
2194 : : static guint32 attr = 0;
2195 : : GFileAttributeValue *value;
2196 : :
2197 : 693 : g_return_if_fail (G_IS_FILE_INFO (info));
2198 : :
2199 : 693 : if (attr == 0)
2200 : 9 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
2201 : :
2202 : 693 : value = g_file_info_create_value (info, attr);
2203 : 693 : if (value)
2204 : 100 : _g_file_attribute_value_set_boolean (value, is_symlink);
2205 : : }
2206 : :
2207 : : /**
2208 : : * g_file_info_set_name:
2209 : : * @info: a #GFileInfo.
2210 : : * @name: (type filename): a string containing a name.
2211 : : *
2212 : : * Sets the name attribute for the current #GFileInfo.
2213 : : * See %G_FILE_ATTRIBUTE_STANDARD_NAME.
2214 : : **/
2215 : : void
2216 : 1455 : g_file_info_set_name (GFileInfo *info,
2217 : : const char *name)
2218 : : {
2219 : : static guint32 attr = 0;
2220 : : GFileAttributeValue *value;
2221 : :
2222 : 1455 : g_return_if_fail (G_IS_FILE_INFO (info));
2223 : 1455 : g_return_if_fail (name != NULL);
2224 : :
2225 : 1455 : if (attr == 0)
2226 : 12 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_NAME);
2227 : :
2228 : 1455 : value = g_file_info_create_value (info, attr);
2229 : 1455 : if (value)
2230 : 478 : _g_file_attribute_value_set_byte_string (value, name);
2231 : : }
2232 : :
2233 : : /**
2234 : : * g_file_info_set_display_name:
2235 : : * @info: a #GFileInfo.
2236 : : * @display_name: a string containing a display name.
2237 : : *
2238 : : * Sets the display name for the current #GFileInfo.
2239 : : * See %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME.
2240 : : **/
2241 : : void
2242 : 135 : g_file_info_set_display_name (GFileInfo *info,
2243 : : const char *display_name)
2244 : : {
2245 : : static guint32 attr = 0;
2246 : : GFileAttributeValue *value;
2247 : :
2248 : 135 : g_return_if_fail (G_IS_FILE_INFO (info));
2249 : 135 : g_return_if_fail (display_name != NULL);
2250 : :
2251 : 135 : if (attr == 0)
2252 : 2 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
2253 : :
2254 : 135 : value = g_file_info_create_value (info, attr);
2255 : 135 : if (value)
2256 : 135 : _g_file_attribute_value_set_string (value, display_name);
2257 : : }
2258 : :
2259 : : /**
2260 : : * g_file_info_set_edit_name:
2261 : : * @info: a #GFileInfo.
2262 : : * @edit_name: a string containing an edit name.
2263 : : *
2264 : : * Sets the edit name for the current file.
2265 : : * See %G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME.
2266 : : **/
2267 : : void
2268 : 131 : g_file_info_set_edit_name (GFileInfo *info,
2269 : : const char *edit_name)
2270 : : {
2271 : : static guint32 attr = 0;
2272 : : GFileAttributeValue *value;
2273 : :
2274 : 131 : g_return_if_fail (G_IS_FILE_INFO (info));
2275 : 131 : g_return_if_fail (edit_name != NULL);
2276 : :
2277 : 131 : if (attr == 0)
2278 : 1 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
2279 : :
2280 : 131 : value = g_file_info_create_value (info, attr);
2281 : 131 : if (value)
2282 : 131 : _g_file_attribute_value_set_string (value, edit_name);
2283 : : }
2284 : :
2285 : : /**
2286 : : * g_file_info_set_icon:
2287 : : * @info: a #GFileInfo.
2288 : : * @icon: a #GIcon.
2289 : : *
2290 : : * Sets the icon for a given #GFileInfo.
2291 : : * See %G_FILE_ATTRIBUTE_STANDARD_ICON.
2292 : : **/
2293 : : void
2294 : 76 : g_file_info_set_icon (GFileInfo *info,
2295 : : GIcon *icon)
2296 : : {
2297 : : static guint32 attr = 0;
2298 : : GFileAttributeValue *value;
2299 : :
2300 : 76 : g_return_if_fail (G_IS_FILE_INFO (info));
2301 : 76 : g_return_if_fail (G_IS_ICON (icon));
2302 : :
2303 : 76 : if (attr == 0)
2304 : 1 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_ICON);
2305 : :
2306 : 76 : value = g_file_info_create_value (info, attr);
2307 : 76 : if (value)
2308 : 76 : _g_file_attribute_value_set_object (value, G_OBJECT (icon));
2309 : : }
2310 : :
2311 : : /**
2312 : : * g_file_info_set_symbolic_icon:
2313 : : * @info: a #GFileInfo.
2314 : : * @icon: a #GIcon.
2315 : : *
2316 : : * Sets the symbolic icon for a given #GFileInfo.
2317 : : * See %G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON.
2318 : : *
2319 : : * Since: 2.34
2320 : : **/
2321 : : void
2322 : 76 : g_file_info_set_symbolic_icon (GFileInfo *info,
2323 : : GIcon *icon)
2324 : : {
2325 : : static guint32 attr = 0;
2326 : : GFileAttributeValue *value;
2327 : :
2328 : 76 : g_return_if_fail (G_IS_FILE_INFO (info));
2329 : 76 : g_return_if_fail (G_IS_ICON (icon));
2330 : :
2331 : 76 : if (attr == 0)
2332 : 1 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON);
2333 : :
2334 : 76 : value = g_file_info_create_value (info, attr);
2335 : 76 : if (value)
2336 : 76 : _g_file_attribute_value_set_object (value, G_OBJECT (icon));
2337 : : }
2338 : :
2339 : : /**
2340 : : * g_file_info_set_content_type:
2341 : : * @info: a #GFileInfo.
2342 : : * @content_type: a [content type](content-types.html#content-types).
2343 : : *
2344 : : * Sets the content type attribute for a given #GFileInfo.
2345 : : * See %G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE.
2346 : : **/
2347 : : void
2348 : 84 : g_file_info_set_content_type (GFileInfo *info,
2349 : : const char *content_type)
2350 : : {
2351 : : static guint32 attr = 0;
2352 : : GFileAttributeValue *value;
2353 : :
2354 : 84 : g_return_if_fail (G_IS_FILE_INFO (info));
2355 : 84 : g_return_if_fail (content_type != NULL);
2356 : :
2357 : 84 : if (attr == 0)
2358 : 4 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
2359 : :
2360 : 84 : value = g_file_info_create_value (info, attr);
2361 : 84 : if (value)
2362 : 84 : _g_file_attribute_value_set_string (value, content_type);
2363 : : }
2364 : :
2365 : : /**
2366 : : * g_file_info_set_size:
2367 : : * @info: a #GFileInfo.
2368 : : * @size: a #goffset containing the file's size.
2369 : : *
2370 : : * Sets the %G_FILE_ATTRIBUTE_STANDARD_SIZE attribute in the file info
2371 : : * to the given size.
2372 : : **/
2373 : : void
2374 : 740 : g_file_info_set_size (GFileInfo *info,
2375 : : goffset size)
2376 : : {
2377 : : static guint32 attr = 0;
2378 : : GFileAttributeValue *value;
2379 : :
2380 : 740 : g_return_if_fail (G_IS_FILE_INFO (info));
2381 : :
2382 : 740 : if (attr == 0)
2383 : 10 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SIZE);
2384 : :
2385 : 740 : value = g_file_info_create_value (info, attr);
2386 : 740 : if (value)
2387 : 290 : _g_file_attribute_value_set_uint64 (value, size);
2388 : : }
2389 : :
2390 : : /**
2391 : : * g_file_info_set_modification_time:
2392 : : * @info: a #GFileInfo.
2393 : : * @mtime: a #GTimeVal.
2394 : : *
2395 : : * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED and
2396 : : * %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC attributes in the file info to the
2397 : : * given time value.
2398 : : *
2399 : : * %G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC will be cleared.
2400 : : *
2401 : : * Deprecated: 2.62: Use g_file_info_set_modification_date_time() instead, as
2402 : : * #GTimeVal is deprecated due to the year 2038 problem.
2403 : : **/
2404 : : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2405 : : void
2406 : 0 : g_file_info_set_modification_time (GFileInfo *info,
2407 : : GTimeVal *mtime)
2408 : : {
2409 : : static guint32 attr_mtime = 0, attr_mtime_usec = 0, attr_mtime_nsec = 0;
2410 : : GFileAttributeValue *value;
2411 : :
2412 : 0 : g_return_if_fail (G_IS_FILE_INFO (info));
2413 : 0 : g_return_if_fail (mtime != NULL);
2414 : :
2415 : 0 : if (attr_mtime == 0)
2416 : : {
2417 : 0 : attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
2418 : 0 : attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
2419 : 0 : attr_mtime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
2420 : : }
2421 : :
2422 : 0 : value = g_file_info_create_value (info, attr_mtime);
2423 : 0 : if (value)
2424 : 0 : _g_file_attribute_value_set_uint64 (value, mtime->tv_sec);
2425 : 0 : value = g_file_info_create_value (info, attr_mtime_usec);
2426 : 0 : if (value)
2427 : 0 : _g_file_attribute_value_set_uint32 (value, mtime->tv_usec);
2428 : :
2429 : : /* nsecs can’t be known from a #GTimeVal, so remove them */
2430 : 0 : g_file_info_remove_value (info, attr_mtime_nsec);
2431 : : }
2432 : : G_GNUC_END_IGNORE_DEPRECATIONS
2433 : :
2434 : : /**
2435 : : * g_file_info_set_modification_date_time:
2436 : : * @info: a #GFileInfo.
2437 : : * @mtime: (not nullable): a #GDateTime.
2438 : : *
2439 : : * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED and
2440 : : * %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC attributes in the file info to the
2441 : : * given date/time value.
2442 : : *
2443 : : * %G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC will be cleared.
2444 : : *
2445 : : * Since: 2.62
2446 : : */
2447 : : void
2448 : 2 : g_file_info_set_modification_date_time (GFileInfo *info,
2449 : : GDateTime *mtime)
2450 : : {
2451 : : static guint32 attr_mtime = 0, attr_mtime_usec = 0, attr_mtime_nsec = 0;
2452 : : GFileAttributeValue *value;
2453 : :
2454 : 2 : g_return_if_fail (G_IS_FILE_INFO (info));
2455 : 2 : g_return_if_fail (mtime != NULL);
2456 : :
2457 : 2 : if (attr_mtime == 0)
2458 : : {
2459 : 1 : attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
2460 : 1 : attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
2461 : 1 : attr_mtime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
2462 : : }
2463 : :
2464 : 2 : value = g_file_info_create_value (info, attr_mtime);
2465 : 2 : if (value)
2466 : 2 : _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (mtime));
2467 : 2 : value = g_file_info_create_value (info, attr_mtime_usec);
2468 : 2 : if (value)
2469 : 2 : _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (mtime));
2470 : :
2471 : : /* nsecs can’t be known from a #GDateTime, so remove them */
2472 : 2 : g_file_info_remove_value (info, attr_mtime_nsec);
2473 : : }
2474 : :
2475 : : /**
2476 : : * g_file_info_set_access_date_time:
2477 : : * @info: a #GFileInfo.
2478 : : * @atime: (not nullable): a #GDateTime.
2479 : : *
2480 : : * Sets the %G_FILE_ATTRIBUTE_TIME_ACCESS and
2481 : : * %G_FILE_ATTRIBUTE_TIME_ACCESS_USEC attributes in the file info to the
2482 : : * given date/time value.
2483 : : *
2484 : : * %G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC will be cleared.
2485 : : *
2486 : : * Since: 2.70
2487 : : */
2488 : : void
2489 : 2 : g_file_info_set_access_date_time (GFileInfo *info,
2490 : : GDateTime *atime)
2491 : : {
2492 : : static guint32 attr_atime = 0, attr_atime_usec = 0, attr_atime_nsec = 0;
2493 : : GFileAttributeValue *value;
2494 : :
2495 : 2 : g_return_if_fail (G_IS_FILE_INFO (info));
2496 : 2 : g_return_if_fail (atime != NULL);
2497 : :
2498 : 2 : if (attr_atime == 0)
2499 : : {
2500 : 1 : attr_atime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS);
2501 : 1 : attr_atime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_USEC);
2502 : 1 : attr_atime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC);
2503 : : }
2504 : :
2505 : 2 : value = g_file_info_create_value (info, attr_atime);
2506 : 2 : if (value)
2507 : 2 : _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (atime));
2508 : 2 : value = g_file_info_create_value (info, attr_atime_usec);
2509 : 2 : if (value)
2510 : 2 : _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (atime));
2511 : :
2512 : : /* nsecs can’t be known from a #GDateTime, so remove them */
2513 : 2 : g_file_info_remove_value (info, attr_atime_nsec);
2514 : : }
2515 : :
2516 : : /**
2517 : : * g_file_info_set_creation_date_time:
2518 : : * @info: a #GFileInfo.
2519 : : * @creation_time: (not nullable): a #GDateTime.
2520 : : *
2521 : : * Sets the %G_FILE_ATTRIBUTE_TIME_CREATED and
2522 : : * %G_FILE_ATTRIBUTE_TIME_CREATED_USEC attributes in the file info to the
2523 : : * given date/time value.
2524 : : *
2525 : : * %G_FILE_ATTRIBUTE_TIME_CREATED_NSEC will be cleared.
2526 : : *
2527 : : * Since: 2.70
2528 : : */
2529 : : void
2530 : 2 : g_file_info_set_creation_date_time (GFileInfo *info,
2531 : : GDateTime *creation_time)
2532 : : {
2533 : : static guint32 attr_ctime = 0, attr_ctime_usec = 0, attr_ctime_nsec = 0;
2534 : : GFileAttributeValue *value;
2535 : :
2536 : 2 : g_return_if_fail (G_IS_FILE_INFO (info));
2537 : 2 : g_return_if_fail (creation_time != NULL);
2538 : :
2539 : 2 : if (attr_ctime == 0)
2540 : : {
2541 : 1 : attr_ctime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED);
2542 : 1 : attr_ctime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_USEC);
2543 : 1 : attr_ctime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_NSEC);
2544 : : }
2545 : :
2546 : 2 : value = g_file_info_create_value (info, attr_ctime);
2547 : 2 : if (value)
2548 : 2 : _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (creation_time));
2549 : 2 : value = g_file_info_create_value (info, attr_ctime_usec);
2550 : 2 : if (value)
2551 : 2 : _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (creation_time));
2552 : :
2553 : : /* nsecs can’t be known from a #GDateTime, so remove them */
2554 : 2 : g_file_info_remove_value (info, attr_ctime_nsec);
2555 : : }
2556 : :
2557 : : /**
2558 : : * g_file_info_set_symlink_target:
2559 : : * @info: a #GFileInfo.
2560 : : * @symlink_target: (type filename): a static string containing a path to a symlink target.
2561 : : *
2562 : : * Sets the %G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET attribute in the file info
2563 : : * to the given symlink target.
2564 : : **/
2565 : : void
2566 : 43 : g_file_info_set_symlink_target (GFileInfo *info,
2567 : : const char *symlink_target)
2568 : : {
2569 : : static guint32 attr = 0;
2570 : : GFileAttributeValue *value;
2571 : :
2572 : 43 : g_return_if_fail (G_IS_FILE_INFO (info));
2573 : 43 : g_return_if_fail (symlink_target != NULL);
2574 : :
2575 : 43 : if (attr == 0)
2576 : 3 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET);
2577 : :
2578 : 43 : value = g_file_info_create_value (info, attr);
2579 : 43 : if (value)
2580 : 43 : _g_file_attribute_value_set_byte_string (value, symlink_target);
2581 : : }
2582 : :
2583 : : /**
2584 : : * g_file_info_set_sort_order:
2585 : : * @info: a #GFileInfo.
2586 : : * @sort_order: a sort order integer.
2587 : : *
2588 : : * Sets the sort order attribute in the file info structure. See
2589 : : * %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
2590 : : **/
2591 : : void
2592 : 0 : g_file_info_set_sort_order (GFileInfo *info,
2593 : : gint32 sort_order)
2594 : : {
2595 : : static guint32 attr = 0;
2596 : : GFileAttributeValue *value;
2597 : :
2598 : 0 : g_return_if_fail (G_IS_FILE_INFO (info));
2599 : :
2600 : 0 : if (attr == 0)
2601 : 0 : attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER);
2602 : :
2603 : 0 : value = g_file_info_create_value (info, attr);
2604 : 0 : if (value)
2605 : 0 : _g_file_attribute_value_set_int32 (value, sort_order);
2606 : : }
2607 : :
2608 : :
2609 : : typedef struct {
2610 : : guint32 id;
2611 : : guint32 mask;
2612 : : } SubMatcher;
2613 : :
2614 : : struct _GFileAttributeMatcher {
2615 : : gboolean all;
2616 : : gint ref;
2617 : :
2618 : : GArray *sub_matchers;
2619 : :
2620 : : /* Iterator */
2621 : : guint32 iterator_ns;
2622 : : gint iterator_pos;
2623 : : };
2624 : :
2625 : 4 : G_DEFINE_BOXED_TYPE (GFileAttributeMatcher, g_file_attribute_matcher,
2626 : : g_file_attribute_matcher_ref,
2627 : : g_file_attribute_matcher_unref)
2628 : :
2629 : : static gint
2630 : 3440 : compare_sub_matchers (gconstpointer a,
2631 : : gconstpointer b)
2632 : : {
2633 : 3440 : const SubMatcher *suba = a;
2634 : 3440 : const SubMatcher *subb = b;
2635 : : int diff;
2636 : :
2637 : 3440 : diff = suba->id - subb->id;
2638 : :
2639 : 3440 : if (diff)
2640 : 3437 : return diff;
2641 : :
2642 : 3 : return suba->mask - subb->mask;
2643 : : }
2644 : :
2645 : : static gboolean
2646 : 2548 : sub_matcher_matches (SubMatcher *matcher,
2647 : : SubMatcher *submatcher)
2648 : : {
2649 : 2548 : if ((matcher->mask & submatcher->mask) != matcher->mask)
2650 : 128 : return FALSE;
2651 : :
2652 : 2420 : return matcher->id == (submatcher->id & matcher->mask);
2653 : : }
2654 : :
2655 : : /* Call this function after modifying a matcher.
2656 : : * It will ensure all the invariants other functions rely on.
2657 : : */
2658 : : static GFileAttributeMatcher *
2659 : 1575 : matcher_optimize (GFileAttributeMatcher *matcher)
2660 : : {
2661 : : SubMatcher *submatcher, *compare;
2662 : : guint i, j;
2663 : :
2664 : : /* remove sub_matchers if we match everything anyway */
2665 : 1575 : if (matcher->all)
2666 : : {
2667 : 64 : if (matcher->sub_matchers)
2668 : : {
2669 : 64 : g_array_free (matcher->sub_matchers, TRUE);
2670 : 64 : matcher->sub_matchers = NULL;
2671 : : }
2672 : 64 : return matcher;
2673 : : }
2674 : :
2675 : 1511 : if (matcher->sub_matchers->len == 0)
2676 : : {
2677 : 222 : g_file_attribute_matcher_unref (matcher);
2678 : 222 : return NULL;
2679 : : }
2680 : :
2681 : : /* sort sub_matchers by id (and then mask), so we can bsearch
2682 : : * and compare matchers in O(N) instead of O(N²) */
2683 : 1289 : g_array_sort (matcher->sub_matchers, compare_sub_matchers);
2684 : :
2685 : : /* remove duplicates and specific matches when we match the whole namespace */
2686 : 1289 : j = 0;
2687 : 1289 : compare = &g_array_index (matcher->sub_matchers, SubMatcher, j);
2688 : :
2689 : 3333 : for (i = 1; i < matcher->sub_matchers->len; i++)
2690 : : {
2691 : 2044 : submatcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
2692 : 2044 : if (sub_matcher_matches (compare, submatcher))
2693 : 7 : continue;
2694 : :
2695 : 2037 : j++;
2696 : 2037 : compare++;
2697 : :
2698 : 2037 : if (j < i)
2699 : 1 : *compare = *submatcher;
2700 : : }
2701 : :
2702 : 1289 : g_array_set_size (matcher->sub_matchers, j + 1);
2703 : :
2704 : 1289 : return matcher;
2705 : : }
2706 : :
2707 : : /**
2708 : : * g_file_attribute_matcher_new:
2709 : : * @attributes: an attribute string to match.
2710 : : *
2711 : : * Creates a new file attribute matcher, which matches attributes
2712 : : * against a given string. [GFileAttributeMatchers][struct@FileAttributeMatcher] are reference
2713 : : * counted structures, and are created with a reference count of 1. If
2714 : : * the number of references falls to 0, the [struct@FileAttributeMatcher] is
2715 : : * automatically destroyed.
2716 : : *
2717 : : * The @attributes string should be formatted with specific keys separated
2718 : : * from namespaces with a double colon. Several `"namespace::key"` strings may be
2719 : : * concatenated with a single comma (e.g. `"standard::type,standard::is-hidden"`).
2720 : : * The wildcard `"*"` may be used to match all keys and namespaces, or
2721 : : * `"namespace::*"` will match all keys in a given namespace.
2722 : : *
2723 : : * ## Examples of file attribute matcher strings and results
2724 : : *
2725 : : * - `"*"`: matches all attributes.
2726 : : * - `"standard::is-hidden"`: matches only the key is-hidden in the
2727 : : * standard namespace.
2728 : : * - `"standard::type,unix::*"`: matches the type key in the standard
2729 : : * namespace and all keys in the unix namespace.
2730 : : *
2731 : : * Returns: a #GFileAttributeMatcher
2732 : : */
2733 : : GFileAttributeMatcher *
2734 : 1328 : g_file_attribute_matcher_new (const char *attributes)
2735 : : {
2736 : : char **split;
2737 : : char *colon;
2738 : : int i;
2739 : : GFileAttributeMatcher *matcher;
2740 : :
2741 : 1328 : if (attributes == NULL || *attributes == '\0')
2742 : 2 : return NULL;
2743 : :
2744 : 1326 : matcher = g_malloc0 (sizeof (GFileAttributeMatcher));
2745 : 1326 : matcher->ref = 1;
2746 : 1326 : matcher->sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
2747 : :
2748 : 1326 : split = g_strsplit (attributes, ",", -1);
2749 : :
2750 : 4697 : for (i = 0; split[i] != NULL; i++)
2751 : : {
2752 : 3371 : if (strcmp (split[i], "*") == 0)
2753 : 65 : matcher->all = TRUE;
2754 : : else
2755 : : {
2756 : : SubMatcher s;
2757 : :
2758 : 3306 : colon = strstr (split[i], "::");
2759 : 3306 : if (colon != NULL &&
2760 : 3279 : !(colon[2] == 0 ||
2761 : 3279 : (colon[2] == '*' &&
2762 : 182 : colon[3] == 0)))
2763 : : {
2764 : 3097 : s.id = lookup_attribute (split[i]);
2765 : 3097 : s.mask = 0xffffffff;
2766 : : }
2767 : : else
2768 : : {
2769 : 209 : if (colon)
2770 : 182 : *colon = 0;
2771 : :
2772 : 209 : s.id = lookup_namespace (split[i]) << NS_POS;
2773 : 209 : s.mask = NS_MASK << NS_POS;
2774 : : }
2775 : :
2776 : 3306 : g_array_append_val (matcher->sub_matchers, s);
2777 : : }
2778 : : }
2779 : :
2780 : 1326 : g_strfreev (split);
2781 : :
2782 : 1326 : matcher = matcher_optimize (matcher);
2783 : :
2784 : 1326 : return matcher;
2785 : : }
2786 : :
2787 : : /**
2788 : : * g_file_attribute_matcher_subtract:
2789 : : * @matcher: (nullable): Matcher to subtract from
2790 : : * @subtract: (nullable): The matcher to subtract
2791 : : *
2792 : : * Subtracts all attributes of @subtract from @matcher and returns
2793 : : * a matcher that supports those attributes.
2794 : : *
2795 : : * Note that currently it is not possible to remove a single
2796 : : * attribute when the @matcher matches the whole namespace - or remove
2797 : : * a namespace or attribute when the matcher matches everything. This
2798 : : * is a limitation of the current implementation, but may be fixed
2799 : : * in the future.
2800 : : *
2801 : : * Returns: (nullable): A file attribute matcher matching all attributes of
2802 : : * @matcher that are not matched by @subtract
2803 : : **/
2804 : : GFileAttributeMatcher *
2805 : 284 : g_file_attribute_matcher_subtract (GFileAttributeMatcher *matcher,
2806 : : GFileAttributeMatcher *subtract)
2807 : : {
2808 : : GFileAttributeMatcher *result;
2809 : : guint mi, si;
2810 : : SubMatcher *msub, *ssub;
2811 : :
2812 : 284 : if (matcher == NULL)
2813 : 2 : return NULL;
2814 : 282 : if (subtract == NULL)
2815 : 0 : return g_file_attribute_matcher_ref (matcher);
2816 : 282 : if (subtract->all)
2817 : 10 : return NULL;
2818 : 272 : if (matcher->all)
2819 : 23 : return g_file_attribute_matcher_ref (matcher);
2820 : :
2821 : 249 : result = g_malloc0 (sizeof (GFileAttributeMatcher));
2822 : 249 : result->ref = 1;
2823 : 249 : result->sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
2824 : :
2825 : 249 : si = 0;
2826 : 249 : g_assert (subtract->sub_matchers->len > 0);
2827 : 249 : ssub = &g_array_index (subtract->sub_matchers, SubMatcher, si);
2828 : :
2829 : 521 : for (mi = 0; mi < matcher->sub_matchers->len; mi++)
2830 : : {
2831 : 288 : msub = &g_array_index (matcher->sub_matchers, SubMatcher, mi);
2832 : :
2833 : 504 : retry:
2834 : 504 : if (sub_matcher_matches (ssub, msub))
2835 : 259 : continue;
2836 : :
2837 : 245 : si++;
2838 : 245 : if (si >= subtract->sub_matchers->len)
2839 : 16 : break;
2840 : :
2841 : 229 : ssub = &g_array_index (subtract->sub_matchers, SubMatcher, si);
2842 : 229 : if (ssub->id <= msub->id)
2843 : 216 : goto retry;
2844 : :
2845 : 13 : g_array_append_val (result->sub_matchers, *msub);
2846 : : }
2847 : :
2848 : 249 : if (mi < matcher->sub_matchers->len)
2849 : 16 : g_array_append_vals (result->sub_matchers,
2850 : 16 : &g_array_index (matcher->sub_matchers, SubMatcher, mi),
2851 : 16 : matcher->sub_matchers->len - mi);
2852 : :
2853 : 249 : result = matcher_optimize (result);
2854 : :
2855 : 249 : return result;
2856 : : }
2857 : :
2858 : : /**
2859 : : * g_file_attribute_matcher_ref:
2860 : : * @matcher: a #GFileAttributeMatcher.
2861 : : *
2862 : : * References a file attribute matcher.
2863 : : *
2864 : : * Returns: a #GFileAttributeMatcher.
2865 : : **/
2866 : : GFileAttributeMatcher *
2867 : 1145 : g_file_attribute_matcher_ref (GFileAttributeMatcher *matcher)
2868 : : {
2869 : 1145 : if (matcher)
2870 : : {
2871 : 808 : g_return_val_if_fail (matcher->ref > 0, NULL);
2872 : 808 : g_atomic_int_inc (&matcher->ref);
2873 : : }
2874 : 1145 : return matcher;
2875 : : }
2876 : :
2877 : : /**
2878 : : * g_file_attribute_matcher_unref:
2879 : : * @matcher: a #GFileAttributeMatcher.
2880 : : *
2881 : : * Unreferences @matcher. If the reference count falls below 1,
2882 : : * the @matcher is automatically freed.
2883 : : *
2884 : : **/
2885 : : void
2886 : 2954 : g_file_attribute_matcher_unref (GFileAttributeMatcher *matcher)
2887 : : {
2888 : 2954 : if (matcher)
2889 : : {
2890 : 2382 : g_return_if_fail (matcher->ref > 0);
2891 : :
2892 : 2382 : if (g_atomic_int_dec_and_test (&matcher->ref))
2893 : : {
2894 : 1574 : if (matcher->sub_matchers)
2895 : 1510 : g_array_free (matcher->sub_matchers, TRUE);
2896 : :
2897 : 1574 : g_free (matcher);
2898 : : }
2899 : : }
2900 : : }
2901 : :
2902 : : /**
2903 : : * g_file_attribute_matcher_matches_only:
2904 : : * @matcher: a #GFileAttributeMatcher.
2905 : : * @attribute: a file attribute key.
2906 : : *
2907 : : * Checks if an attribute matcher only matches a given attribute. Always
2908 : : * returns %FALSE if "*" was used when creating the matcher.
2909 : : *
2910 : : * Returns: %TRUE if the matcher only matches @attribute. %FALSE otherwise.
2911 : : **/
2912 : : gboolean
2913 : 1 : g_file_attribute_matcher_matches_only (GFileAttributeMatcher *matcher,
2914 : : const char *attribute)
2915 : : {
2916 : : SubMatcher *sub_matcher;
2917 : : guint32 id;
2918 : :
2919 : 1 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
2920 : :
2921 : 1 : if (matcher == NULL ||
2922 : 1 : matcher->all)
2923 : 0 : return FALSE;
2924 : :
2925 : 1 : if (matcher->sub_matchers->len != 1)
2926 : 1 : return FALSE;
2927 : :
2928 : 0 : id = lookup_attribute (attribute);
2929 : :
2930 : 0 : sub_matcher = &g_array_index (matcher->sub_matchers, SubMatcher, 0);
2931 : :
2932 : 0 : return sub_matcher->id == id &&
2933 : 0 : sub_matcher->mask == 0xffffffff;
2934 : : }
2935 : :
2936 : : static gboolean
2937 : 44186 : matcher_matches_id (GFileAttributeMatcher *matcher,
2938 : : guint32 id)
2939 : : {
2940 : : SubMatcher *sub_matchers;
2941 : : guint i;
2942 : :
2943 : 44186 : if (matcher->sub_matchers)
2944 : : {
2945 : 44186 : sub_matchers = (SubMatcher *)matcher->sub_matchers->data;
2946 : 135348 : for (i = 0; i < matcher->sub_matchers->len; i++)
2947 : : {
2948 : 93248 : if (sub_matchers[i].id == (id & sub_matchers[i].mask))
2949 : 2086 : return TRUE;
2950 : : }
2951 : : }
2952 : :
2953 : 42100 : return FALSE;
2954 : : }
2955 : :
2956 : : gboolean
2957 : 51473 : _g_file_attribute_matcher_matches_id (GFileAttributeMatcher *matcher,
2958 : : guint32 id)
2959 : : {
2960 : : /* We return a NULL matcher for an empty match string, so handle this */
2961 : 51473 : if (matcher == NULL)
2962 : 1368 : return FALSE;
2963 : :
2964 : 50105 : if (matcher->all)
2965 : 5957 : return TRUE;
2966 : :
2967 : 44148 : return matcher_matches_id (matcher, id);
2968 : : }
2969 : :
2970 : : /**
2971 : : * g_file_attribute_matcher_matches:
2972 : : * @matcher: a #GFileAttributeMatcher.
2973 : : * @attribute: a file attribute key.
2974 : : *
2975 : : * Checks if an attribute will be matched by an attribute matcher. If
2976 : : * the matcher was created with the "*" matching string, this function
2977 : : * will always return %TRUE.
2978 : : *
2979 : : * Returns: %TRUE if @attribute matches @matcher. %FALSE otherwise.
2980 : : **/
2981 : : gboolean
2982 : 40 : g_file_attribute_matcher_matches (GFileAttributeMatcher *matcher,
2983 : : const char *attribute)
2984 : : {
2985 : 40 : g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
2986 : :
2987 : : /* We return a NULL matcher for an empty match string, so handle this */
2988 : 40 : if (matcher == NULL)
2989 : 0 : return FALSE;
2990 : :
2991 : 40 : if (matcher->all)
2992 : 2 : return TRUE;
2993 : :
2994 : 38 : return matcher_matches_id (matcher, lookup_attribute (attribute));
2995 : : }
2996 : :
2997 : : /* return TRUE -> all */
2998 : : /**
2999 : : * g_file_attribute_matcher_enumerate_namespace:
3000 : : * @matcher: a #GFileAttributeMatcher.
3001 : : * @ns: a string containing a file attribute namespace.
3002 : : *
3003 : : * Checks if the matcher will match all of the keys in a given namespace.
3004 : : * This will always return %TRUE if a wildcard character is in use (e.g. if
3005 : : * matcher was created with "standard::\*" and @ns is "standard", or if matcher was created
3006 : : * using "*" and namespace is anything.)
3007 : : *
3008 : : * TODO: this is awkwardly worded.
3009 : : *
3010 : : * Returns: %TRUE if the matcher matches all of the entries
3011 : : * in the given @ns, %FALSE otherwise.
3012 : : **/
3013 : : gboolean
3014 : 1476 : g_file_attribute_matcher_enumerate_namespace (GFileAttributeMatcher *matcher,
3015 : : const char *ns)
3016 : : {
3017 : : SubMatcher *sub_matchers;
3018 : : guint ns_id;
3019 : : guint i;
3020 : :
3021 : 1476 : g_return_val_if_fail (ns != NULL && *ns != '\0', FALSE);
3022 : :
3023 : : /* We return a NULL matcher for an empty match string, so handle this */
3024 : 1476 : if (matcher == NULL)
3025 : 0 : return FALSE;
3026 : :
3027 : 1476 : if (matcher->all)
3028 : 152 : return TRUE;
3029 : :
3030 : 1324 : ns_id = lookup_namespace (ns) << NS_POS;
3031 : :
3032 : 1324 : if (matcher->sub_matchers)
3033 : : {
3034 : 1324 : sub_matchers = (SubMatcher *)matcher->sub_matchers->data;
3035 : 4584 : for (i = 0; i < matcher->sub_matchers->len; i++)
3036 : : {
3037 : 3332 : if (sub_matchers[i].id == ns_id)
3038 : 72 : return TRUE;
3039 : : }
3040 : : }
3041 : :
3042 : 1252 : matcher->iterator_ns = ns_id;
3043 : 1252 : matcher->iterator_pos = 0;
3044 : :
3045 : 1252 : return FALSE;
3046 : : }
3047 : :
3048 : : /**
3049 : : * g_file_attribute_matcher_enumerate_next:
3050 : : * @matcher: a #GFileAttributeMatcher.
3051 : : *
3052 : : * Gets the next matched attribute from a #GFileAttributeMatcher.
3053 : : *
3054 : : * Returns: (nullable): a string containing the next attribute or, %NULL if
3055 : : * no more attribute exist.
3056 : : **/
3057 : : const char *
3058 : 1253 : g_file_attribute_matcher_enumerate_next (GFileAttributeMatcher *matcher)
3059 : : {
3060 : : guint i;
3061 : : SubMatcher *sub_matcher;
3062 : :
3063 : : /* We return a NULL matcher for an empty match string, so handle this */
3064 : 1253 : if (matcher == NULL)
3065 : 0 : return NULL;
3066 : :
3067 : : while (1)
3068 : : {
3069 : 4120 : i = matcher->iterator_pos++;
3070 : :
3071 : 4120 : if (matcher->sub_matchers == NULL)
3072 : 0 : return NULL;
3073 : :
3074 : 4120 : if (i < matcher->sub_matchers->len)
3075 : 2868 : sub_matcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
3076 : : else
3077 : 1252 : return NULL;
3078 : :
3079 : 2868 : if (sub_matcher->mask == 0xffffffff &&
3080 : 2662 : (sub_matcher->id & (NS_MASK << NS_POS)) == matcher->iterator_ns)
3081 : 1 : return get_attribute_for_id (sub_matcher->id);
3082 : : }
3083 : : }
3084 : :
3085 : : /**
3086 : : * g_file_attribute_matcher_to_string:
3087 : : * @matcher: (nullable): a #GFileAttributeMatcher.
3088 : : *
3089 : : * Prints what the matcher is matching against. The format will be
3090 : : * equal to the format passed to g_file_attribute_matcher_new().
3091 : : * The output however, might not be identical, as the matcher may
3092 : : * decide to use a different order or omit needless parts.
3093 : : *
3094 : : * Returns: a string describing the attributes the matcher matches
3095 : : * against or %NULL if @matcher was %NULL.
3096 : : *
3097 : : * Since: 2.32
3098 : : **/
3099 : : char *
3100 : 69 : g_file_attribute_matcher_to_string (GFileAttributeMatcher *matcher)
3101 : : {
3102 : : GString *string;
3103 : : guint i;
3104 : :
3105 : 69 : if (matcher == NULL)
3106 : 19 : return NULL;
3107 : :
3108 : 50 : if (matcher->all)
3109 : 11 : return g_strdup ("*");
3110 : :
3111 : 39 : string = g_string_new ("");
3112 : 91 : for (i = 0; i < matcher->sub_matchers->len; i++)
3113 : : {
3114 : 52 : SubMatcher *submatcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
3115 : :
3116 : 52 : if (i > 0)
3117 : : g_string_append_c (string, ',');
3118 : :
3119 : 52 : g_string_append (string, get_attribute_for_id (submatcher->id));
3120 : : }
3121 : :
3122 : 39 : return g_string_free (string, FALSE);
3123 : : }
|