Coverage Report

Created: 2026-08-15 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-path-store.c
Line
Count
Source
1
/*
2
 * Copyright 2026 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
0
#define G_LOG_DOMAIN "FuPathStore"
8
9
#include "config.h"
10
11
#include "fu-path-store.h"
12
13
struct _FuPathStore {
14
  GObject parent_instance;
15
  gchar *paths[FU_PATH_KIND_LAST];
16
  gboolean loaded_defaults;
17
  gboolean loaded_from_env;
18
  GPtrArray *program_paths; /* element-type utf-8*/
19
};
20
21
0
G_DEFINE_TYPE(FuPathStore, fu_path_store, G_TYPE_OBJECT)
22
0
23
0
/**
24
0
 * fu_path_store_add_program_path:
25
0
 * @self: a #FuPathStore
26
0
 * @path: (not nullable): directory name
27
0
 *
28
0
 * Sets a possible program path.
29
0
 *
30
0
 * If the directory does not exist it is ignored
31
0
 *
32
0
 * Since: 2.1.5
33
0
 **/
34
0
void
35
0
fu_path_store_add_program_path(FuPathStore *self, const gchar *path)
36
0
{
37
0
  g_return_if_fail(FU_IS_PATH_STORE(self));
38
0
  g_return_if_fail(path != NULL);
39
40
0
  if (!g_file_test(path, G_FILE_TEST_IS_DIR))
41
0
    return;
42
0
  if (g_ptr_array_find_with_equal_func(self->program_paths, path, g_str_equal, NULL))
43
0
    return;
44
0
  g_ptr_array_add(self->program_paths, g_strdup(path));
45
0
}
46
47
/**
48
 * fu_path_store_find_program:
49
 * @self: a #FuPathStore
50
 * @basename: the program to search
51
 * @error: (nullable): optional return location for an error
52
 *
53
 * Looks for a program in a path added by fu_path_store_add_program_path() -- in most cases this
54
 * will be the same as the `PATH` environment variable.
55
 *
56
 * Returns: a new path, or %NULL for error
57
 *
58
 * Since: 2.1.5
59
 **/
60
gchar *
61
fu_path_store_find_program(FuPathStore *self, const gchar *basename, GError **error)
62
0
{
63
0
  g_return_val_if_fail(FU_IS_PATH_STORE(self), NULL);
64
0
  g_return_val_if_fail(basename != NULL, NULL);
65
0
  g_return_val_if_fail(error == NULL || *error == NULL, NULL);
66
67
0
  for (guint i = 0; i < self->program_paths->len; i++) {
68
0
    const gchar *path = g_ptr_array_index(self->program_paths, i);
69
0
    g_autofree gchar *fn = g_build_filename(path, basename, NULL);
70
0
    if (g_file_test(fn, G_FILE_TEST_IS_EXECUTABLE))
71
0
      return g_steal_pointer(&fn);
72
0
  }
73
0
  g_set_error(error,
74
0
        FWUPD_ERROR,
75
0
        FWUPD_ERROR_NOT_FOUND,
76
0
        "missing executable %s in PATH",
77
0
        basename);
78
0
  return NULL;
79
0
}
80
81
/**
82
 * fu_path_store_get_path:
83
 * @self: a #FuPathStore
84
 * @kind: a #FuPathKind e.g. %FU_PATH_KIND_DATADIR_PKG
85
 * @error: (nullable): optional return location for an error
86
 *
87
 * Gets the defined path for the @kind.
88
 *
89
 * Returns: filename, or %NULL
90
 *
91
 * Since: 2.1.1
92
 **/
