/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 | } |