Coverage Report

Created: 2025-07-01 07:09

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