93
const gchar *
94
fu_path_store_get_path(FuPathStore *self, FuPathKind kind, GError **error)
95
0
{
96
0
  g_return_val_if_fail(FU_IS_PATH_STORE(self), NULL);
97
0
  g_return_val_if_fail(kind < FU_PATH_KIND_LAST, NULL);
98
0
  g_return_val_if_fail(error == NULL || *error == NULL, NULL);
99
0
  if (self->paths[kind] == NULL) {
100
0
    g_set_error(error,
101
0
          FWUPD_ERROR,
102
0
          FWUPD_ERROR_NOT_SUPPORTED,
103
0
          "no path set for %s",
104
0
          fu_path_kind_to_string(kind));
105
0
    return NULL;
106
0
  }
107
0
  return self->paths[kind];
108
0
}
109
110
/**
111
 * fu_path_store_build_filename:
112
 * @self: a #FuPathStore
113
 * @error: (nullable): optional return location for an error
114
 * @kind: a #FuPathKind e.g. %FU_PATH_KIND_DATADIR_PKG
115
 * @...: pairs of string key values, ending with %NULL
116
 *
117
 * Gets a fwupd-specific system path. These can be overridden with various
118
 * environment variables, for instance %FWUPD_DATADIR.
119
 *
120
 * Returns: a system path, or %NULL if invalid
121
 *
122
 * Since: 2.1.1
123
 **/
124
gchar *
125
fu_path_store_build_filename(FuPathStore *self, GError **error, FuPathKind kind, ...)
126
0
{
127
0
  va_list args;
128
0
  gchar *path;
129
0
  const gchar *path_prefix = NULL;
130
131
0
  g_return_val_if_fail(FU_IS_PATH_STORE(self), NULL);
132
0
  g_return_val_if_fail(error == NULL || *error == NULL, NULL);
133
0
  g_return_val_if_fail(kind < FU_PATH_KIND_LAST, NULL);
134
135
0
  path_prefix = fu_path_store_get_path(self, kind, error);
136
0
  if (path_prefix == NULL)
137
0
    return NULL;
138
139
0
  va_start(args, kind);
140
0
  path = g_build_filename_valist(path_prefix, &args);
141
0
  va_end(args);
142
143
0
  return path;
144
0
}
145
146
/**
147
 * fu_path_store_set_path:
148
 * @self: a #FuPathStore
149
 * @kind: a #FuPathKind e.g. %FU_PATH_KIND_DATADIR_PKG
150
 * @path: (nullable): directory name
151
 *
152
 * Sets the defined path for the @kind.
153
 *
154
 * Since: 2.1.1
155
 **/
156
void
157
fu_path_store_set_path(FuPathStore *self, FuPathKind kind, const gchar *path)
158
0
{
159
0
  g_return_if_fail(FU_IS_PATH_STORE(self));
160
0
  g_return_if_fail(kind < FU_PATH_KIND_LAST);
161
0
  g_free(self->paths[kind]);
162
0
  self->paths[kind] = g_strdup(path);
163
0
}
164
165
/**
166
 * fu_path_store_set_tmpdir:
167
 * @self: a #FuPathStore
168
 * @kind: a #FuPathKind e.g. %FU_PATH_KIND_DATADIR_PKG
169
 * @tmpdir: (not nullable): a #FuTemporaryDirectory
170
 *
171
 * Sets the @kind to a temporary path.
172
 *
173
 * Since: 2.1.1
174
 **/
175
void
176
fu_path_store_set_tmpdir(FuPathStore *self, FuPathKind kind, FuTemporaryDirectory *tmpdir)
177
0
{
178
0
  g_return_if_fail(FU_IS_PATH_STORE(self));
179
0
  g_return_if_fail(kind < FU_PATH_KIND_LAST);
180
0
  g_return_if_fail(FU_IS_TEMPORARY_DIRECTORY(tmpdir));
181
0
  fu_path_store_set_path(self, kind, fu_temporary_directory_get_path(tmpdir));
182
0
}
183
184
/**
185
 * fu_path_store_add_prefix:
186
 * @self: a #FuPathStore
187
 * @prefix: (not nullable): directory name
188
 *
189
 * Sets the prefix path for the @kind.
190
 *
191
 * Since: 2.1.1
192
 **/
