1 /*
2  * libosinfo:
3  *
4  * Copyright (C) 2009-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 "osinfo/osinfo_product_private.h"
23 #include <glib/gi18n-lib.h>
24 
25 /**
26  * SECTION:osinfo_platform
27  * @short_description: An virtualization platform
28  * @see_also: #OsinfoOs, #OsinfoPlatform
29  *
30  * #OsinfoPlatform is an entity representing an virtualization
31  * platform. Platforms have a list of supported devices
32  */
33 
34 struct _OsinfoPlatformPrivate
35 {
36     // Value: List of device_link structs
37     GList *deviceLinks;
38 };
39 
40 G_DEFINE_TYPE_WITH_PRIVATE(OsinfoPlatform, osinfo_platform, OSINFO_TYPE_PRODUCT);
41 
42 struct _OsinfoPlatformDeviceLink {
43     OsinfoDevice *dev;
44     gchar *driver;
45 };
46 
47 static void
osinfo_platform_finalize(GObject * object)48 osinfo_platform_finalize(GObject *object)
49 {
50     OsinfoPlatform *platform = OSINFO_PLATFORM(object);
51 
52     g_list_free_full(platform->priv->deviceLinks, g_object_unref);
53 
54     /* Chain up to the parent class */
55     G_OBJECT_CLASS(osinfo_platform_parent_class)->finalize(object);
56 }
57 
58 /* Init functions */
59 static void
osinfo_platform_class_init(OsinfoPlatformClass * klass)60 osinfo_platform_class_init(OsinfoPlatformClass *klass)
61 {
62     GObjectClass *g_klass = G_OBJECT_CLASS(klass);
63 
64     g_klass->finalize = osinfo_platform_finalize;
65 }
66 
67 static void
osinfo_platform_init(OsinfoPlatform * platform)68 osinfo_platform_init(OsinfoPlatform *platform)
69 {
70     platform->priv = osinfo_platform_get_instance_private(platform);
71     platform->priv->deviceLinks = NULL;
72 }
73 
74 
75 /**
76  * osinfo_platform_new:
77  * @id: a unique identifier
78  *
79  * Create a new platform entity
80  *
81  * Returns: (transfer full): A platform entity
82  */
osinfo_platform_new(const gchar * id)83 OsinfoPlatform *osinfo_platform_new(const gchar *id)
84 {
85     return g_object_new(OSINFO_TYPE_PLATFORM,
86                         "id", id,
87                         NULL);
88 }
89 
90 struct GetAllDevicesData {
91     OsinfoFilter *filter;
92     OsinfoDeviceList *devices;
93 };
94 
get_all_devices_cb(OsinfoProduct * product,gpointer user_data)95 static void get_all_devices_cb(OsinfoProduct *product, gpointer user_data)
96 {
97     OsinfoDeviceList *devices;
98     OsinfoList *tmp_list;
99     struct GetAllDevicesData *foreach_data = (struct GetAllDevicesData *)user_data;
100 
101     g_return_if_fail(OSINFO_IS_PLATFORM(product));
102 
103     devices = osinfo_platform_get_devices(OSINFO_PLATFORM(product),
104                                           foreach_data->filter);
105     tmp_list = osinfo_list_new_union(OSINFO_LIST(foreach_data->devices),
106                                      OSINFO_LIST(devices));
107     g_object_unref(foreach_data->devices);
108     g_object_unref(devices);
109     foreach_data->devices = OSINFO_DEVICELIST(tmp_list);
110 }
111 
112 
113 /**
114  * osinfo_platform_get_all_devices:
115  * @platform: a platform
116  * @filter: (allow-none)(transfer none): an optional device property filter
117  *
118  * Get all platforms matching a given filter but unlike
119  * osinfo_platform_get_devices this function also retrieves devices from
120  * all derived and upgraded platforms.
121  *
122  * Returns: (transfer full): A list of devices
123  *
124  * Since: 0.2.7
125  */
osinfo_platform_get_all_devices(OsinfoPlatform * platform,OsinfoFilter * filter)126 OsinfoDeviceList *osinfo_platform_get_all_devices(OsinfoPlatform *platform,
127                                                   OsinfoFilter *filter)
128 {
129     struct GetAllDevicesData foreach_data = {
130         .filter = filter,
131         .devices = osinfo_devicelist_new()
132     };
133 
134     osinfo_product_foreach_related(OSINFO_PRODUCT(platform),
135                                    OSINFO_PRODUCT_FOREACH_FLAG_UPGRADES |
136                                    OSINFO_PRODUCT_FOREACH_FLAG_DERIVES_FROM,
137                                    get_all_devices_cb,
138                                    &foreach_data);
139 
140     return foreach_data.devices;
141 }
142 
143 /**
144  * osinfo_platform_get_devices:
145  * @platform: a platform entity
146  * @filter: (transfer none)(allow-none): an optional filter
147  *
148  * Retrieve all the associated devices matching the filter.
149  * The filter matches against the device, not the link.
150  *
151  * Returns: (transfer full): a list of #OsinfoDevice entities
152  */
osinfo_platform_get_devices(OsinfoPlatform * platform,OsinfoFilter * filter)153 OsinfoDeviceList *osinfo_platform_get_devices(OsinfoPlatform *platform, OsinfoFilter *filter)
154 {
155     OsinfoDeviceList *newList;
156     GList *tmp;
157 
158     g_return_val_if_fail(OSINFO_IS_PLATFORM(platform), NULL);
159     g_return_val_if_fail(!filter || OSINFO_IS_FILTER(filter), NULL);
160 
161     newList = osinfo_devicelist_new();
162     tmp = platform->priv->deviceLinks;
163 
164     while (tmp) {
165         OsinfoDeviceLink *devlink = OSINFO_DEVICELINK(tmp->data);
166         OsinfoDevice *dev = osinfo_devicelink_get_target(devlink);
167         if (!filter || osinfo_filter_matches(filter, OSINFO_ENTITY(dev)))
168             osinfo_list_add(OSINFO_LIST(newList), OSINFO_ENTITY(dev));
169 
170         tmp = tmp->next;
171     }
172 
173     return newList;
174 }
175 
176 
177 /**
178  * osinfo_platform_get_device_links:
179  * @platform: a platform entity
180  * @filter: (transfer none)(allow-none): an optional filter
181  *
182  * Retrieve all the associated devices matching the filter.
183  * The filter matches against the link, not the device.
184  *
185  * Returns: (transfer full): a list of #OsinfoDevice entities
186  */
osinfo_platform_get_device_links(OsinfoPlatform * platform,OsinfoFilter * filter)187 OsinfoDeviceLinkList *osinfo_platform_get_device_links(OsinfoPlatform *platform, OsinfoFilter *filter)
188 {
189     OsinfoDeviceLinkList *newList;
190     GList *tmp;
191 
192     g_return_val_if_fail(OSINFO_IS_PLATFORM(platform), NULL);
193     g_return_val_if_fail(!filter || OSINFO_IS_FILTER(filter), NULL);
194 
195     newList = osinfo_devicelinklist_new();
196     tmp = platform->priv->deviceLinks;
197 
198     while (tmp) {
199         OsinfoDeviceLink *devlink = OSINFO_DEVICELINK(tmp->data);
200 
201         if (!filter || osinfo_filter_matches(filter, OSINFO_ENTITY(devlink)))
202             osinfo_list_add(OSINFO_LIST(newList), OSINFO_ENTITY(devlink));
203 
204         tmp = tmp->next;
205     }
206 
207     return newList;
208 }
209 
210 
211 /**
212  * osinfo_platform_add_device:
213  * @platform: a platform entity
214  * @dev: (transfer none): the device to associate
215  *
216  * Associate a device with a platform. The returned #OsinfoDeviceLink
217  * can be used to record extra metadata against the link
218  *
219  * Returns: (transfer none): the device association
220  */
osinfo_platform_add_device(OsinfoPlatform * platform,OsinfoDevice * dev)221 OsinfoDeviceLink *osinfo_platform_add_device(OsinfoPlatform *platform, OsinfoDevice *dev)
222 {
223     OsinfoDeviceLink *devlink;
224 
225     g_return_val_if_fail(OSINFO_IS_PLATFORM(platform), NULL);
226     g_return_val_if_fail(OSINFO_IS_DEVICE(dev), NULL);
227 
228     devlink = osinfo_devicelink_new(dev);
229 
230     platform->priv->deviceLinks = g_list_prepend(platform->priv->deviceLinks,
231                                                  devlink);
232 
233     return devlink;
234 }
235