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 : : #include "config.h"
24 : :
25 : : #include <stdint.h>
26 : : #include <string.h>
27 : :
28 : : #include "gfileattribute.h"
29 : : #include "gfileattribute-priv.h"
30 : : #include <glib-object.h>
31 : : #include "glibintl.h"
32 : :
33 : :
34 : : /**
35 : : * _g_file_attribute_value_free:
36 : : * @attr: a #GFileAttributeValue.
37 : : *
38 : : * Frees the memory used by @attr.
39 : : *
40 : : **/
41 : : void
42 : 0 : _g_file_attribute_value_free (GFileAttributeValue *attr)
43 : : {
44 : 0 : g_return_if_fail (attr != NULL);
45 : :
46 : 0 : _g_file_attribute_value_clear (attr);
47 : 0 : g_free (attr);
48 : : }
49 : :
50 : : /**
51 : : * _g_file_attribute_value_clear:
52 : : * @attr: a #GFileAttributeValue.
53 : : *
54 : : * Clears the value of @attr and sets its type to
55 : : * %G_FILE_ATTRIBUTE_TYPE_INVALID.
56 : : *
57 : : **/
58 : : void
59 : 12537 : _g_file_attribute_value_clear (GFileAttributeValue *attr)
60 : : {
61 : 12537 : g_return_if_fail (attr != NULL);
62 : :
63 : 12537 : if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING ||
64 : 11412 : attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING)
65 : 1704 : g_free (attr->u.string);
66 : :
67 : 12537 : if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRINGV)
68 : 0 : g_strfreev (attr->u.stringv);
69 : :
70 : 12537 : if (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT &&
71 : 152 : attr->u.obj != NULL)
72 : 152 : g_object_unref (attr->u.obj);
73 : :
74 : 12537 : attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
75 : : }
76 : :
77 : : /**
78 : : * g_file_attribute_value_set:
79 : : * @attr: a #GFileAttributeValue to set the value in.
80 : : * @new_value: a #GFileAttributeValue to get the value from.
81 : : *
82 : : * Sets an attribute's value from another attribute.
83 : : **/
84 : : void
85 : 8 : _g_file_attribute_value_set (GFileAttributeValue *attr,
86 : : const GFileAttributeValue *new_value)
87 : : {
88 : 8 : g_return_if_fail (attr != NULL);
89 : 8 : g_return_if_fail (new_value != NULL);
90 : :
91 : 8 : _g_file_attribute_value_clear (attr);
92 : 8 : *attr = *new_value;
93 : :
94 : 8 : if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING ||
95 : 6 : attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING)
96 : 8 : attr->u.string = g_strdup (attr->u.string);
97 : :
98 : 8 : if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRINGV)
99 : 0 : attr->u.stringv = g_strdupv (attr->u.stringv);
100 : :
101 : 8 : if (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT &&
102 : 0 : attr->u.obj != NULL)
103 : 0 : g_object_ref (attr->u.obj);
104 : : }
105 : :
106 : : /**
107 : : * _g_file_attribute_value_new:
108 : : *
109 : : * Creates a new file attribute.
110 : : *
111 : : * Returns: a #GFileAttributeValue.
112 : : **/
113 : : GFileAttributeValue *
114 : 0 : _g_file_attribute_value_new (void)
115 : : {
116 : : GFileAttributeValue *attr;
117 : :
118 : 0 : attr = g_new (GFileAttributeValue, 1);
119 : 0 : attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
120 : 0 : return attr;
121 : : }
122 : :
123 : : gpointer
124 : 44 : _g_file_attribute_value_peek_as_pointer (GFileAttributeValue *attr)
125 : : {
126 : 44 : switch (attr->type) {
127 : 10 : case G_FILE_ATTRIBUTE_TYPE_STRING:
128 : : case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
129 : 10 : return attr->u.string;
130 : 0 : case G_FILE_ATTRIBUTE_TYPE_STRINGV:
131 : 0 : return attr->u.stringv;
132 : 0 : case G_FILE_ATTRIBUTE_TYPE_OBJECT:
133 : 0 : return attr->u.obj;
134 : 34 : default:
135 : 34 : return (gpointer) &attr->u;
136 : : }
137 : : }
138 : :
139 : : /**
140 : : * g_file_attribute_value_dup:
141 : : * @other: a #GFileAttributeValue to duplicate.
142 : : *
143 : : * Duplicates a file attribute.
144 : : *
145 : : * Returns: a duplicate of the @other.
146 : : **/
147 : : GFileAttributeValue *
148 : 0 : _g_file_attribute_value_dup (const GFileAttributeValue *other)
149 : : {
150 : : GFileAttributeValue *attr;
151 : :
152 : 0 : g_return_val_if_fail (other != NULL, NULL);
153 : :
154 : 0 : attr = g_new (GFileAttributeValue, 1);
155 : 0 : attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
156 : 0 : _g_file_attribute_value_set (attr, other);
157 : 0 : return attr;
158 : : }
159 : :
160 : 4 : G_DEFINE_BOXED_TYPE (GFileAttributeInfoList, g_file_attribute_info_list,
161 : : g_file_attribute_info_list_dup,
162 : : g_file_attribute_info_list_unref)
163 : :
164 : : static gboolean
165 : 0 : valid_char (char c)
166 : : {
167 : 0 : return c >= 32 && c <= 126 && c != '\\';
168 : : }
169 : :
170 : : /* Returns NULL on error */
171 : : static char *
172 : 0 : escape_byte_string (const char *str)
173 : : {
174 : : size_t i, len;
175 : : size_t num_invalid;
176 : : char *escaped_val, *p;
177 : : char c;
178 : 0 : const char hex_digits[] = "0123456789abcdef";
179 : :
180 : 0 : len = strlen (str);
181 : :
182 : 0 : num_invalid = 0;
183 : 0 : for (i = 0; i < len; i++)
184 : : {
185 : 0 : if (!valid_char (str[i]))
186 : 0 : num_invalid++;
187 : : }
188 : :
189 : 0 : if (num_invalid == 0)
190 : 0 : return g_strdup (str);
191 : : else
192 : : {
193 : : /* Check for overflow. We want to check the inequality:
194 : : * !(len + num_invalid * 3 + 1 > SIZE_MAX) */
195 : 0 : if (num_invalid >= (SIZE_MAX - len) / 3)
196 : 0 : return NULL;
197 : :
198 : 0 : escaped_val = g_malloc (len + num_invalid * 3 + 1);
199 : :
200 : 0 : p = escaped_val;
201 : 0 : for (i = 0; i < len; i++)
202 : : {
203 : 0 : c = str[i];
204 : 0 : if (valid_char (c))
205 : 0 : *p++ = c;
206 : : else
207 : : {
208 : 0 : *p++ = '\\';
209 : 0 : *p++ = 'x';
210 : 0 : *p++ = hex_digits[(c >> 4) & 0xf];
211 : 0 : *p++ = hex_digits[c & 0xf];
212 : : }
213 : : }
214 : 0 : *p++ = 0;
215 : 0 : return escaped_val;
216 : : }
217 : : }
218 : :
219 : : /**
220 : : * _g_file_attribute_value_as_string:
221 : : * @attr: a #GFileAttributeValue.
222 : : *
223 : : * Converts a #GFileAttributeValue to a string for display.
224 : : * The returned string should be freed when no longer needed.
225 : : *
226 : : * Returns: a string from the @attr, %NULL on error, or "<invalid>"
227 : : * if @attr is of type %G_FILE_ATTRIBUTE_TYPE_INVALID.
228 : : */
229 : : char *
230 : 1 : _g_file_attribute_value_as_string (const GFileAttributeValue *attr)
231 : : {
232 : : GString *s;
233 : : int i;
234 : : char *str;
235 : :
236 : 1 : g_return_val_if_fail (attr != NULL, NULL);
237 : :
238 : 1 : switch (attr->type)
239 : : {
240 : 1 : case G_FILE_ATTRIBUTE_TYPE_STRING:
241 : 1 : str = g_strdup (attr->u.string);
242 : 1 : break;
243 : 0 : case G_FILE_ATTRIBUTE_TYPE_STRINGV:
244 : 0 : s = g_string_new ("[");
245 : 0 : for (i = 0; attr->u.stringv[i] != NULL; i++)
246 : : {
247 : 0 : g_string_append (s, attr->u.stringv[i]);
248 : 0 : if (attr->u.stringv[i+1] != NULL)
249 : 0 : g_string_append (s, ", ");
250 : : }
251 : 0 : g_string_append (s, "]");
252 : 0 : str = g_string_free (s, FALSE);
253 : 0 : break;
254 : 0 : case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
255 : 0 : str = escape_byte_string (attr->u.string);
256 : 0 : break;
257 : 0 : case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
258 : 0 : str = g_strdup_printf ("%s", attr->u.boolean?"TRUE":"FALSE");
259 : 0 : break;
260 : 0 : case G_FILE_ATTRIBUTE_TYPE_UINT32:
261 : 0 : str = g_strdup_printf ("%u", (unsigned int)attr->u.uint32);
262 : 0 : break;
263 : 0 : case G_FILE_ATTRIBUTE_TYPE_INT32:
264 : 0 : str = g_strdup_printf ("%i", (int)attr->u.int32);
265 : 0 : break;
266 : 0 : case G_FILE_ATTRIBUTE_TYPE_UINT64:
267 : 0 : str = g_strdup_printf ("%"G_GUINT64_FORMAT, attr->u.uint64);
268 : 0 : break;
269 : 0 : case G_FILE_ATTRIBUTE_TYPE_INT64:
270 : 0 : str = g_strdup_printf ("%"G_GINT64_FORMAT, attr->u.int64);
271 : 0 : break;
272 : 0 : case G_FILE_ATTRIBUTE_TYPE_OBJECT:
273 : 0 : str = g_strdup_printf ("%s:%p", g_type_name_from_instance
274 : 0 : ((GTypeInstance *) attr->u.obj),
275 : 0 : attr->u.obj);
276 : 0 : break;
277 : 0 : case G_FILE_ATTRIBUTE_TYPE_INVALID:
278 : 0 : str = g_strdup ("<unset>");
279 : 0 : break;
280 : 0 : default:
281 : 0 : g_warning ("Invalid type in GFileInfo attribute");
282 : 0 : str = g_strdup ("<invalid>");
283 : 0 : break;
284 : : }
285 : :
286 : 1 : return str;
287 : : }
288 : :
289 : : /**
290 : : * _g_file_attribute_value_get_string:
291 : : * @attr: a #GFileAttributeValue.
292 : : *
293 : : * Gets the string from a file attribute value. If the value is not the
294 : : * right type then %NULL will be returned.
295 : : *
296 : : * Returns: the UTF-8 string value contained within the attribute, or %NULL.
297 : : */
298 : : const char *
299 : 214 : _g_file_attribute_value_get_string (const GFileAttributeValue *attr)
300 : : {
301 : 214 : if (attr == NULL)
302 : 4 : return NULL;
303 : :
304 : 210 : g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING, NULL);
305 : :
306 : 210 : return attr->u.string;
307 : : }
308 : :
309 : : /**
310 : : * _g_file_attribute_value_get_byte_string:
311 : : * @attr: a #GFileAttributeValue.
312 : : *
313 : : * Gets the byte string from a file attribute value. If the value is not the
314 : : * right type then %NULL will be returned.
315 : : *
316 : : * Returns: the byte string contained within the attribute or %NULL.
317 : : */
318 : : const char *
319 : 316 : _g_file_attribute_value_get_byte_string (const GFileAttributeValue *attr)
320 : : {
321 : 316 : if (attr == NULL)
322 : 0 : return NULL;
323 : :
324 : 316 : g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, NULL);
325 : :
326 : 316 : return attr->u.string;
327 : : }
328 : :
329 : : char **
330 : 0 : _g_file_attribute_value_get_stringv (const GFileAttributeValue *attr)
331 : : {
332 : 0 : if (attr == NULL)
333 : 0 : return NULL;
334 : :
335 : 0 : g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_STRINGV, NULL);
336 : :
337 : 0 : return attr->u.stringv;
338 : : }
339 : :
340 : : /**
341 : : * _g_file_attribute_value_get_boolean:
342 : : * @attr: a #GFileAttributeValue.
343 : : *
344 : : * Gets the boolean value from a file attribute value. If the value is not the
345 : : * right type then %FALSE will be returned.
346 : : *
347 : : * Returns: the boolean value contained within the attribute, or %FALSE.
348 : : */
349 : : gboolean
350 : 245 : _g_file_attribute_value_get_boolean (const GFileAttributeValue *attr)
351 : : {
352 : 245 : if (attr == NULL)
353 : 0 : return FALSE;
354 : :
355 : 245 : g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_BOOLEAN, FALSE);
356 : :
357 : 245 : return attr->u.boolean;
358 : : }
359 : :
360 : : /**
361 : : * _g_file_attribute_value_get_uint32:
362 : : * @attr: a #GFileAttributeValue.
363 : : *
364 : : * Gets the unsigned 32-bit integer from a file attribute value. If the value
365 : : * is not the right type then 0 will be returned.
366 : : *
367 : : * Returns: the unsigned 32-bit integer from the attribute, or 0.
368 : : */
369 : : guint32
370 : 756 : _g_file_attribute_value_get_uint32 (const GFileAttributeValue *attr)
371 : : {
372 : 756 : if (attr == NULL)
373 : 3 : return 0;
374 : :
375 : 753 : g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_UINT32, 0);
376 : :
377 : 753 : return attr->u.uint32;
378 : : }
379 : :
380 : : /**
381 : : * _g_file_attribute_value_get_int32:
382 : : * @attr: a #GFileAttributeValue.
383 : : *
384 : : * Gets the signed 32-bit integer from a file attribute value. If the value
385 : : * is not the right type then 0 will be returned.
386 : : *
387 : : * Returns: the signed 32-bit integer from the attribute, or 0.
388 : : */
389 : : gint32
390 : 0 : _g_file_attribute_value_get_int32 (const GFileAttributeValue *attr)
391 : : {
392 : 0 : if (attr == NULL)
393 : 0 : return 0;
394 : :
395 : 0 : g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_INT32, 0);
396 : :
397 : 0 : return attr->u.int32;
398 : : }
399 : :
400 : : /**
401 : : * _g_file_attribute_value_get_uint64:
402 : : * @attr: a #GFileAttributeValue.
403 : : *
404 : : * Gets the unsigned 64-bit integer from a file attribute value. If the value
405 : : * is not the right type then 0 will be returned.
406 : : *
407 : : * Returns: the unsigned 64-bit integer from the attribute, or 0.
408 : : */
409 : : guint64
410 : 207 : _g_file_attribute_value_get_uint64 (const GFileAttributeValue *attr)
411 : : {
412 : 207 : if (attr == NULL)
413 : 4 : return 0;
414 : :
415 : 203 : g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_UINT64, 0);
416 : :
417 : 203 : return attr->u.uint64;
418 : : }
419 : :
420 : : /**
421 : : * _g_file_attribute_value_get_int64:
422 : : * @attr: a #GFileAttributeValue.
423 : : *
424 : : * Gets the signed 64-bit integer from a file attribute value. If the value
425 : : * is not the right type then 0 will be returned.
426 : : *
427 : : * Returns: the signed 64-bit integer from the attribute, or 0.
428 : : */
429 : : gint64
430 : 0 : _g_file_attribute_value_get_int64 (const GFileAttributeValue *attr)
431 : : {
432 : 0 : if (attr == NULL)
433 : 0 : return 0;
434 : :
435 : 0 : g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_INT64, 0);
436 : :
437 : 0 : return attr->u.int64;
438 : : }
439 : :
440 : : /**
441 : : * _g_file_attribute_value_get_object:
442 : : * @attr: a #GFileAttributeValue.
443 : : *
444 : : * Gets the GObject from a file attribute value. If the value
445 : : * is not the right type then %NULL will be returned.
446 : : *
447 : : * Returns: the GObject from the attribute, or %NULL.
448 : : **/
449 : : GObject *
450 : 0 : _g_file_attribute_value_get_object (const GFileAttributeValue *attr)
451 : : {
452 : 0 : if (attr == NULL)
453 : 0 : return NULL;
454 : :
455 : 0 : g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT, NULL);
456 : :
457 : 0 : return attr->u.obj;
458 : : }
459 : :
460 : :
461 : : void
462 : 209 : _g_file_attribute_value_set_from_pointer (GFileAttributeValue *value,
463 : : GFileAttributeType type,
464 : : gpointer value_p,
465 : : gboolean dup)
466 : : {
467 : 209 : _g_file_attribute_value_clear (value);
468 : 209 : value->type = type;
469 : 209 : switch (type)
470 : : {
471 : 10 : case G_FILE_ATTRIBUTE_TYPE_STRING:
472 : : case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
473 : 10 : if (dup)
474 : 0 : value->u.string = g_strdup (value_p);
475 : : else
476 : 10 : value->u.string = value_p;
477 : 10 : break;
478 : :
479 : 0 : case G_FILE_ATTRIBUTE_TYPE_STRINGV:
480 : 0 : if (dup)
481 : 0 : value->u.stringv = g_strdupv (value_p);
482 : : else
483 : 0 : value->u.stringv = value_p;
484 : 0 : break;
485 : :
486 : 0 : case G_FILE_ATTRIBUTE_TYPE_OBJECT:
487 : 0 : if (dup)
488 : 0 : value->u.obj = g_object_ref (value_p);
489 : : else
490 : 0 : value->u.obj = value_p;
491 : 0 : break;
492 : :
493 : 0 : case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
494 : 0 : value->u.boolean = *(gboolean *)value_p;
495 : 0 : break;
496 : :
497 : 164 : case G_FILE_ATTRIBUTE_TYPE_UINT32:
498 : 164 : value->u.uint32 = *(guint32 *)value_p;
499 : 164 : break;
500 : :
501 : 0 : case G_FILE_ATTRIBUTE_TYPE_INT32:
502 : 0 : value->u.int32 = *(gint32 *)value_p;
503 : 0 : break;
504 : :
505 : 34 : case G_FILE_ATTRIBUTE_TYPE_UINT64:
506 : 34 : value->u.uint64 = *(guint64 *)value_p;
507 : 34 : break;
508 : :
509 : 0 : case G_FILE_ATTRIBUTE_TYPE_INT64:
510 : 0 : value->u.int64 = *(gint64 *)value_p;
511 : 0 : break;
512 : :
513 : 1 : case G_FILE_ATTRIBUTE_TYPE_INVALID:
514 : 1 : break;
515 : :
516 : 0 : default:
517 : 0 : g_warning ("Unknown type specified in g_file_info_set_attribute");
518 : 0 : break;
519 : : }
520 : 209 : }
521 : :
522 : : /**
523 : : * _g_file_attribute_value_set_string:
524 : : * @attr: a #GFileAttributeValue.
525 : : * @string: a UTF-8 string to set within the type.
526 : : *
527 : : * Sets the attribute value to a given UTF-8 string.
528 : : */
529 : : void
530 : 1123 : _g_file_attribute_value_set_string (GFileAttributeValue *attr,
531 : : const char *string)
532 : : {
533 : 1123 : g_return_if_fail (attr != NULL);
534 : 1123 : g_return_if_fail (string != NULL);
535 : :
536 : 1123 : _g_file_attribute_value_clear (attr);
537 : 1123 : attr->type = G_FILE_ATTRIBUTE_TYPE_STRING;
538 : 1123 : attr->u.string = g_strdup (string);
539 : : }
540 : :
541 : : /**
542 : : * _g_file_attribute_value_set_byte_string:
543 : : * @attr: a #GFileAttributeValue.
544 : : * @string: a byte string to set within the type.
545 : : *
546 : : * Sets the attribute value to a given byte string.
547 : : */
548 : : void
549 : 577 : _g_file_attribute_value_set_byte_string (GFileAttributeValue *attr,
550 : : const char *string)
551 : : {
552 : 577 : g_return_if_fail (attr != NULL);
553 : 577 : g_return_if_fail (string != NULL);
554 : :
555 : 577 : _g_file_attribute_value_clear (attr);
556 : 577 : attr->type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING;
557 : 577 : attr->u.string = g_strdup (string);
558 : : }
559 : :
560 : : void
561 : 0 : _g_file_attribute_value_set_stringv (GFileAttributeValue *attr,
562 : : char **value)
563 : : {
564 : 0 : g_return_if_fail (attr != NULL);
565 : 0 : g_return_if_fail (value != NULL);
566 : :
567 : 0 : _g_file_attribute_value_clear (attr);
568 : 0 : attr->type = G_FILE_ATTRIBUTE_TYPE_STRINGV;
569 : 0 : attr->u.stringv = g_strdupv (value);
570 : : }
571 : :
572 : :
573 : : /**
574 : : * _g_file_attribute_value_set_boolean:
575 : : * @attr: a #GFileAttributeValue.
576 : : * @value: a #gboolean to set within the type.
577 : : *
578 : : * Sets the attribute value to the given boolean value.
579 : : */
580 : : void
581 : 1220 : _g_file_attribute_value_set_boolean (GFileAttributeValue *attr,
582 : : gboolean value)
583 : : {
584 : 1220 : g_return_if_fail (attr != NULL);
585 : :
586 : 1220 : _g_file_attribute_value_clear (attr);
587 : 1220 : attr->type = G_FILE_ATTRIBUTE_TYPE_BOOLEAN;
588 : 1220 : attr->u.boolean = !!value;
589 : : }
590 : :
591 : : /**
592 : : * _g_file_attribute_value_set_uint32:
593 : : * @attr: a #GFileAttributeValue.
594 : : * @value: a #guint32 to set within the type.
595 : : *
596 : : * Sets the attribute value to the given unsigned 32-bit integer.
597 : : */
598 : : void
599 : 2318 : _g_file_attribute_value_set_uint32 (GFileAttributeValue *attr,
600 : : guint32 value)
601 : : {
602 : 2318 : g_return_if_fail (attr != NULL);
603 : :
604 : 2318 : _g_file_attribute_value_clear (attr);
605 : 2318 : attr->type = G_FILE_ATTRIBUTE_TYPE_UINT32;
606 : 2318 : attr->u.uint32 = value;
607 : : }
608 : :
609 : : /**
610 : : * _g_file_attribute_value_set_int32:
611 : : * @attr: a #GFileAttributeValue.
612 : : * @value: a #gint32 to set within the type.
613 : : *
614 : : * Sets the attribute value to the given signed 32-bit integer.
615 : : */
616 : : void
617 : 1 : _g_file_attribute_value_set_int32 (GFileAttributeValue *attr,
618 : : gint32 value)
619 : : {
620 : 1 : g_return_if_fail (attr != NULL);
621 : :
622 : 1 : _g_file_attribute_value_clear (attr);
623 : 1 : attr->type = G_FILE_ATTRIBUTE_TYPE_INT32;
624 : 1 : attr->u.int32 = value;
625 : : }
626 : :
627 : : /**
628 : : * _g_file_attribute_value_set_uint64:
629 : : * @attr: a #GFileAttributeValue.
630 : : * @value: a #guint64 to set within the type.
631 : : *
632 : : * Sets the attribute value to a given unsigned 64-bit integer.
633 : : */
634 : : void
635 : 913 : _g_file_attribute_value_set_uint64 (GFileAttributeValue *attr,
636 : : guint64 value)
637 : : {
638 : 913 : g_return_if_fail (attr != NULL);
639 : :
640 : 913 : _g_file_attribute_value_clear (attr);
641 : 913 : attr->type = G_FILE_ATTRIBUTE_TYPE_UINT64;
642 : 913 : attr->u.uint64 = value;
643 : : }
644 : :
645 : : /**
646 : : * _g_file_attribute_value_set_int64:
647 : : * @attr: a #GFileAttributeValue.
648 : : * @value: a #gint64 to set within the type.
649 : : *
650 : : * Sets the attribute value to a given signed 64-bit integer.
651 : : */
652 : : void
653 : 0 : _g_file_attribute_value_set_int64 (GFileAttributeValue *attr,
654 : : gint64 value)
655 : : {
656 : 0 : g_return_if_fail (attr != NULL);
657 : :
658 : 0 : _g_file_attribute_value_clear (attr);
659 : 0 : attr->type = G_FILE_ATTRIBUTE_TYPE_INT64;
660 : 0 : attr->u.int64 = value;
661 : : }
662 : :
663 : : /**
664 : : * _g_file_attribute_value_set_object:
665 : : * @attr: a #GFileAttributeValue.
666 : : * @obj: a #GObject.
667 : : *
668 : : * Sets the attribute to contain the value @obj.
669 : : * The @attr references the GObject internally.
670 : : */
671 : : void
672 : 152 : _g_file_attribute_value_set_object (GFileAttributeValue *attr,
673 : : GObject *obj)
674 : : {
675 : 152 : g_return_if_fail (attr != NULL);
676 : 152 : g_return_if_fail (obj != NULL);
677 : :
678 : 152 : _g_file_attribute_value_clear (attr);
679 : 152 : attr->type = G_FILE_ATTRIBUTE_TYPE_OBJECT;
680 : 152 : attr->u.obj = g_object_ref (obj);
681 : : }
682 : :
683 : : typedef struct {
684 : : GFileAttributeInfoList public;
685 : : GArray *array;
686 : : int ref_count;
687 : : } GFileAttributeInfoListPriv;
688 : :
689 : : static void
690 : 550 : list_update_public (GFileAttributeInfoListPriv *priv)
691 : : {
692 : 550 : priv->public.infos = (GFileAttributeInfo *)priv->array->data;
693 : :
694 : : /* The `n_infos` member should really have type `size_t`, but by a historical
695 : : * accident it has type `int` and we can’t change it now because it’s public
696 : : * API. It should never end up with a negative value at runtime. */
697 : 550 : g_assert (priv->array->len <= INT_MAX);
698 : 550 : priv->public.n_infos = (int) priv->array->len;
699 : 550 : }
700 : :
701 : : /**
702 : : * g_file_attribute_info_list_new:
703 : : *
704 : : * Creates a new file attribute info list.
705 : : *
706 : : * Returns: a #GFileAttributeInfoList.
707 : : */
708 : : GFileAttributeInfoList *
709 : 54 : g_file_attribute_info_list_new (void)
710 : : {
711 : : GFileAttributeInfoListPriv *priv;
712 : :
713 : 54 : priv = g_new0 (GFileAttributeInfoListPriv, 1);
714 : :
715 : 54 : priv->ref_count = 1;
716 : 54 : priv->array = g_array_new (TRUE, FALSE, sizeof (GFileAttributeInfo));
717 : :
718 : 54 : list_update_public (priv);
719 : :
720 : 54 : return (GFileAttributeInfoList *)priv;
721 : : }
722 : :
723 : : /**
724 : : * g_file_attribute_info_list_dup:
725 : : * @list: a #GFileAttributeInfoList to duplicate.
726 : : *
727 : : * Makes a duplicate of a file attribute info list.
728 : : *
729 : : * Returns: a copy of the given @list.
730 : : */
731 : : GFileAttributeInfoList *
732 : 0 : g_file_attribute_info_list_dup (GFileAttributeInfoList *list)
733 : : {
734 : : GFileAttributeInfoListPriv *new;
735 : : int i;
736 : :
737 : 0 : g_return_val_if_fail (list != NULL, NULL);
738 : :
739 : 0 : new = g_new0 (GFileAttributeInfoListPriv, 1);
740 : 0 : new->ref_count = 1;
741 : 0 : new->array = g_array_new (TRUE, FALSE, sizeof (GFileAttributeInfo));
742 : :
743 : 0 : g_array_set_size (new->array, (unsigned int) list->n_infos);
744 : 0 : list_update_public (new);
745 : 0 : for (i = 0; i < list->n_infos; i++)
746 : : {
747 : 0 : new->public.infos[i].name = g_strdup (list->infos[i].name);
748 : 0 : new->public.infos[i].type = list->infos[i].type;
749 : 0 : new->public.infos[i].flags = list->infos[i].flags;
750 : : }
751 : :
752 : 0 : return (GFileAttributeInfoList *)new;
753 : : }
754 : :
755 : : /**
756 : : * g_file_attribute_info_list_ref:
757 : : * @list: a #GFileAttributeInfoList to reference.
758 : : *
759 : : * References a file attribute info list.
760 : : *
761 : : * Returns: #GFileAttributeInfoList or %NULL on error.
762 : : */
763 : : GFileAttributeInfoList *
764 : 144 : g_file_attribute_info_list_ref (GFileAttributeInfoList *list)
765 : : {
766 : 144 : GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
767 : : int old_ref_count;
768 : :
769 : 144 : g_return_val_if_fail (list != NULL, NULL);
770 : :
771 : 144 : old_ref_count = g_atomic_int_add (&priv->ref_count, 1);
772 : 144 : g_return_val_if_fail (old_ref_count > 0, NULL);
773 : :
774 : 144 : return list;
775 : : }
776 : :
777 : : /**
778 : : * g_file_attribute_info_list_unref:
779 : : * @list: The #GFileAttributeInfoList to unreference.
780 : : *
781 : : * Removes a reference from the given @list. If the reference count
782 : : * falls to zero, the @list is deleted.
783 : : */
784 : : void
785 : 144 : g_file_attribute_info_list_unref (GFileAttributeInfoList *list)
786 : : {
787 : 144 : GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
788 : : int i;
789 : :
790 : 144 : g_return_if_fail (list != NULL);
791 : 144 : g_return_if_fail (priv->ref_count > 0);
792 : :
793 : 144 : if (g_atomic_int_dec_and_test (&priv->ref_count))
794 : : {
795 : 0 : for (i = 0; i < list->n_infos; i++)
796 : 0 : g_free (list->infos[i].name);
797 : 0 : g_array_free (priv->array, TRUE);
798 : 0 : g_free (list);
799 : : }
800 : : }
801 : :
802 : : static int
803 : 496 : g_file_attribute_info_list_bsearch (GFileAttributeInfoList *list,
804 : : const char *name)
805 : : {
806 : : int start, end, mid;
807 : :
808 : 496 : start = 0;
809 : 496 : end = list->n_infos;
810 : :
811 : 1577 : while (start != end)
812 : : {
813 : 1081 : mid = start + (end - start) / 2;
814 : :
815 : 1081 : if (strcmp (name, list->infos[mid].name) < 0)
816 : 686 : end = mid;
817 : 395 : else if (strcmp (name, list->infos[mid].name) > 0)
818 : 395 : start = mid + 1;
819 : : else
820 : 0 : return mid;
821 : : }
822 : 496 : return start;
823 : : }
824 : :
825 : : /**
826 : : * g_file_attribute_info_list_lookup:
827 : : * @list: a #GFileAttributeInfoList.
828 : : * @name: the name of the attribute to look up.
829 : : *
830 : : * Gets the file attribute with the name @name from @list.
831 : : *
832 : : * Returns: a #GFileAttributeInfo for the @name, or %NULL if an
833 : : * attribute isn't found.
834 : : */
835 : : const GFileAttributeInfo *
836 : 0 : g_file_attribute_info_list_lookup (GFileAttributeInfoList *list,
837 : : const char *name)
838 : : {
839 : : int i;
840 : :
841 : 0 : g_return_val_if_fail (list != NULL, NULL);
842 : 0 : g_return_val_if_fail (name != NULL, NULL);
843 : :
844 : 0 : i = g_file_attribute_info_list_bsearch (list, name);
845 : :
846 : 0 : if (i < list->n_infos && strcmp (list->infos[i].name, name) == 0)
847 : 0 : return &list->infos[i];
848 : :
849 : 0 : return NULL;
850 : : }
851 : :
852 : : /**
853 : : * g_file_attribute_info_list_add:
854 : : * @list: a #GFileAttributeInfoList.
855 : : * @name: the name of the attribute to add.
856 : : * @type: the #GFileAttributeType for the attribute.
857 : : * @flags: #GFileAttributeInfoFlags for the attribute.
858 : : *
859 : : * Adds a new attribute with @name to the @list, setting
860 : : * its @type and @flags.
861 : : */
862 : : void
863 : 496 : g_file_attribute_info_list_add (GFileAttributeInfoList *list,
864 : : const char *name,
865 : : GFileAttributeType type,
866 : : GFileAttributeInfoFlags flags)
867 : : {
868 : 496 : GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
869 : : GFileAttributeInfo info;
870 : : int i;
871 : :
872 : 496 : g_return_if_fail (list != NULL);
873 : 496 : g_return_if_fail (name != NULL);
874 : :
875 : 496 : i = g_file_attribute_info_list_bsearch (list, name);
876 : :
877 : 496 : if (i < list->n_infos && strcmp (list->infos[i].name, name) == 0)
878 : : {
879 : 0 : list->infos[i].type = type;
880 : 0 : return;
881 : : }
882 : :
883 : 496 : g_assert (i >= 0);
884 : :
885 : 496 : info.name = g_strdup (name);
886 : 496 : info.type = type;
887 : 496 : info.flags = flags;
888 : 496 : g_array_insert_vals (priv->array, (unsigned int) i, &info, 1);
889 : :
890 : 496 : list_update_public (priv);
891 : : }
|