193
void
194
fu_path_store_add_prefix(FuPathStore *self, FuPathKind kind, const gchar *prefix)
195
0
{
196
0
  gchar *path;
197
0
  g_return_if_fail(FU_IS_PATH_STORE(self));
198
0
  g_return_if_fail(kind < FU_PATH_KIND_LAST);
199
0
  g_return_if_fail(prefix != NULL);
200
201
0
  if (self->paths[kind] == NULL)
202
0
    return;
203
0
  path = g_build_filename(prefix, self->paths[kind], NULL);
204
0
  g_free(self->paths[kind]);
205
0
  self->paths[kind] = path;
206
0
}
207
208
static void
209
fu_path_store_add_dir(FuPathStore *self, FuPathKind kind, const gchar *first, ...)
210
0
{
211
0
  va_list args;
212
0
  g_autofree gchar *dir = NULL;
213
214
0
  va_start(args, first);
215
0
  dir = g_build_filename_valist(first, &args);
216
0
  va_end(args);
217
218
0
  fu_path_store_set_path(self, kind, dir);
219
0
}
220
221
static void
222
fu_path_store_ensure_lockdir(FuPathStore *self)
223
0
{
224
0
  const gchar *dirs[] = {
225
#ifdef __ANDROID__
226
      "/data/vendor/fwupd/run",
227
#else
228
0
      "/run/lock",
229
0
      "/var/run",
230
0
#endif
231
0
  };
232
0
  for (guint i = 0; i < G_N_ELEMENTS(dirs); i++) {
233
0
    if (g_file_test(dirs[i], G_FILE_TEST_EXISTS)) {
234
0
      fu_path_store_set_path(self, FU_PATH_KIND_LOCKDIR, dirs[i]);
235
0
      break;
236
0
    }
237
0
  }
238
0
}
239
240
static void
241
fu_path_store_ensure_localtime(FuPathStore *self)
242
0
{
243
0
  const gchar *dirs[] = {
244
0
      "/var/lib/timezone/localtime",
245
0
      FWUPD_SYSCONFDIR "/localtime",
246
0
      "/etc/localtime",
247
0
  };
248
0
  for (guint i = 0; i < G_N_ELEMENTS(dirs); i++) {
249
0
    g_debug("looking for %s", dirs[i]);
250
0
    if (g_file_test(dirs[i], G_FILE_TEST_EXISTS)) {
251
0
      fu_path_store_set_path(self, FU_PATH_KIND_LOCALTIME, dirs[i]);
252
0
      break;
253
0
    }
254
0
  }
255
0
}
256
257
#ifdef _WIN32
258
static gchar *
259
fu_path_store_get_win32_basedir(void)
260
{
261
  char drive_buf[_MAX_DRIVE];
262
  char dir_buf[_MAX_DIR];
263
  _splitpath(_pgmptr, drive_buf, dir_buf, NULL, NULL);
264
  return g_build_filename(drive_buf, dir_buf, "..", NULL);
265
}
266
#endif
267
268
/**
269
 * fu_path_store_load_defaults:
270
 * @self: a #FuPathStore
271
 *
272
 * Load the default paths for a typical system.
273
 *
274
 * Since: 2.1.1
275
 **/
