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