Coverage Report

Created: 2026-05-30 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-kernel-search-path.c
Line
Count
Source
1
/*
2
 * Copyright 2017 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
0
#define G_LOG_DOMAIN "FuKernel"
8
9
#include "config.h"
10
11
#include "fu-kernel-search-path-private.h"
12
13
/**
14
 * FuKernelSearchPathLocker:
15
 *
16
 * Easily reset the firmware search path.
17
 */
18
19
struct _FuKernelSearchPathLocker {
20
  GObject parent_instance;
21
  FuPathStore *pstore;
22
  gchar *path;
23
  gchar *old_path;
24
};
25
26
0
G_DEFINE_TYPE(FuKernelSearchPathLocker, fu_kernel_search_path_locker, G_TYPE_OBJECT)
27
0
28
0
/**
29
0
 * fu_kernel_search_path_locker_get_path:
30
0
 * @self: a #FuDfuFirmware
31
0
 *
32
0
 * Gets the kernel search path set using this locker.
33
0
 *
34
0
 * Returns: the path set with fu_kernel_search_path_locker_new()
35
0
 *
36
0
 * Since: 2.0.7
37
0
 **/
38
0
const gchar *
39
0
fu_kernel_search_path_locker_get_path(FuKernelSearchPathLocker *self)
40
0
{
41
0
  g_return_val_if_fail(FU_IS_KERNEL_SEARCH_PATH_LOCKER(self), NULL);
42
0
  return self->path;
43
0
}
44
45
/* private */
46
gchar *
47
fu_kernel_search_path_get_current(FuPathStore *pstore, GError **error)
48
0
{
49
0
  const gchar *sys_fw_search_path = NULL;
50
0
  gsize sz = 0;
51
0
  g_autofree gchar *contents = NULL;
52
53
0
  sys_fw_search_path = fu_path_store_get_path(pstore, FU_PATH_KIND_FIRMWARE_SEARCH, error);
54
0
  if (sys_fw_search_path == NULL)
55
0
    return NULL;
56
0
  if (!g_file_get_contents(sys_fw_search_path, &contents, &sz, error))
57
0
    return NULL;
58
59
  /* sanity check */
60
0
  if (contents == NULL || sz == 0) {
61
0
    g_set_error(error,
62
0
          FWUPD_ERROR,
63
0
          FWUPD_ERROR_INTERNAL,
64
0
          "failed to get firmware search path from %s",
65
0
          sys_fw_search_path);
66
0
    return NULL;
67
0
  }
68
69
  /* remove newline character */
70
0
  if (contents[sz - 1] == '\n')
71
0
    contents[sz - 1] = 0;
72
73
0
  g_debug("read firmware search path (%" G_GSIZE_FORMAT "): %s", sz, contents);
74
0
  return g_steal_pointer(&contents);
75
0
}
76
77
static gboolean
78
fu_kernel_search_path_set_current(FuKernelSearchPathLocker *self, const gchar *path, GError **error)
79
0
{
80
0
  const gchar *sys_fw_search_path_prm = NULL;
81
82
0
  g_return_val_if_fail(path != NULL, FALSE);
83
0
  g_return_val_if_fail(strlen(path) < PATH_MAX, FALSE);
84
85
0
  g_debug("writing firmware search path (%" G_GSIZE_FORMAT "): %s", strlen(path), path);
86
0
  sys_fw_search_path_prm =
87
0
      fu_path_store_get_path(self->pstore, FU_PATH_KIND_FIRMWARE_SEARCH, error);
88
0
  if (sys_fw_search_path_prm == NULL)
89
0
    return FALSE;
90
0
  return g_file_set_contents_full(sys_fw_search_path_prm,
91
0
          path,
92
0
          strlen(path),
93
0
          G_FILE_SET_CONTENTS_NONE,
94
0
          0644,
95
0
          error);
96
0
}
97
98
static gboolean
99
fu_kernel_search_path_locker_close(FuKernelSearchPathLocker *self, GError **error)
100
0
{
101
0
  if (self->old_path == NULL)
102
0
    return TRUE;
103
0
  if (!fu_kernel_search_path_set_current(self, self->old_path, error))
104
0
    return FALSE;
105
0
  g_clear_pointer(&self->old_path, g_free);
106
0
  return TRUE;
107
0
}
108
109
/**
110
 * fu_kernel_search_path_locker_new:
111
 * @pstore: a #FuPathStore
112
 * @path: the new devivce path
113
 * @error: (nullable): optional return location for an error
114
 *
115
 * Sets the kernel firmware search path. When the #FuKernelSearchPathLocker is deallocated path
116
 * is restored to the previous value.
117
 *
118
 * This object is typically called using g_autoptr() but the device can also be
119
 * manually closed using g_clear_object().
120
 *
121
 * Returns: (transfer full): a #FuKernelSearchPathLocker, or %NULL on error
122
 *
123
 * Since: 2.0.6
124
 **/