276
void
277
fu_path_store_load_defaults(FuPathStore *self)
278
0
{
279
#ifdef _WIN32
280
  g_autofree gchar *win32_basedir = fu_path_store_get_win32_basedir();
281
#endif
282
283
0
  g_return_if_fail(FU_IS_PATH_STORE(self));
284
285
  /* already done */
286
0
  if (self->loaded_defaults)
287
0
    return;
288
289
  /* hardcoded */
290
0
  fu_path_store_set_path(self, FU_PATH_KIND_HOSTFS_ROOT, "/");
291
0
  fu_path_store_set_path(self, FU_PATH_KIND_HOSTFS_BOOT, "/boot");
292
0
  fu_path_store_set_path(self, FU_PATH_KIND_PROCFS, "/proc");
293
0
  fu_path_store_set_path(self, FU_PATH_KIND_DEVFS, "/dev");
294
0
  fu_path_store_set_path(self, FU_PATH_KIND_RUNDIR, "/run");
295
0
  fu_path_store_set_path(self, FU_PATH_KIND_SYSFSDIR, "/sys");
296
0
  fu_path_store_set_path(self, FU_PATH_KIND_SYSFSDIR_FW, "/sys/firmware");
297
0
  fu_path_store_set_path(self, FU_PATH_KIND_SYSFSDIR_TPM, "/sys/class/tpm");
298
0
  fu_path_store_set_path(self, FU_PATH_KIND_SYSFSDIR_DRIVERS, "/sys/bus/platform/drivers");
299
0
  fu_path_store_set_path(self, FU_PATH_KIND_SYSFSDIR_SECURITY, "/sys/kernel/security");
300
0
  fu_path_store_set_path(self, FU_PATH_KIND_SYSFSDIR_DMI, "/sys/class/dmi/id");
301
0
  fu_path_store_set_path(self, FU_PATH_KIND_ACPI_TABLES, "/sys/firmware/acpi/tables");
302
0
  fu_path_store_set_path(self,
303
0
             FU_PATH_KIND_FIRMWARE_SEARCH,
304
0
             "/sys/module/firmware_class/parameters/path");
305
0
  fu_path_store_set_path(self,
306
0
             FU_PATH_KIND_SYSFSDIR_FW_ATTRIB,
307
0
             "/sys/class/firmware-attributes");
308
0
  fu_path_store_set_path(self, FU_PATH_KIND_DEBUGFSDIR, "/sys/kernel/debug");
309
310
  /* defined from the buildsystem */
311
0
  fu_path_store_set_path(self, FU_PATH_KIND_LOCALSTATEDIR, FWUPD_LOCALSTATEDIR);
312
0
  fu_path_store_set_path(self, FU_PATH_KIND_LIBEXECDIR, FWUPD_LIBEXECDIR);
313
0
  fu_path_store_add_dir(self,
314
0
            FU_PATH_KIND_LIBEXECDIR_PKG,
315
0
            FWUPD_LIBEXECDIR,
316
0
            PACKAGE_NAME,
317
0
            NULL);
318
0
  fu_path_store_set_path(self, FU_PATH_KIND_DATADIR_VENDOR_IDS, FWUPD_DATADIR_VENDOR_IDS);
319
0
  fu_path_store_add_dir(self,
320
0
            FU_PATH_KIND_LOCALSTATEDIR_PKG,
321
0
            FWUPD_LOCALSTATEDIR,
322
0
            "lib",
323
0
            PACKAGE_NAME,
324
0
            NULL);
325
0
  fu_path_store_add_dir(self,
326
0
            FU_PATH_KIND_LOCALSTATEDIR_QUIRKS,
327
0
            FWUPD_LOCALSTATEDIR,
328
0
            "lib",
329
0
            PACKAGE_NAME,
330
0
            "quirks.d",
331
0
            NULL);
332
0
  fu_path_store_add_dir(self,
333
0
            FU_PATH_KIND_LOCALSTATEDIR_METADATA,
334
0
            FWUPD_LOCALSTATEDIR,
335
0
            "lib",
336
0
            PACKAGE_NAME,
337
0
            "metadata",
338
0
            NULL);
339
0
  fu_path_store_add_dir(self,
340
0
            FU_PATH_KIND_LOCALSTATEDIR_REMOTES,
341
0
            FWUPD_LOCALSTATEDIR,
342
0
            "lib",
343
0
            PACKAGE_NAME,
344
0
            "remotes.d",
345
0
            NULL);
346
0
  fu_path_store_add_dir(self,
347
0
            FU_PATH_KIND_CACHEDIR_PKG,
348
0
            FWUPD_LOCALSTATEDIR,
349
0
            "cache",
350
0
            PACKAGE_NAME,
351
0
            NULL);
352
0
  fu_path_store_add_dir(self,
353
0
            FU_PATH_KIND_LOCALCONFDIR_PKG,
354
0
            FWUPD_LOCALSTATEDIR,
355
0
            "etc",
356
0
            PACKAGE_NAME,
357
0
            NULL);
358
0
  fu_path_store_set_path(self, FU_PATH_KIND_SYSCONFDIR, FWUPD_SYSCONFDIR);
359
0
  fu_path_store_add_dir(self,
360
0
            FU_PATH_KIND_SYSCONFDIR_PKG,
361
0
            FWUPD_SYSCONFDIR,
362
0
            PACKAGE_NAME,
363
0
            NULL);
364
0
  fu_path_store_set_path(self, FU_PATH_KIND_LIBDIR_PKG, FWUPD_LIBDIR_PKG);
365
0
  fu_path_store_add_dir(self, FU_PATH_KIND_DATADIR_PKG, FWUPD_DATADIR, PACKAGE_NAME, NULL);
366
0
  fu_path_store_add_dir(self,
367
0
            FU_PATH_KIND_DATADIR_QUIRKS,
368
0
            FWUPD_DATADIR,
369
0
            PACKAGE_NAME,
370
0
            "quirks.d",
371
0
            NULL);
372
#ifdef EFI_APP_LOCATION
373
  fu_path_store_set_path(self, FU_PATH_KIND_EFIAPPDIR, EFI_APP_LOCATION);
374
#endif
375
376
  /* discovered from the filesystem */
377
0
  fu_path_store_ensure_lockdir(self);
378
0
  fu_path_store_ensure_localtime(self);
379
380
#ifdef _WIN32
381
  /* fix up WIN32 */
382
  fu_path_store_set_path(self, FU_PATH_KIND_WIN32_BASEDIR, win32_basedir);
383
  fu_path_store_add_prefix(self, FU_PATH_KIND_SYSCONFDIR, win32_basedir);
384
  fu_path_store_add_prefix(self, FU_PATH_KIND_SYSCONFDIR_PKG, win32_basedir);
385
  fu_path_store_add_prefix(self, FU_PATH_KIND_LIBDIR_PKG, win32_basedir);
386
  fu_path_store_add_prefix(self, FU_PATH_KIND_DATADIR_PKG, win32_basedir);
387
  fu_path_store_add_prefix(self, FU_PATH_KIND_DATADIR_QUIRKS, win32_basedir);
388
#endif
389
390
  /* success */
391
0
  self->loaded_defaults = TRUE;
392
0
}
393
394
/**
395
 * fu_path_store_load_from_env:
396
 * @self: a #FuPathStore
397
 *
398
 * Apply environment-based overrides to the existing paths.
399
 *
400
 * Since: 2.1.1
401
 **/
