Bug Summary

File:file-utils.c
Warning:line 627, column 52
Access to field 'message' results in a dereference of a null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name file-utils.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D GRAPA_RESOURCE_UI_PATH="/org/cafe/Grapa/ui" -D FR_PREFIX="/usr" -D FR_SYSCONFDIR="/usr/etc" -D FR_DATADIR="/usr/share" -D PRIVDATADIR="/usr/share/grapa/" -D FR_LIBDIR="/usr/lib" -D PKG_DATA_DIR="/usr/share/grapa" -D PIXMAPSDIR="/usr/share/pixmaps" -D GLADEDIR="" -D LOCALEDIR="/usr/share/locale" -D SHDIR="/usr/libexec/grapa/" -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/json-glib-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-03-28-134609-51145-1 -x c file-utils.c
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3/*
4 * Grapa
5 *
6 * Copyright (C) 2001, 2003 Free Software Foundation, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23#define _XOPEN_SOURCE700 700
24
25#include <config.h>
26#include <pwd.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <strings.h>
31#include <ctype.h>
32#include <time.h>
33#include <unistd.h>
34#include <sys/param.h>
35#include <sys/stat.h>
36#include <sys/time.h>
37#include <sys/types.h>
38#include <dirent.h>
39
40#include <glib.h>
41#include <gio/gio.h>
42#include "file-utils.h"
43#include "glib-utils.h"
44#include "fr-init.h"
45
46
47#define BUF_SIZE4096 4096
48#define FILE_PREFIX"file://" "file://"
49#define FILE_PREFIX_L7 7
50#define SPECIAL_DIR(x)((strcmp ((x), "..") == 0) || (strcmp ((x), ".") == 0)) ((strcmp ((x), "..") == 0) || (strcmp ((x), ".") == 0))
51
52
53gboolean
54uri_exists (const char *uri)
55{
56 GFile *file;
57 gboolean exists;
58
59 if (uri == NULL((void*)0))
60 return FALSE(0);
61
62 file = g_file_new_for_uri (uri);
63 exists = g_file_query_exists (file, NULL((void*)0));
64 g_object_unref (file);
65
66 return exists;
67}
68
69
70static gboolean
71uri_is_filetype (const char *uri,
72 GFileType file_type)
73{
74 gboolean result = FALSE(0);
75 GFile *file;
76 GFileInfo *info;
77 GError *error = NULL((void*)0);
78
79 file = g_file_new_for_uri (uri);
80
81 if (! g_file_query_exists (file, NULL((void*)0))) {
82 g_object_unref (file);
83 return FALSE(0);
84 }
85
86 info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type", 0, NULL((void*)0), &error);
87 if (error == NULL((void*)0)) {
88 result = (g_file_info_get_file_type (info) == file_type);
89 }
90 else {
91 g_warning ("Failed to get file type for uri %s: %s", uri, error->message);
92 g_error_free (error);
93 }
94
95 g_object_unref (info);
96 g_object_unref (file);
97
98 return result;
99}
100
101
102gboolean
103uri_is_file (const char *uri)
104{
105 return uri_is_filetype (uri, G_FILE_TYPE_REGULAR);
106}
107
108
109gboolean
110uri_is_dir (const char *uri)
111{
112 return uri_is_filetype (uri, G_FILE_TYPE_DIRECTORY);
113}
114
115
116gboolean
117path_is_dir (const char *path)
118{
119 char *uri;
120 gboolean result;
121
122 uri = g_filename_to_uri (path, NULL((void*)0), NULL((void*)0));
123 result = uri_is_dir (uri);
124 g_free (uri);
125
126 return result;
127}
128
129gboolean
130uri_is_local (const char *uri)
131{
132 return strncmp (uri, "file://", 7) == 0;
133}
134
135
136gboolean
137dir_is_empty (const char *uri)
138{
139 GFile *file;
140 GFileEnumerator *file_enum;
141 GFileInfo *info;
142 GError *error = NULL((void*)0);
143 int n = 0;
144
145 file = g_file_new_for_uri (uri);
146
147 if (! g_file_query_exists (file, NULL((void*)0))) {
148 g_object_unref (file);
149 return TRUE(!(0));
150 }
151
152 file_enum = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name", 0, NULL((void*)0), &error);
153 if (error != NULL((void*)0)) {
154 g_warning ("Failed to enumerate children of %s: %s", uri, error->message);
155 g_error_free (error);
156 g_object_unref (file_enum);
157 g_object_unref (file);
158 return TRUE(!(0));
159 }
160
161 while ((n == 0) && ((info = g_file_enumerator_next_file (file_enum, NULL((void*)0), &error)) != NULL((void*)0))) {
162 if (error != NULL((void*)0)) {
163 g_warning ("Encountered error while enumerating children of %s (ignoring): %s", uri, error->message);
164 g_error_free (error);
165 }
166 else if (! SPECIAL_DIR (g_file_info_get_name (info))((strcmp ((g_file_info_get_name (info)), "..") == 0) || (strcmp
((g_file_info_get_name (info)), ".") == 0))
)
167 n++;
168 g_object_unref (info);
169 }
170
171 g_object_unref (file);
172 g_object_unref (file_enum);
173
174 return (n == 0);
175}
176
177
178gboolean
179dir_contains_one_object (const char *uri)
180{
181 GFile *file;
182 GFileEnumerator *file_enum;
183 GFileInfo *info;
184 GError *err = NULL((void*)0);
185 int n = 0;
186
187 file = g_file_new_for_uri (uri);
188
189 if (! g_file_query_exists (file, NULL((void*)0))) {
190 g_object_unref (file);
191 return FALSE(0);
192 }
193
194 file_enum = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name", 0, NULL((void*)0), &err);
195 if (err != NULL((void*)0)) {
196 g_warning ("Failed to enumerate children of %s: %s", uri, err->message);
197 g_error_free (err);
198 g_object_unref (file_enum);
199 g_object_unref (file);
200 return FALSE(0);
201 }
202
203 while ((info = g_file_enumerator_next_file (file_enum, NULL((void*)0), &err)) != NULL((void*)0)) {
204 const char *name;
205
206 if (err != NULL((void*)0)) {
207 g_warning ("Encountered error while enumerating children of %s, ignoring: %s", uri, err->message);
208 g_error_free (err);
209 g_object_unref (info);
210 continue;
211 }
212
213 name = g_file_info_get_name (info);
214 if (strcmp (name, ".") == 0 || strcmp (name, "..") == 0) {
215 g_object_unref (info);
216 continue;
217 }
218
219 g_object_unref (info);
220
221 if (++n > 1)
222 break;
223 }
224
225 g_object_unref (file);
226 g_object_unref (file_enum);
227
228 return (n == 1);
229}
230
231
232char *
233get_dir_content_if_unique (const char *uri)
234{
235 GFile *file;
236 GFileEnumerator *file_enum;
237 GFileInfo *info;
238 GError *err = NULL((void*)0);
239 char *content_uri = NULL((void*)0);
240
241 file = g_file_new_for_uri (uri);
242
243 if (! g_file_query_exists (file, NULL((void*)0))) {
244 g_object_unref (file);
245 return NULL((void*)0);
246 }
247
248 file_enum = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name", 0, NULL((void*)0), &err);
249 if (err != NULL((void*)0)) {
250 g_warning ("Failed to enumerate children of %s: %s", uri, err->message);
251 g_error_free (err);
252 return NULL((void*)0);
253 }
254
255 while ((info = g_file_enumerator_next_file (file_enum, NULL((void*)0), &err)) != NULL((void*)0)) {
256 const char *name;
257
258 if (err != NULL((void*)0)) {
259 g_warning ("Failed to get info while enumerating children: %s", err->message);
260 g_clear_error (&err);
261 g_object_unref (info);
262 continue;
263 }
264
265 name = g_file_info_get_name (info);
266 if ((strcmp (name, ".") == 0) || (strcmp (name, "..") == 0)) {
267 g_object_unref (info);
268 continue;
269 }
270
271 if (content_uri != NULL((void*)0)) {
272 g_free (content_uri);
273 g_object_unref (info);
274 content_uri = NULL((void*)0);
275 break;
276 }
277
278 content_uri = build_uri (uri, name, NULL((void*)0));
279 g_object_unref (info);
280 }
281
282 if (err != NULL((void*)0)) {
283 g_warning ("Failed to get info after enumerating children: %s", err->message);
284 g_clear_error (&err);
285 }
286
287 g_object_unref (file_enum);
288 g_object_unref (file);
289
290 return content_uri;
291}
292
293
294/* Check whether the dirname is contained in filename */
295gboolean
296path_in_path (const char *dirname,
297 const char *filename)
298{
299 int dirname_l, filename_l, separator_position;
300
301 if ((dirname == NULL((void*)0)) || (filename == NULL((void*)0)))
302 return FALSE(0);
303
304 dirname_l = strlen (dirname);
305 filename_l = strlen (filename);
306
307 if ((dirname_l == filename_l + 1)
308 && (dirname[dirname_l - 1] == '/'))
309 return FALSE(0);
310
311 if ((filename_l == dirname_l + 1)
312 && (filename[filename_l - 1] == '/'))
313 return FALSE(0);
314
315 if (dirname[dirname_l - 1] == '/')
316 separator_position = dirname_l - 1;
317 else
318 separator_position = dirname_l;
319
320 return ((filename_l > dirname_l)
321 && (strncmp (dirname, filename, dirname_l) == 0)
322 && (filename[separator_position] == '/'));
323}
324
325
326goffset
327get_file_size (const char *uri)
328{
329 goffset size = 0;
330 GFile *file;
331 GFileInfo *info;
332 GError *err = NULL((void*)0);
333
334 if ((uri == NULL((void*)0)) || (*uri == '\0'))
335 return 0;
336
337 file = g_file_new_for_uri (uri);
338 info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size", 0, NULL((void*)0), &err);
339 if (err == NULL((void*)0)) {
340 size = g_file_info_get_size (info);
341 }
342 else {
343 g_warning ("Failed to get file size for %s: %s", uri, err->message);
344 g_error_free (err);
345 }
346
347 g_object_unref (info);
348 g_object_unref (file);
349
350 return size;
351}
352
353
354goffset
355get_file_size_for_path (const char *path)
356{
357 char *uri;
358 goffset result;
359
360 uri = g_filename_to_uri (path, NULL((void*)0), NULL((void*)0));
361 result = get_file_size (uri);
362 g_free (uri);
363
364 return result;
365}
366
367
368static time_t
369get_file_time_type (const char *uri,
370 const char *type)
371{
372 time_t result = 0;
373 GFile *file;
374 GFileInfo *info;
375 GError *err = NULL((void*)0);
376
377 if ((uri == NULL((void*)0)) || (*uri == '\0'))
378 return 0;
379
380 file = g_file_new_for_uri (uri);
381 info = g_file_query_info (file, type, 0, NULL((void*)0), &err);
382 if (err == NULL((void*)0)) {
383 result = (time_t) g_file_info_get_attribute_uint64 (info, type);
384 }
385 else {
386 g_warning ("Failed to get %s: %s", type, err->message);
387 g_error_free (err);
388 result = 0;
389 }
390
391 g_object_unref (info);
392 g_object_unref (file);
393
394 return result;
395}
396
397
398time_t
399get_file_mtime (const char *uri)
400{
401 return get_file_time_type (uri, G_FILE_ATTRIBUTE_TIME_MODIFIED"time::modified");
402}
403
404
405time_t
406get_file_mtime_for_path (const char *path)
407{
408 char *uri;
409 time_t result;
410
411 uri = g_filename_to_uri (path, NULL((void*)0), NULL((void*)0));
412 result = get_file_mtime (uri);
413 g_free (uri);
414
415 return result;
416}
417
418
419time_t
420get_file_ctime (const char *uri)
421{
422 return get_file_time_type (uri, G_FILE_ATTRIBUTE_TIME_CREATED"time::created");
423}
424
425
426gboolean
427file_is_hidden (const gchar *name)
428{
429 if (name[0] != '.') return FALSE(0);
430 if (name[1] == '\0') return FALSE(0);
431 if ((name[1] == '.') && (name[2] == '\0')) return FALSE(0);
432
433 return TRUE(!(0));
434}
435
436
437/* like g_path_get_basename but does not warn about NULL and does not
438 * alloc a new string. */
439const gchar* file_name_from_path(const gchar *file_name)
440{
441 register char *base;
442 register gssize last_char;
443
444 if (file_name == NULL((void*)0))
445 return NULL((void*)0);
446
447 if ((file_name[0] == '\0') || (strlen (file_name) == 0))
448 return "";
449
450 last_char = strlen (file_name) - 1;
451
452 if (file_name [last_char] == G_DIR_SEPARATOR'/')
453 return "";
454
455 base = g_utf8_strrchr (file_name, -1, G_DIR_SEPARATOR'/');
456 if (! base)
457 return file_name;
458
459 return base + 1;
460}
461
462
463char *
464dir_name_from_path (const gchar *path)
465{
466 register gssize base;
467 register gssize last_char;
468
469 if (path == NULL((void*)0))
470 return NULL((void*)0);
471
472 if (path[0] == '\0')
473 return g_strdup ("")g_strdup_inline ("");
474
475 last_char = strlen (path) - 1;
476 if (path[last_char] == G_DIR_SEPARATOR'/')
477 last_char--;
478
479 base = last_char;
480 while ((base >= 0) && (path[base] != G_DIR_SEPARATOR'/'))
481 base--;
482
483 return g_strndup (path + base + 1, last_char - base);
484}
485
486
487gchar *
488remove_level_from_path (const gchar *path)
489{
490 int p;
491 const char *ptr = path;
492 char *new_path;
493
494 if (path == NULL((void*)0))
495 return NULL((void*)0);
496
497 p = strlen (path) - 1;
498 if (p < 0)
499 return NULL((void*)0);
500
501 while ((p > 0) && (ptr[p] != '/'))
502 p--;
503 if ((p == 0) && (ptr[p] == '/'))
504 p++;
505 new_path = g_strndup (path, (guint)p);
506
507 return new_path;
508}
509
510
511char *
512remove_ending_separator (const char *path)
513{
514 gint len, copy_len;
515
516 if (path == NULL((void*)0))
517 return NULL((void*)0);
518
519 copy_len = len = strlen (path);
520 if ((len > 1) && (path[len - 1] == '/'))
521 copy_len--;
522
523 return g_strndup (path, copy_len);
524}
525
526
527char *
528build_uri (const char *base, ...)
529{
530 va_list args;
531 const char *child;
532 GString *uri;
533
534 uri = g_string_new (base);
535
536 va_start (args, base)__builtin_va_start(args, base);
537 while ((child = va_arg (args, const char *)__builtin_va_arg(args, const char *)) != NULL((void*)0)) {
538 if (! g_str_has_suffix (uri->str, "/")(__builtin_constant_p ("/")? __extension__ ({ const char * const
__str = (uri->str); const char * const __suffix = ("/"); gboolean
__result = (0); if (__str == ((void*)0) || __suffix == ((void
*)0)) __result = (g_str_has_suffix) (__str, __suffix); else {
const size_t __str_len = strlen (((__str) + !(__str))); const
size_t __suffix_len = strlen (((__suffix) + !(__suffix))); if
(__str_len >= __suffix_len) __result = memcmp (__str + __str_len
- __suffix_len, ((__suffix) + !(__suffix)), __suffix_len) ==
0; } __result; }) : (g_str_has_suffix) (uri->str, "/") )
&& ! g_str_has_prefix (child, "/")(__builtin_constant_p ("/")? __extension__ ({ const char * const
__str = (child); const char * const __prefix = ("/"); gboolean
__result = (0); if (__str == ((void*)0) || __prefix == ((void
*)0)) __result = (g_str_has_prefix) (__str, __prefix); else {
const size_t __str_len = strlen (((__str) + !(__str))); const
size_t __prefix_len = strlen (((__prefix) + !(__prefix))); if
(__str_len >= __prefix_len) __result = memcmp (((__str) +
!(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0; }
__result; }) : (g_str_has_prefix) (child, "/") )
)
539 g_string_append (uri, "/")(__builtin_constant_p ("/") ? __extension__ ({ const char * const
__val = ("/"); g_string_append_len_inline (uri, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (uri, "/", (gssize) -1
))
;
540 g_string_append (uri, child)(__builtin_constant_p (child) ? __extension__ ({ const char *
const __val = (child); g_string_append_len_inline (uri, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (uri, child
, (gssize) -1))
;
541 }
542 va_end (args)__builtin_va_end(args);
543
544 return g_string_free (uri, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((uri)
, ((0))) : g_string_free_and_steal (uri)) : (g_string_free) (
(uri), ((0))))
;
545}
546
547
548gchar *
549remove_extension_from_path (const gchar *path)
550{
551 int len;
552 int p;
553 const char *ptr = path;
554 char *new_path;
555
556 if (! path)
557 return NULL((void*)0);
558
559 len = strlen (path);
560 if (len == 1)
561 return g_strdup (path)g_strdup_inline (path);
562
563 p = len - 1;
564 while ((p > 0) && (ptr[p] != '.'))
565 p--;
566 if (p == 0)
567 p = len;
568 new_path = g_strndup (path, (guint) p);
569
570 return new_path;
571}
572
573
574gboolean
575make_directory_tree (GFile *dir,
576 mode_t mode,
577 GError **error)
578{
579 gboolean success = TRUE(!(0));
580 GFile *parent;
581
582 if ((dir == NULL((void*)0)) || g_file_query_exists (dir, NULL((void*)0)))
7
Assuming 'dir' is not equal to NULL
8
Assuming the condition is false
9
Taking false branch
583 return TRUE(!(0));
584
585 parent = g_file_get_parent (dir);
586 if (parent != NULL((void*)0)) {
10
Assuming 'parent' is equal to NULL
11
Taking false branch
587 success = make_directory_tree (parent, mode, error);
588 g_object_unref (parent);
589 if (! success)
590 return FALSE(0);
591 }
592
593 success = g_file_make_directory (dir, NULL((void*)0), error);
12
Assigning value
594 if ((error
12.1
'error' is not equal to NULL
!= NULL((void*)0)) && (*error != NULL((void*)0)) && g_error_matches (*error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_EXISTS)) {
13
Assuming pointer value is null
595 g_clear_error (error);
596 success = TRUE(!(0));
597 }
598
599 if (success)
14
Assuming 'success' is 0
15
Taking false branch
600 g_file_set_attribute_uint32 (dir,
601 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
602 mode,
603 0,
604 NULL((void*)0),
605 NULL((void*)0));
606
607 return success;
608}
609
610
611gboolean
612ensure_dir_exists (const char *uri,
613 mode_t mode,
614 GError **error)
615{
616 GFile *dir;
617 GError *priv_error = NULL((void*)0);
618
619 if (uri == NULL((void*)0))
2
Assuming 'uri' is not equal to NULL
3
Taking false branch
620 return FALSE(0);
621
622 if (error == NULL((void*)0))
4
Assuming 'error' is not equal to NULL
5
Taking false branch
623 error = &priv_error;
624
625 dir = g_file_new_for_uri (uri);
626 if (! make_directory_tree (dir, mode, error)) {
6
Calling 'make_directory_tree'
16
Returning from 'make_directory_tree'
17
Taking true branch
627 g_warning ("could create directory %s: %s", uri, (*error)->message);
18
Access to field 'message' results in a dereference of a null pointer
628 if (priv_error != NULL((void*)0))
629 g_clear_error (&priv_error);
630 return FALSE(0);
631 }
632
633 return TRUE(!(0));
634}
635
636
637gboolean
638make_directory_tree_from_path (const char *path,
639 mode_t mode,
640 GError **error)
641{
642 char *uri;
643 gboolean result;
644
645 uri = g_filename_to_uri (path, NULL((void*)0), NULL((void*)0));
646 result = ensure_dir_exists (uri, mode, error);
1
Calling 'ensure_dir_exists'
647 g_free (uri);
648
649 return result;
650}
651
652
653const char *
654get_file_extension (const char *filename)
655{
656 const char *ptr = filename;
657 int len;
658 int p;
659 const char *ext;
660
661 if (filename == NULL((void*)0))
662 return NULL((void*)0);
663
664 len = strlen (filename);
665 if (len <= 1)
666 return NULL((void*)0);
667
668 p = len - 1;
669 while ((p >= 0) && (ptr[p] != '.'))
670 p--;
671 if (p < 0)
672 return NULL((void*)0);
673
674 ext = filename + p;
675 if (ext - 4 > filename) {
676 const char *test = ext - 4;
677 if (strncmp (test, ".tar", 4) == 0)
678 ext = ext - 4;
679 }
680 return ext;
681}
682
683
684gboolean
685file_extension_is (const char *filename,
686 const char *ext)
687{
688 int filename_l, ext_l;
689
690 filename_l = strlen (filename);
691 ext_l = strlen (ext);
692
693 if (filename_l < ext_l)
694 return FALSE(0);
695 return strcasecmp (filename + filename_l - ext_l, ext) == 0;
696}
697
698
699gboolean
700is_mime_type (const char *mime_type,
701 const char *pattern)
702{
703 return (strcasecmp (mime_type, pattern) == 0);
704}
705
706
707const char*
708get_file_mime_type (const char *uri,
709 gboolean fast_file_type)
710{
711 GFile *file;
712 GFileInfo *info;
713 GError *err = NULL((void*)0);
714 const char *result = NULL((void*)0);
715
716 file = g_file_new_for_uri (uri);
717 info = g_file_query_info (file,
718 fast_file_type ?
719 G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE"standard::fast-content-type" :
720 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE"standard::content-type",
721 0, NULL((void*)0), &err);
722 if (info == NULL((void*)0)) {
723 g_warning ("could not get content type for %s: %s", uri, err->message);
724 g_clear_error (&err);
725 }
726 else {
727 result = get_static_string (g_file_info_get_content_type (info));
728 g_object_unref (info);
729 }
730
731 g_object_unref (file);
732
733 return result;
734}
735
736
737const char*
738get_file_mime_type_for_path (const char *filename,
739 gboolean fast_file_type)
740{
741 char *uri;
742 const char *mime_type;
743
744 uri = g_filename_to_uri (filename, NULL((void*)0), NULL((void*)0));
745 mime_type = get_file_mime_type (uri, fast_file_type);
746 g_free (uri);
747
748 return mime_type;
749}
750
751
752void
753path_list_free (GList *path_list)
754{
755 if (path_list == NULL((void*)0))
756 return;
757 g_list_free_full (path_list, g_free);
758}
759
760
761GList *
762path_list_dup (GList *path_list)
763{
764 GList *new_list = NULL((void*)0);
765 GList *scan;
766
767 for (scan = path_list; scan; scan = scan->next)
768 new_list = g_list_prepend (new_list, g_strdup (scan->data)g_strdup_inline (scan->data));
769
770 return g_list_reverse (new_list);
771}
772
773
774guint64
775get_dest_free_space (const char *path)
776{
777 guint64 freespace = 0;
778 GFile *file;
779 GFileInfo *info;
780 GError *err = NULL((void*)0);
781
782 file = g_file_new_for_path (path);
783 info = g_file_query_filesystem_info (file, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free", NULL((void*)0), &err);
784 if (info != NULL((void*)0)) {
785 freespace = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
786 g_object_unref (info);
787 }
788 else {
789 g_warning ("Could not get filesystem free space on volume that contains %s: %s", path, err->message);
790 g_error_free (err);
791 }
792 g_object_unref (file);
793
794 return freespace;
795}
796
797
798static gboolean
799delete_directory_recursive (GFile *dir,
800 GError **error)
801{
802 char *uri;
803 GFileEnumerator *file_enum;
804 GFileInfo *info;
805 gboolean error_occurred = FALSE(0);
806
807 if (error != NULL((void*)0))
808 *error = NULL((void*)0);
809
810 file_enum = g_file_enumerate_children (dir,
811 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name" ","
812 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type",
813 0, NULL((void*)0), error);
814
815 uri = g_file_get_uri (dir);
816 while (! error_occurred && (info = g_file_enumerator_next_file (file_enum, NULL((void*)0), error)) != NULL((void*)0)) {
817 char *child_uri;
818 GFile *child;
819
820 child_uri = build_uri (uri, g_file_info_get_name (info), NULL((void*)0));
821 child = g_file_new_for_uri (child_uri);
822
823 switch (g_file_info_get_file_type (info)) {
824 case G_FILE_TYPE_DIRECTORY:
825 if (! delete_directory_recursive (child, error))
826 error_occurred = TRUE(!(0));
827 break;
828 default:
829 if (! g_file_delete (child, NULL((void*)0), error))
830 error_occurred = TRUE(!(0));
831 break;
832 }
833
834 g_object_unref (child);
835 g_free (child_uri);
836 g_object_unref (info);
837 }
838 g_free (uri);
839
840 if (! error_occurred && ! g_file_delete (dir, NULL((void*)0), error))
841 error_occurred = TRUE(!(0));
842
843 g_object_unref (file_enum);
844
845 return ! error_occurred;
846}
847
848
849gboolean
850remove_directory (const char *uri)
851{
852 GFile *dir;
853 gboolean result;
854 GError *error = NULL((void*)0);
855
856 dir = g_file_new_for_uri (uri);
857 result = delete_directory_recursive (dir, &error);
858 if (! result) {
859 g_warning ("Cannot delete %s: %s", uri, error->message);
860 g_clear_error (&error);
861 }
862 g_object_unref (dir);
863
864 return result;
865}
866
867
868gboolean
869remove_local_directory (const char *path)
870{
871 char *uri;
872 gboolean result;
873
874 if (path == NULL((void*)0))
875 return TRUE(!(0));
876
877 uri = g_filename_to_uri (path, NULL((void*)0), NULL((void*)0));
878 result = remove_directory (uri);
879 g_free (uri);
880
881 return result;
882}
883
884
885static const char *try_folder[] = { "cache", "~", "tmp", NULL((void*)0) };
886
887
888static char *
889ith_temp_folder_to_try (int n)
890{
891 const char *folder;
892
893 folder = try_folder[n];
894 if (strcmp (folder, "cache") == 0)
895 folder = g_get_user_cache_dir ();
896 else if (strcmp (folder, "~") == 0)
897 folder = g_get_home_dir ();
898 else if (strcmp (folder, "tmp") == 0)
899 folder = g_get_tmp_dir ();
900
901 return g_strdup (folder)g_strdup_inline (folder);
902}
903
904
905char *
906get_temp_work_dir (const char *parent_folder)
907{
908 guint64 max_size = 0;
909 char *best_folder = NULL((void*)0);
910 char *template;
911 char *result = NULL((void*)0);
912
913 if (parent_folder == NULL((void*)0)) {
914 /* find the folder with more free space. */
915
916 int i;
917
918 for (i = 0; try_folder[i] != NULL((void*)0); i++) {
919 char *folder;
920 guint64 size;
921
922 folder = ith_temp_folder_to_try (i);
923 size = get_dest_free_space (folder);
924 if (max_size < size) {
925 max_size = size;
926 g_free (best_folder);
927 best_folder = folder;
928 }
929 else
930 g_free (folder);
931 }
932 }
933 else
934 best_folder = g_strdup (parent_folder)g_strdup_inline (parent_folder);
935
936 if (best_folder == NULL((void*)0))
937 return NULL((void*)0);
938
939 template = g_strconcat (best_folder, "/.fr-XXXXXX", NULL((void*)0));
940 result = mkdtemp (template);
941
942 if ((result == NULL((void*)0)) || (*result == '\0')) {
943 g_free (template);
944 result = NULL((void*)0);
945 }
946
947 return result;
948}
949
950
951gboolean
952is_temp_work_dir (const char *dir)
953{
954 int i;
955 char *folder = NULL((void*)0);
956
957 if (strncmp (dir, "file://", 7) == 0)
958 dir = dir + 7;
959 else if (dir[0] != '/')
960 return FALSE(0);
961
962 for (i = 0; try_folder[i] != NULL((void*)0); i++) {
963 folder = ith_temp_folder_to_try (i);
964 if (strncmp (dir, folder, strlen (folder)) == 0)
965 if (strncmp (dir + strlen (folder), "/.fr-", 5) == 0) {
966 g_free (folder);
967 return TRUE(!(0));
968 }
969 g_free (folder);
970 }
971
972 return FALSE(0);
973}
974
975
976gboolean
977is_temp_dir (const char *dir)
978{
979 if (strncmp (dir, "file://", 7) == 0)
980 dir = dir + 7;
981 if (strcmp (g_get_tmp_dir (), dir) == 0)
982 return TRUE(!(0));
983 if (path_in_path (g_get_tmp_dir (), dir))
984 return TRUE(!(0));
985 else
986 return is_temp_work_dir (dir);
987}
988
989
990/* file list utils */
991
992
993gboolean
994file_list__match_pattern (const char *line,
995 const char *pattern)
996{
997 const char *l = line, *p = pattern;
998
999 for (; (*p != 0) && (*l != 0); p++, l++) {
1000 if (*p != '%') {
1001 if (*p != *l)
1002 return FALSE(0);
1003 }
1004 else {
1005 p++;
1006 switch (*p) {
1007 case 'a':
1008 break;
1009 case 'n':
1010 if (!isdigit (*l)((*__ctype_b_loc ())[(int) ((*l))] & (unsigned short int)
_ISdigit)
)
1011 return FALSE(0);
1012 break;
1013 case 'c':
1014 if (!isalpha (*l)((*__ctype_b_loc ())[(int) ((*l))] & (unsigned short int)
_ISalpha)
)
1015 return FALSE(0);
1016 break;
1017 default:
1018 return FALSE(0);
1019 }
1020 }
1021 }
1022
1023 return (*p == 0);
1024}
1025
1026
1027int
1028file_list__get_index_from_pattern (const char *line,
1029 const char *pattern)
1030{
1031 int line_l, pattern_l;
1032 const char *l;
1033
1034 line_l = strlen (line);
1035 pattern_l = strlen (pattern);
1036
1037 if ((pattern_l == 0) || (line_l == 0))
1038 return -1;
1039
1040 for (l = line; *l != 0; l++)
1041 if (file_list__match_pattern (l, pattern))
1042 return (l - line);
1043
1044 return -1;
1045}
1046
1047
1048char*
1049file_list__get_next_field (const char *line,
1050 int start_from,
1051 int field_n)
1052{
1053 const char *f_start, *f_end;
1054
1055 line = line + start_from;
1056
1057 f_start = line;
1058 while ((*f_start == ' ') && (*f_start != *line))
1059 f_start++;
1060 f_end = f_start;
1061
1062 while ((field_n > 0) && (*f_end != 0)) {
1063 if (*f_end == ' ') {
1064 field_n--;
1065 if (field_n != 0) {
1066 while ((*f_end == ' ') && (*f_end != *line))
1067 f_end++;
1068 f_start = f_end;
1069 }
1070 } else
1071 f_end++;
1072 }
1073
1074 return g_strndup (f_start, f_end - f_start);
1075}
1076
1077
1078char*
1079file_list__get_prev_field (const char *line,
1080 int start_from,
1081 int field_n)
1082{
1083 const char *f_start, *f_end;
1084
1085 f_start = line + start_from - 1;
1086 while ((*f_start == ' ') && (*f_start != *line))
1087 f_start--;
1088 f_end = f_start;
1089
1090 while ((field_n > 0) && (*f_start != *line)) {
1091 if (*f_start == ' ') {
1092 field_n--;
1093 if (field_n != 0) {
1094 while ((*f_start == ' ') && (*f_start != *line))
1095 f_start--;
1096 f_end = f_start;
1097 }
1098 } else
1099 f_start--;
1100 }
1101
1102 return g_strndup (f_start + 1, f_end - f_start);
1103}
1104
1105
1106gboolean
1107check_permissions (const char *uri,
1108 int mode)
1109{
1110 GFile *file;
1111 gboolean result;
1112
1113 file = g_file_new_for_uri (uri);
1114 result = check_file_permissions (file, mode);
1115
1116 g_object_unref (file);
1117
1118 return result;
1119}
1120
1121
1122gboolean
1123check_file_permissions (GFile *file,
1124 int mode)
1125{
1126 gboolean result = TRUE(!(0));
1127 GFileInfo *info;
1128 GError *err = NULL((void*)0);
1129 gboolean default_permission_when_unknown = TRUE(!(0));
1130
1131 info = g_file_query_info (file, "access::*", 0, NULL((void*)0), &err);
1132 if (err != NULL((void*)0)) {
1133 g_clear_error (&err);
1134 result = FALSE(0);
1135 }
1136 else {
1137 if ((mode & R_OK4) == R_OK4) {
1138 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read"))
1139 result = (result && g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read"));
1140 else
1141 result = (result && default_permission_when_unknown);
1142 }
1143
1144 if ((mode & W_OK2) == W_OK2) {
1145 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write"))
1146 result = (result && g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write"));
1147 else
1148 result = (result && default_permission_when_unknown);
1149 }
1150
1151 if ((mode & X_OK1) == X_OK1) {
1152 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute"))
1153 result = (result && g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute"));
1154 else
1155 result = (result && default_permission_when_unknown);
1156 }
1157
1158 g_object_unref (info);
1159 }
1160
1161 return result;
1162}
1163
1164
1165gboolean
1166is_program_in_path (const char *filename)
1167{
1168 char *str;
1169 char *value;
1170 int result = FALSE(0);
1171
1172 value = g_hash_table_lookup (ProgramsCache, filename);
1173 if (value != NULL((void*)0)) {
1174 result = (strcmp (value, "1") == 0);
1175 return result;
1176 }
1177
1178 str = g_find_program_in_path (filename);
1179 if (str != NULL((void*)0)) {
1180 g_free (str);
1181 result = TRUE(!(0));
1182 }
1183
1184 g_hash_table_insert (ProgramsCache,
1185 g_strdup (filename)g_strdup_inline (filename),
1186 result ? "1" : "0");
1187
1188 return result;
1189}
1190
1191
1192gboolean
1193is_program_available (const char *filename,
1194 gboolean check)
1195{
1196 return ! check || is_program_in_path (filename);
1197}
1198
1199
1200const char *
1201get_home_uri (void)
1202{
1203 static char *home_uri = NULL((void*)0);
1204 if (home_uri == NULL((void*)0))
1205 home_uri = g_filename_to_uri (g_get_home_dir (), NULL((void*)0), NULL((void*)0));
1206 return home_uri;
1207}
1208
1209
1210char *
1211get_home_relative_uri (const char *partial_uri)
1212{
1213 return g_strconcat (get_home_uri (),
1214 "/",
1215 partial_uri,
1216 NULL((void*)0));
1217}
1218
1219
1220GFile *
1221get_home_relative_file (const char *partial_uri)
1222{
1223 GFile *file;
1224 char *uri;
1225
1226 uri = g_strconcat (get_home_uri (), "/", partial_uri, NULL((void*)0));
1227 file = g_file_new_for_uri (uri);
1228 g_free (uri);
1229
1230 return file;
1231}
1232
1233
1234GFile *
1235get_user_config_subdirectory (const char *child_name,
1236 gboolean create_child)
1237{
1238 char *full_path;
1239 GFile *file;
1240 GError *error = NULL((void*)0);
1241
1242 full_path = g_strconcat (g_get_user_config_dir (), "/", child_name, NULL((void*)0));
1243 file = g_file_new_for_path (full_path);
1244 g_free (full_path);
1245
1246 if (create_child && ! make_directory_tree (file, 0700, &error)) {
1247 g_warning ("%s", error->message);
1248 g_error_free (error);
1249 g_object_unref (file);
1250 file = NULL((void*)0);
1251 }
1252
1253 return file;
1254}
1255
1256
1257const char *
1258remove_host_from_uri (const char *uri)
1259{
1260 const char *idx, *sep;
1261
1262 if (uri == NULL((void*)0))
1263 return NULL((void*)0);
1264
1265 idx = strstr (uri, "://");
1266 if (idx == NULL((void*)0))
1267 return uri;
1268 idx += 3;
1269 if (*idx == '\0')
1270 return "/";
1271 sep = strstr (idx, "/");
1272 if (sep == NULL((void*)0))
1273 return idx;
1274 return sep;
1275}
1276
1277
1278char *
1279get_uri_host (const char *uri)
1280{
1281 const char *idx;
1282
1283 idx = strstr (uri, "://");
1284 if (idx == NULL((void*)0))
1285 return NULL((void*)0);
1286 idx = strstr (idx + 3, "/");
1287 if (idx == NULL((void*)0))
1288 return NULL((void*)0);
1289 return g_strndup (uri, (idx - uri));
1290}
1291
1292
1293char *
1294get_uri_root (const char *uri)
1295{
1296 char *host;
1297 char *root;
1298
1299 host = get_uri_host (uri);
1300 if (host == NULL((void*)0))
1301 return NULL((void*)0);
1302 root = g_strconcat (host, "/", NULL((void*)0));
1303 g_free (host);
1304
1305 return root;
1306}
1307
1308
1309int
1310uricmp (const char *uri1,
1311 const char *uri2)
1312{
1313 return strcmp_null_tolerant (uri1, uri2);
1314}
1315
1316
1317char *
1318get_alternative_uri (const char *folder,
1319 const char *name)
1320{
1321 char *new_uri = NULL((void*)0);
1322 int n = 1;
1323
1324 do {
1325 g_free (new_uri);
1326 if (n == 1)
1327 new_uri = g_strconcat (folder, "/", name, NULL((void*)0));
1328 else
1329 new_uri = g_strdup_printf ("%s/%s%%20(%d)", folder, name, n);
1330 n++;
1331 } while (uri_exists (new_uri));
1332
1333 return new_uri;
1334}
1335
1336
1337char *
1338get_alternative_uri_for_uri (const char *uri)
1339{
1340 char *base_uri;
1341 char *new_uri;
1342
1343 base_uri = remove_level_from_path (uri);
1344 new_uri = get_alternative_uri (base_uri, file_name_from_path (uri));
1345 g_free (base_uri);
1346
1347 return new_uri;
1348}
1349
1350
1351GList *
1352gio_file_list_dup (GList *l)
1353{
1354 GList *r = NULL((void*)0), *scan;
1355 for (scan = l; scan; scan = scan->next)
1356 r = g_list_prepend (r, g_file_dup ((GFile*)scan->data));
1357 return g_list_reverse (r);
1358}
1359
1360
1361void
1362gio_file_list_free (GList *l)
1363{
1364 GList *scan;
1365 for (scan = l; scan; scan = scan->next)
1366 g_object_unref (scan->data);
1367 g_list_free (l);
1368}
1369
1370
1371GList *
1372gio_file_list_new_from_uri_list (GList *uris)
1373{
1374 GList *r = NULL((void*)0), *scan;
1375 for (scan = uris; scan; scan = scan->next)
1376 r = g_list_prepend (r, g_file_new_for_uri ((char*)scan->data));
1377 return g_list_reverse (r);
1378}
1379
1380
1381void
1382g_key_file_save (GKeyFile *key_file,
1383 GFile *file)
1384{
1385 char *file_data;
1386 gsize size;
1387 GError *error = NULL((void*)0);
1388
1389 file_data = g_key_file_to_data (key_file, &size, &error);
1390 if (error != NULL((void*)0)) {
1391 g_warning ("Could not save options: %s\n", error->message);
1392 g_clear_error (&error);
1393 }
1394 else {
1395 GFileOutputStream *stream;
1396
1397 stream = g_file_replace (file, NULL((void*)0), FALSE(0), 0, NULL((void*)0), &error);
1398 if (stream == NULL((void*)0)) {
1399 g_warning ("Could not save options: %s\n", error->message);
1400 g_clear_error (&error);
1401 }
1402 else if (! g_output_stream_write_all (G_OUTPUT_STREAM (stream)((((GOutputStream*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stream)), ((g_output_stream_get_type ()))))))
, file_data, size, NULL((void*)0), NULL((void*)0), &error)) {
1403 g_warning ("Could not save options: %s\n", error->message);
1404 g_clear_error (&error);
1405 }
1406 else if (! g_output_stream_close (G_OUTPUT_STREAM (stream)((((GOutputStream*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((stream)), ((g_output_stream_get_type ()))))))
, NULL((void*)0), &error)) {
1407 g_warning ("Could not save options: %s\n", error->message);
1408 g_clear_error (&error);
1409 }
1410
1411 g_object_unref (stream);
1412 }
1413
1414 g_free (file_data);
1415}