1 /* ide-triplet.c
2 *
3 * Copyright 2018 Corentin Noël <corentin.noel@collabora.com>
4 * Copyright 2018 Collabora Ltd.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * SPDX-License-Identifier: GPL-3.0-or-later
20 */
21
22 #define G_LOG_DOMAIN "ide-triplet"
23
24 #include "config.h"
25
26 #include "ide-triplet.h"
27
28 G_DEFINE_BOXED_TYPE (IdeTriplet, ide_triplet, ide_triplet_ref, ide_triplet_unref)
29
30 struct _IdeTriplet
31 {
32 volatile gint ref_count;
33
34 gchar *full_name;
35 gchar *arch;
36 gchar *vendor;
37 gchar *kernel;
38 gchar *operating_system;
39 };
40
41 static IdeTriplet *
_ide_triplet_construct(void)42 _ide_triplet_construct (void)
43 {
44 IdeTriplet *self;
45
46 self = g_slice_new0 (IdeTriplet);
47 self->ref_count = 1;
48 self->full_name = NULL;
49 self->arch = NULL;
50 self->vendor = NULL;
51 self->kernel = NULL;
52 self->operating_system = NULL;
53
54 return self;
55 }
56
57 /**
58 * ide_triplet_new:
59 * @full_name: The complete identifier of the machine
60 *
61 * Creates a new #IdeTriplet from a given identifier. This identifier
62 * can be a simple architecture name, a duet of "arch-kernel" (like "m68k-coff"), a triplet
63 * of "arch-kernel-os" (like "x86_64-linux-gnu") or a quadriplet of "arch-vendor-kernel-os"
64 * (like "i686-pc-linux-gnu")
65 *
66 * Returns: (transfer full): An #IdeTriplet.
67 *
68 * Since: 3.32
69 */
70 IdeTriplet *
ide_triplet_new(const gchar * full_name)71 ide_triplet_new (const gchar *full_name)
72 {
73 IdeTriplet *self;
74 g_auto (GStrv) parts = NULL;
75 guint parts_length = 0;
76
77 g_return_val_if_fail (full_name != NULL, NULL);
78
79 self = _ide_triplet_construct ();
80 self->full_name = g_strdup (full_name);
81
82 parts = g_strsplit (full_name, "-", 4);
83 parts_length = g_strv_length (parts);
84 /* Currently they can't have more than 4 parts */
85 if (parts_length >= 4)
86 {
87 self->arch = g_strdup (parts[0]);
88 self->vendor = g_strdup (parts[1]);
89 self->kernel = g_strdup (parts[2]);
90 self->operating_system = g_strdup (parts[3]);
91 }
92 else if (parts_length == 3)
93 {
94 self->arch = g_strdup (parts[0]);
95 self->kernel = g_strdup (parts[1]);
96 self->operating_system = g_strdup (parts[2]);
97 }
98 else if (parts_length == 2)
99 {
100 self->arch = g_strdup (parts[0]);
101 self->kernel = g_strdup (parts[1]);
102 }
103 else if (parts_length == 1)
104 self->arch = g_strdup (parts[0]);
105
106 return self;
107 }
108
109 /**
110 * ide_triplet_new_from_system:
111 *
112 * Creates a new #IdeTriplet from a the current system information
113 *
114 * Returns: (transfer full): An #IdeTriplet.
115 *
116 * Since: 3.32
117 */
118 IdeTriplet *
ide_triplet_new_from_system(void)119 ide_triplet_new_from_system (void)
120 {
121 static IdeTriplet *system_triplet;
122
123 if (g_once_init_enter (&system_triplet))
124 g_once_init_leave (&system_triplet, ide_triplet_new (ide_get_system_type ()));
125
126 return ide_triplet_ref (system_triplet);
127 }
128
129 /**
130 * ide_triplet_new_with_triplet:
131 * @arch: The name of the architecture of the machine (like "x86_64")
132 * @kernel: (nullable): The name of the kernel of the machine (like "linux")
133 * @operating_system: (nullable): The name of the os of the machine
134 * (like "gnuabi64")
135 *
136 * Creates a new #IdeTriplet from a given triplet of "arch-kernel-os"
137 * (like "x86_64-linux-gnu")
138 *
139 * Returns: (transfer full): An #IdeTriplet.
140 *
141 * Since: 3.32
142 */
143 IdeTriplet *
ide_triplet_new_with_triplet(const gchar * arch,const gchar * kernel,const gchar * operating_system)144 ide_triplet_new_with_triplet (const gchar *arch,
145 const gchar *kernel,
146 const gchar *operating_system)
147 {
148 IdeTriplet *self;
149 g_autofree gchar *full_name = NULL;
150
151 g_return_val_if_fail (arch != NULL, NULL);
152
153 self = _ide_triplet_construct ();
154 self->arch = g_strdup (arch);
155 self->kernel = g_strdup (kernel);
156 self->operating_system = g_strdup (operating_system);
157
158 full_name = g_strdup (arch);
159 if (kernel != NULL)
160 {
161 g_autofree gchar *start_full_name = full_name;
162 full_name = g_strdup_printf ("%s-%s", start_full_name, kernel);
163 }
164
165 if (operating_system != NULL)
166 {
167 g_autofree gchar *start_full_name = full_name;
168 full_name = g_strdup_printf ("%s-%s", start_full_name, operating_system);
169 }
170
171 self->full_name = g_steal_pointer (&full_name);
172
173 return self;
174 }
175
176 /**
177 * ide_triplet_new_with_quadruplet:
178 * @arch: The name of the architecture of the machine (like "x86_64")
179 * @vendor: (nullable): The name of the vendor of the machine (like "pc")
180 * @kernel: (nullable): The name of the kernel of the machine (like "linux")
181 * @operating_system: (nullable): The name of the os of the machine (like "gnuabi64")
182 *
183 * Creates a new #IdeTriplet from a given quadruplet of
184 * "arch-vendor-kernel-os" (like "i686-pc-linux-gnu")
185 *
186 * Returns: (transfer full): An #IdeTriplet.
187 *
188 * Since: 3.32
189 */
190 IdeTriplet *
ide_triplet_new_with_quadruplet(const gchar * arch,const gchar * vendor,const gchar * kernel,const gchar * operating_system)191 ide_triplet_new_with_quadruplet (const gchar *arch,
192 const gchar *vendor,
193 const gchar *kernel,
194 const gchar *operating_system)
195 {
196 IdeTriplet *self;
197 g_autofree gchar *full_name = NULL;
198
199 g_return_val_if_fail (arch != NULL, NULL);
200
201 if (vendor == NULL)
202 return ide_triplet_new_with_triplet (arch, kernel, operating_system);
203
204 self = _ide_triplet_construct ();
205 self->arch = g_strdup (arch);
206 self->vendor = g_strdup (vendor);
207 self->kernel = g_strdup (kernel);
208 self->operating_system = g_strdup (operating_system);
209
210 full_name = g_strdup_printf ("%s-%s", arch, vendor);
211 if (kernel != NULL)
212 {
213 g_autofree gchar *start_full_name = full_name;
214 full_name = g_strdup_printf ("%s-%s", start_full_name, kernel);
215 }
216
217 if (operating_system != NULL)
218 {
219 g_autofree gchar *start_full_name = full_name;
220 full_name = g_strdup_printf ("%s-%s", start_full_name, operating_system);
221 }
222
223 self->full_name = g_steal_pointer (&full_name);
224
225 return self;
226 }
227
228 static void
ide_triplet_finalize(IdeTriplet * self)229 ide_triplet_finalize (IdeTriplet *self)
230 {
231 g_free (self->full_name);
232 g_free (self->arch);
233 g_free (self->vendor);
234 g_free (self->kernel);
235 g_free (self->operating_system);
236 g_slice_free (IdeTriplet, self);
237 }
238
239 /**
240 * ide_triplet_ref:
241 * @self: An #IdeTriplet
242 *
243 * Increases the reference count of @self
244 *
245 * Returns: (transfer none): An #IdeTriplet.
246 *
247 * Since: 3.32
248 */
249 IdeTriplet *
ide_triplet_ref(IdeTriplet * self)250 ide_triplet_ref (IdeTriplet *self)
251 {
252 g_return_val_if_fail (self, NULL);
253 g_return_val_if_fail (self->ref_count > 0, NULL);
254
255 g_atomic_int_inc (&self->ref_count);
256
257 return self;
258 }
259
260 /**
261 * ide_triplet_unref:
262 * @self: An #IdeTriplet
263 *
264 * Decreases the reference count of @self
265 * Once the reference count reaches 0, the object is freed.
266 *
267 * Since: 3.32
268 */
269 void
ide_triplet_unref(IdeTriplet * self)270 ide_triplet_unref (IdeTriplet *self)
271 {
272 g_return_if_fail (self);
273 g_return_if_fail (self->ref_count > 0);
274
275 if (g_atomic_int_dec_and_test (&self->ref_count))
276 ide_triplet_finalize (self);
277 }
278
279 /**
280 * ide_triplet_get_full_name:
281 * @self: An #IdeTriplet
282 *
283 * Gets the full name of the machine configuration name (can be an architecture name,
284 * a duet, a triplet or a quadruplet).
285 *
286 * Returns: (transfer none): The full name of the machine configuration name
287 *
288 * Since: 3.32
289 */
290 const gchar *
ide_triplet_get_full_name(IdeTriplet * self)291 ide_triplet_get_full_name (IdeTriplet *self)
292 {
293 g_return_val_if_fail (self, NULL);
294
295 return self->full_name;
296 }
297
298 /**
299 * ide_triplet_get_arch:
300 * @self: An #IdeTriplet
301 *
302 * Gets the architecture name of the machine
303 *
304 * Returns: (transfer none): The architecture name of the machine
305 *
306 * Since: 3.32
307 */
308 const gchar *
ide_triplet_get_arch(IdeTriplet * self)309 ide_triplet_get_arch (IdeTriplet *self)
310 {
311 g_return_val_if_fail (self, NULL);
312
313 return self->arch;
314 }
315
316 /**
317 * ide_triplet_get_vendor:
318 * @self: An #IdeTriplet
319 *
320 * Gets the vendor name of the machine
321 *
322 * Returns: (transfer none) (nullable): The vendor name of the machine
323 *
324 * Since: 3.32
325 */
326 const gchar *
ide_triplet_get_vendor(IdeTriplet * self)327 ide_triplet_get_vendor (IdeTriplet *self)
328 {
329 g_return_val_if_fail (self, NULL);
330
331 return self->vendor;
332 }
333
334 /**
335 * ide_triplet_get_kernel:
336 * @self: An #IdeTriplet
337 *
338 * Gets name of the kernel of the machine
339 *
340 * Returns: (transfer none) (nullable): The name of the kernel of the machine
341 *
342 * Since: 3.32
343 */
344 const gchar *
ide_triplet_get_kernel(IdeTriplet * self)345 ide_triplet_get_kernel (IdeTriplet *self)
346 {
347 g_return_val_if_fail (self, NULL);
348
349 return self->kernel;
350 }
351
352 /**
353 * ide_triplet_get_operating_system:
354 * @self: An #IdeTriplet
355 *
356 * Gets name of the operating system of the machine
357 *
358 * Returns: (transfer none) (nullable): The name of the operating system of the machine
359 *
360 * Since: 3.32
361 */
362 const gchar *
ide_triplet_get_operating_system(IdeTriplet * self)363 ide_triplet_get_operating_system (IdeTriplet *self)
364 {
365 g_return_val_if_fail (self, NULL);
366
367 return self->operating_system;
368 }
369
370
371 /**
372 * ide_triplet_is_system:
373 * @self: An #IdeTriplet
374 *
375 * Gets whether this is the same architecture as the system
376 *
377 * Returns: %TRUE if this is the same architecture as the system, %FALSE otherwise
378 *
379 * Since: 3.32
380 */
381 gboolean
ide_triplet_is_system(IdeTriplet * self)382 ide_triplet_is_system (IdeTriplet *self)
383 {
384 g_autofree gchar *system_arch = ide_get_system_arch ();
385
386 g_return_val_if_fail (self, FALSE);
387
388 return g_strcmp0 (self->arch, system_arch) == 0;
389 }
390