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