402
void
403
fu_path_store_load_from_env(FuPathStore *self)
404
0
{
405
0
  const gchar *tmp;
406
0
  struct {
407
0
    const gchar *env;
408
0
    FuPathKind kind;
409
0
  } envmap[] = {
410
0
      {"CACHE_DIRECTORY", FU_PATH_KIND_CACHEDIR_PKG},
411
0
      {"CONFIGURATION_DIRECTORY", FU_PATH_KIND_SYSCONFDIR_PKG},
412
0
      {"LOCALCONF_DIRECTORY", FU_PATH_KIND_LOCALCONFDIR_PKG},
413
0
      {"STATE_DIRECTORY", FU_PATH_KIND_LOCALSTATEDIR_PKG},
414
0
      {"FWUPD_DATADIR_QUIRKS", FU_PATH_KIND_DATADIR_QUIRKS},
415
0
      {"FWUPD_HOSTFS_ROOT", FU_PATH_KIND_HOSTFS_ROOT},
416
0
      {"FWUPD_LIBDIR_PKG", FU_PATH_KIND_LIBDIR_PKG},
417
0
      {"FWUPD_LOCKDIR", FU_PATH_KIND_LOCKDIR},
418
0
      {"FWUPD_SYSFSFWATTRIBDIR", FU_PATH_KIND_SYSFSDIR_FW_ATTRIB},
419
0
      {"FWUPD_SYSFSFWDIR", FU_PATH_KIND_SYSFSDIR_FW},
420
0
      {"FWUPD_UEFI_ESP_PATH", FU_PATH_KIND_UEFI_ESP},
421
0
  };
422
423
0
  g_return_if_fail(FU_IS_PATH_STORE(self));
424
425
  /* already done */
426
0
  if (self->loaded_from_env)
427
0
    return;
428
429
  /* special cases */
430
0
  tmp = g_getenv("FWUPD_LOCALSTATEDIR");
431
0
  if (tmp != NULL) {
432
0
    fu_path_store_set_path(self, FU_PATH_KIND_LOCALSTATEDIR, tmp);
433
0
    fu_path_store_add_dir(self,
434
0
              FU_PATH_KIND_LOCALSTATEDIR_PKG,
435
0
              tmp,
436
0
              "lib",
437
0
              PACKAGE_NAME,
438
0
              NULL);
439
0
    fu_path_store_add_dir(self,
440
0
              FU_PATH_KIND_LOCALSTATEDIR_QUIRKS,
441
0
              tmp,
442
0
              "lib",
443
0
              PACKAGE_NAME,
444
0
              "quirks.d",
445
0
              NULL);
446
0
    fu_path_store_add_dir(self,
447
0
              FU_PATH_KIND_LOCALSTATEDIR_METADATA,
448
0
              tmp,
449
0
              "lib",
450
0
              PACKAGE_NAME,
451
0
              "metadata",
452
0
              NULL);
453
0
    fu_path_store_add_dir(self,
454
0
              FU_PATH_KIND_LOCALSTATEDIR_REMOTES,
455
0
              tmp,
456
0
              "lib",
457
0
              PACKAGE_NAME,
458
0
              "remotes.d",
459
0
              NULL);
460
0
    fu_path_store_add_dir(self,
461
0
              FU_PATH_KIND_LOCALCONFDIR_PKG,
462
0
              tmp,
463
0
              "etc",
464
0
              PACKAGE_NAME,
465
0
              NULL);
466
0
  }
467
0
  tmp = g_getenv("FWUPD_DATADIR");
468
0
  if (tmp != NULL) {
469
0
    fu_path_store_set_path(self, FU_PATH_KIND_DATADIR_PKG, tmp);
470
0
    fu_path_store_add_dir(self, FU_PATH_KIND_DATADIR_QUIRKS, tmp, "quirks.d", NULL);
471
0
  }
472
0
  tmp = g_getenv("FWUPD_SYSCONFDIR");
473
0
  if (tmp != NULL) {
474
0
    fu_path_store_set_path(self, FU_PATH_KIND_SYSCONFDIR, tmp);
475
0
    fu_path_store_add_dir(self, FU_PATH_KIND_SYSCONFDIR_PKG, tmp, PACKAGE_NAME, NULL);
476
0
  }
477
0
  tmp = g_getenv("FWUPD_LIBEXECDIR");
478
0
  if (tmp != NULL) {
479
0
    fu_path_store_set_path(self, FU_PATH_KIND_LIBEXECDIR, tmp);
480
0
    fu_path_store_add_dir(self, FU_PATH_KIND_LIBEXECDIR_PKG, tmp, PACKAGE_NAME, NULL);
481
0
  }
482
483
0
  for (guint i = 0; i < G_N_ELEMENTS(envmap); i++) {
484
0
    tmp = g_getenv(envmap[i].env);
485
0
    if (tmp != NULL)
486
0
      fu_path_store_set_path(self, envmap[i].kind, tmp);
487
0
  }
488
489
#ifdef _WIN32
490
  /* WIN32 special case */
491
  tmp = g_getenv("USERPROFILE");
492
  if (tmp != NULL) {
493
    fu_path_store_add_dir(self,
494
              FU_PATH_KIND_LOCALSTATEDIR,
495
              tmp,
496
              PACKAGE_NAME,
497
              FWUPD_LOCALSTATEDIR,
498
              NULL);
499
  }
500
#endif
501
502
  /* snap special case */
503
0
  tmp = g_getenv("SNAP_COMMON");
504
0
  if (tmp != NULL) {
505
0
    fu_path_store_add_dir(self,
506
0
              FU_PATH_KIND_CACHEDIR_PKG,
507
0
              tmp,
508
0
              "var",
509
0
              "local",
510
0
              "cache",
511
0
              PACKAGE_NAME,
512
0
              NULL);
513
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_LOCALSTATEDIR, tmp);
514
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_LOCALSTATEDIR_METADATA, tmp);
515
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_LOCALSTATEDIR_PKG, tmp);
516
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_LOCALSTATEDIR_QUIRKS, tmp);
517
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_LOCALSTATEDIR_REMOTES, tmp);
518
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_LOCALCONFDIR_PKG, tmp);
519
0
  }
