1 /*
2  * libosinfo: An installed image of a (guest) OS
3  *
4  * Copyright (C) 2018-2020 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
21 #include <osinfo/osinfo.h>
22 #include <gio/gio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <glib/gi18n-lib.h>
26 
27 /**
28  * SECTION:osinfo_image
29  * @short_description: A pre-installed image for a (guest) OS
30  * @see_also: #OsinfoOs
31  *
32  * #OsinfoImage is an entity representing an installation image
33  * a (guest) operating system.
34  */
35 
36 struct _OsinfoImagePrivate
37 {
38     GWeakRef os;
39 };
40 
41 G_DEFINE_TYPE_WITH_PRIVATE(OsinfoImage, osinfo_image, OSINFO_TYPE_ENTITY);
42 
43 enum {
44     PROP_0,
45 
46     PROP_ARCHITECTURE,
47     PROP_FORMAT,
48     PROP_URL,
49     PROP_CLOUD_INIT,
50 
51     LAST_PROP
52 };
53 static GParamSpec *properties[LAST_PROP];
54 
55 static void
osinfo_image_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)56 osinfo_image_get_property(GObject *object,
57                          guint property_id,
58                          GValue *value,
59                          GParamSpec *pspec)
60 {
61     OsinfoImage *image = OSINFO_IMAGE(object);
62 
63     switch (property_id) {
64     case PROP_ARCHITECTURE:
65         g_value_set_string(value, osinfo_image_get_architecture(image));
66         break;
67 
68     case PROP_FORMAT:
69         g_value_set_string(value, osinfo_image_get_format(image));
70         break;
71 
72     case PROP_URL:
73         g_value_set_string(value, osinfo_image_get_url(image));
74         break;
75 
76     case PROP_CLOUD_INIT:
77         g_value_set_boolean(value, osinfo_image_get_cloud_init(image));
78         break;
79 
80     default:
81         /* We don't have any other property... */
82         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
83         break;
84     }
85 }
86 
87 static void
osinfo_image_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)88 osinfo_image_set_property(GObject      *object,
89                          guint         property_id,
90                          const GValue *value,
91                          GParamSpec   *pspec)
92 {
93     OsinfoImage *image = OSINFO_IMAGE(object);
94 
95     switch (property_id) {
96     case PROP_ARCHITECTURE:
97         osinfo_entity_set_param(OSINFO_ENTITY(image),
98                                 OSINFO_IMAGE_PROP_ARCHITECTURE,
99                                 g_value_get_string(value));
100         break;
101 
102     case PROP_FORMAT:
103         osinfo_entity_set_param(OSINFO_ENTITY(image),
104                                 OSINFO_IMAGE_PROP_FORMAT,
105                                 g_value_get_string(value));
106         break;
107 
108     case PROP_URL:
109         osinfo_entity_set_param(OSINFO_ENTITY(image),
110                                 OSINFO_IMAGE_PROP_URL,
111                                 g_value_get_string(value));
112         break;
113 
114     case PROP_CLOUD_INIT:
115         osinfo_entity_set_param_boolean(OSINFO_ENTITY(image),
116                                         OSINFO_IMAGE_PROP_CLOUD_INIT,
117                                         g_value_get_boolean(value));
118         break;
119 
120     default:
121         /* We don't have any other property... */
122         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
123         break;
124     }
125 }
126 
osinfo_image_dispose(GObject * obj)127 static void osinfo_image_dispose(GObject *obj)
128 {
129     OsinfoImage *image = OSINFO_IMAGE(obj);
130 
131     g_weak_ref_clear(&image->priv->os);
132 
133     G_OBJECT_CLASS(osinfo_image_parent_class)->dispose(obj);
134 }
135 
136 static void
osinfo_image_finalize(GObject * object)137 osinfo_image_finalize(GObject *object)
138 {
139     /* Chain up to the parent class */
140     G_OBJECT_CLASS(osinfo_image_parent_class)->finalize(object);
141 }
142 
143 /* Init functions */
144 static void
osinfo_image_class_init(OsinfoImageClass * klass)145 osinfo_image_class_init(OsinfoImageClass *klass)
146 {
147     GObjectClass *g_klass = G_OBJECT_CLASS(klass);
148 
149     g_klass->dispose = osinfo_image_dispose;
150     g_klass->finalize = osinfo_image_finalize;
151     g_klass->get_property = osinfo_image_get_property;
152     g_klass->set_property = osinfo_image_set_property;
153 
154     /**
155      * OsinfoImage:architecture:
156      *
157      * The target hardware architecture of this image.
158      */
159     properties[PROP_ARCHITECTURE] = g_param_spec_string("architecture",
160                                                         "ARCHITECTURE",
161                                                         _("CPU Architecture"),
162                                                         NULL /* default value */,
163                                                         G_PARAM_READWRITE |
164                                                         G_PARAM_STATIC_STRINGS);
165 
166     /**
167      * OsinfoImage:format:
168      *
169      * The image format.
170      */
171     properties[PROP_FORMAT] = g_param_spec_string("format",
172                                                   "FORMAT",
173                                                   _("The image format"),
174                                                   NULL /* default value */,
175                                                   G_PARAM_READWRITE |
176                                                   G_PARAM_STATIC_STRINGS);
177 
178     /**
179      * OsinfoImage:url:
180      *
181      * The URL to this image.
182      */
183     properties[PROP_URL] = g_param_spec_string("url",
184                                                "URL",
185                                                _("The URL to this image"),
186                                                NULL /* default value */,
187                                                G_PARAM_READWRITE |
188                                                G_PARAM_STATIC_STRINGS);
189 
190     /**
191      * OsinfoImage:cloud-init:
192      *
193      * Whether the image supports cloud-init customizations or not.
194      */
195     properties[PROP_CLOUD_INIT] = g_param_spec_string("cloud-init",
196                                                       "CloudInit",
197                                                       _("Whether cloud-init customizations are supported or not"),
198                                                       FALSE /* default value */,
199                                                       G_PARAM_READWRITE |
200                                                       G_PARAM_STATIC_STRINGS);
201 
202     g_object_class_install_properties(g_klass, LAST_PROP, properties);
203 }
204 
205 static void
osinfo_image_init(OsinfoImage * image)206 osinfo_image_init(OsinfoImage *image)
207 {
208     image->priv = osinfo_image_get_instance_private(image);
209 
210     g_weak_ref_init(&image->priv->os, NULL);
211 }
212 
osinfo_image_new(const gchar * id,const gchar * architecture,const gchar * format)213 OsinfoImage *osinfo_image_new(const gchar *id,
214                               const gchar *architecture,
215                               const gchar *format)
216 {
217     OsinfoImage *image;
218 
219     image = g_object_new(OSINFO_TYPE_IMAGE,
220                         "id", id,
221                         OSINFO_IMAGE_PROP_ARCHITECTURE, architecture,
222                         OSINFO_IMAGE_PROP_FORMAT, format,
223                         NULL);
224 
225     return image;
226 }
227 
228 /**
229  * osinfo_image_get_architecture:
230  * @image: an #OsinfoImage instance
231  *
232  * Retrieves the target hardware architecture of the OS @image provides.
233  *
234  * Returns: (transfer none): the hardware architecture, or NULL
235  *
236  * Since: 1.3.0
237  */
osinfo_image_get_architecture(OsinfoImage * image)238 const gchar *osinfo_image_get_architecture(OsinfoImage *image)
239 {
240     return osinfo_entity_get_param_value(OSINFO_ENTITY(image),
241                                          OSINFO_IMAGE_PROP_ARCHITECTURE);
242 }
243 
244 /**
245  * osinfo_image_get_format:
246  * @image: an #OsinfoImage instance
247  *
248  * The format of the @image
249  *
250  * Returns: (transfer none): the format, or NULL
251  *
252  * Since: 1.3.0
253  */
osinfo_image_get_format(OsinfoImage * image)254 const gchar *osinfo_image_get_format(OsinfoImage *image)
255 {
256     return osinfo_entity_get_param_value(OSINFO_ENTITY(image),
257                                          OSINFO_IMAGE_PROP_FORMAT);
258 }
259 
260 /**
261  * osinfo_image_get_url:
262  * @image: an #OsinfoImage instance
263  *
264  * The URL to the @image
265  *
266  * Returns: (transfer none): the URL, or NULL
267  *
268  * Since: 1.3.0
269  */
osinfo_image_get_url(OsinfoImage * image)270 const gchar *osinfo_image_get_url(OsinfoImage *image)
271 {
272     return osinfo_entity_get_param_value(OSINFO_ENTITY(image),
273                                          OSINFO_IMAGE_PROP_URL);
274 }
275 
276 /**
277  * osinfo_image_get_cloud_init:
278  * @image: an #OsinfoImage instance
279  *
280  * Whether @image supports cloud init customizations
281  *
282  * Returns: #TRUE if @image supports cloud init customizations, #FALSE
283  * otherwise.
284  *
285  * Since: 1.3.0
286  */
osinfo_image_get_cloud_init(OsinfoImage * image)287 gboolean osinfo_image_get_cloud_init(OsinfoImage *image)
288 {
289     return osinfo_entity_get_param_value_boolean_with_default
290             (OSINFO_ENTITY(image), OSINFO_IMAGE_PROP_CLOUD_INIT, FALSE);
291 }
292 
293 /**
294  * osinfo_image_get_os:
295  * @image: an #OsinfoImage instance
296  *
297  * Returns: (transfer full): the operating system, or NULL
298  *
299  * Since: 1.5.0
300  */
osinfo_image_get_os(OsinfoImage * image)301 OsinfoOs *osinfo_image_get_os(OsinfoImage *image)
302 {
303     g_return_val_if_fail(OSINFO_IS_IMAGE(image), NULL);
304 
305     return g_weak_ref_get(&image->priv->os);
306 }
307 
308 /**
309  * osinfo_image_set_os
310  * @image: an #OsinfoImage instance
311  * @os: an #OsinfoOs instance
312  *
313  * Sets the #OsinfoOs associated to the #OsinfoImage instance.
314  *
315  * Since: 1.5.0
316  */
osinfo_image_set_os(OsinfoImage * image,OsinfoOs * os)317 void osinfo_image_set_os(OsinfoImage *image, OsinfoOs *os)
318 {
319     g_return_if_fail(OSINFO_IS_IMAGE(image));
320 
321     g_object_ref(os);
322     g_weak_ref_set(&image->priv->os, os);
323     g_object_unref(os);
324 }
325 
326 /**
327  * osinfo_image_get_os_variants:
328  * @image: an #OsinfoImage instance
329  *
330  * Gets the varriants of the associated operating system
331  *
332  * Returns: (transfer full): the operating system variants, or NULL
333  *
334  * Since: 1.5.0
335  */
osinfo_image_get_os_variants(OsinfoImage * image)336 OsinfoOsVariantList *osinfo_image_get_os_variants(OsinfoImage *image)
337 {
338     OsinfoOs *os;
339     OsinfoOsVariantList *os_variants;
340     OsinfoOsVariantList *image_variants;
341     GList *ids, *node;
342     OsinfoFilter *filter;
343 
344     g_return_val_if_fail(OSINFO_IS_IMAGE(image), NULL);
345 
346     os = osinfo_image_get_os(image);
347     if (os == NULL)
348         return NULL;
349 
350     os_variants = osinfo_os_get_variant_list(os);
351     g_object_unref(os);
352 
353     ids = osinfo_entity_get_param_value_list(OSINFO_ENTITY(image),
354                                              OSINFO_IMAGE_PROP_VARIANT);
355     filter = osinfo_filter_new();
356     image_variants = osinfo_os_variantlist_new();
357     for (node = ids; node != NULL; node = node->next) {
358         osinfo_filter_clear_constraints(filter);
359         osinfo_filter_add_constraint(filter,
360                                      OSINFO_ENTITY_PROP_ID,
361                                      (const char *) node->data);
362         osinfo_list_add_filtered(OSINFO_LIST(image_variants),
363                                  OSINFO_LIST(os_variants),
364                                  filter);
365     }
366     g_object_unref(os_variants);
367 
368     return image_variants;
369 }
370