125
FuKernelSearchPathLocker *
126
fu_kernel_search_path_locker_new(FuPathStore *pstore, const gchar *path, GError **error)
127
0
{
128
0
  g_autofree gchar *old_path = NULL;
129
0
  g_autoptr(FuKernelSearchPathLocker) self = NULL;
130
131
0
  g_return_val_if_fail(FU_IS_PATH_STORE(pstore), NULL);
132
0
  g_return_val_if_fail(path != NULL, NULL);
133
0
  g_return_val_if_fail(error == NULL || *error == NULL, NULL);
134
135
  /* create object */
136
0
  self = g_object_new(FU_TYPE_KERNEL_SEARCH_PATH_LOCKER, NULL);
137
0
  self->path = g_strdup(path);
138
0
  self->pstore = g_object_ref(pstore);
139
0
  old_path = fu_kernel_search_path_get_current(pstore, error);
140
0
  if (old_path == NULL)
141
0
    return NULL;
142
143
  /* set the new path if different */
144
0
  if (g_strcmp0(self->old_path, path) != 0) {
145
0
    self->old_path = g_steal_pointer(&old_path);
146
0
    if (!fu_kernel_search_path_set_current(self, path, error))
147
0
      return NULL;
148
0
  }
149
150
  /* success */
151
0
  return g_steal_pointer(&self);
152
0
}
153
154
static void
155
fu_kernel_search_path_locker_dispose(GObject *obj)
156
0
{
157
0
  FuKernelSearchPathLocker *self = FU_KERNEL_SEARCH_PATH_LOCKER(obj);
158
0
  if (self->old_path != NULL) {
159
0
    g_autoptr(GError) error = NULL;
160
0
    if (!fu_kernel_search_path_locker_close(self, &error))
161
0
      g_warning("failed to restore path: %s", error->message);
162
0
  }
163
0
  G_OBJECT_CLASS(fu_kernel_search_path_locker_parent_class)->dispose(obj);
164
0
}
165
166
static void
167
fu_kernel_search_path_locker_finalize(GObject *obj)
168
0
{
169
0
  FuKernelSearchPathLocker *self = FU_KERNEL_SEARCH_PATH_LOCKER(obj);
170
0
  g_free(self->path);
171
0
  g_free(self->old_path);
172
0
  g_object_unref(self->pstore);
173
0
  G_OBJECT_CLASS(fu_kernel_search_path_locker_parent_class)->finalize(obj);
174
0
}
175
176
static void
177
fu_kernel_search_path_locker_class_init(FuKernelSearchPathLockerClass *klass)
178
0
{
179
0
  GObjectClass *object_class = G_OBJECT_CLASS(klass);
180
0
  object_class->dispose = fu_kernel_search_path_locker_dispose;
181
0
  object_class->finalize = fu_kernel_search_path_locker_finalize;
182
0
}
183
184
static void
185
fu_kernel_search_path_locker_init(FuKernelSearchPathLocker *self)
186
0
{
187
0
}