520
521
  /* snap usual case */
522
0
  tmp = g_getenv("SNAP");
523
0
  if (tmp != NULL) {
524
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_DATADIR_PKG, tmp);
525
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_DATADIR_QUIRKS, tmp);
526
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_DATADIR_VENDOR_IDS, tmp);
527
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_EFIAPPDIR, tmp);
528
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_LIBDIR_PKG, tmp);
529
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_LIBEXECDIR_PKG, tmp);
530
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_LIBEXECDIR, tmp);
531
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_SYSCONFDIR_PKG, tmp);
532
0
    fu_path_store_add_prefix(self, FU_PATH_KIND_SYSCONFDIR, tmp);
533
0
  }
534
535
  /* program executable paths */
536
0
  tmp = g_getenv("PATH");
537
0
  if (tmp != NULL) {
538
0
    g_auto(GStrv) path_envs = g_strsplit(tmp, G_SEARCHPATH_SEPARATOR_S, -1);
539
0
    for (guint i = 0; path_envs[i] != NULL; i++)
540
0
      fu_path_store_add_program_path(self, path_envs[i]);
541
0
  }
542
543
  /* success */
544
0
  self->loaded_from_env = TRUE;
545
0
}
546
547
static void
548
fu_path_store_finalize(GObject *object)
549
0
{
550
0
  FuPathStore *self = FU_PATH_STORE(object);
551
0
  g_ptr_array_unref(self->program_paths);
552
0
  for (guint i = 0; i < FU_PATH_KIND_LAST; i++)
553
0
    g_free(self->paths[i]);
554
0
  G_OBJECT_CLASS(fu_path_store_parent_class)->finalize(object);
555
0
}
556
557
static void
558
fu_path_store_class_init(FuPathStoreClass *klass)
559
0
{
560
0
  GObjectClass *object_class = G_OBJECT_CLASS(klass);
561
0
  object_class->finalize = fu_path_store_finalize;
562
0
}
563
564
static void
565
fu_path_store_init(FuPathStore *self)
566
0
{
567
0
  self->program_paths = g_ptr_array_new_with_free_func(g_free);
568
0
}
569
570
/**
571
 * fu_path_store_new:
572
 *
573
 * Returns: (transfer full): a #FuPathStore
574
 *
575
 * Since: 2.1.1
576
 **/
577
FuPathStore *
578
fu_path_store_new(void)
579
0
{
580
0
  return g_object_new(FU_TYPE_PATH_STORE, NULL);
581
0
}