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 <string.h>
23 #include <libxml/tree.h>
24 #include <libxslt/transform.h>
25 #include <libxslt/xsltutils.h>
26 #include <libxslt/xsltInternals.h>
27 #include <glib/gi18n-lib.h>
28 #include "osinfo_install_script_private.h"
29 
30 /**
31  * SECTION:osinfo_install_script
32  * @short_description: OS install script generation
33  * @see_also: #OsinfoInstallConfig
34  *
35  * #OsinfoInstallScript is an object used to generate an
36  * automated installation script for an OS. The OS
37  * configuration data (language, keyboard, timezone, ...)
38  * comes from an #OsinfoInstallConfig object.
39  */
40 
41 struct _OsinfoInstallScriptPrivate
42 {
43     gchar *output_prefix;
44     gchar *output_filename;
45     OsinfoInstallConfigParamList *config_params;
46     OsinfoAvatarFormat *avatar;
47 };
48 
49 G_DEFINE_TYPE_WITH_PRIVATE(OsinfoInstallScript, osinfo_install_script, OSINFO_TYPE_ENTITY);
50 
51 enum {
52     PROP_0,
53 
54     PROP_TEMPLATE_URI,
55     PROP_TEMPLATE_DATA,
56     PROP_PROFILE,
57     PROP_PRODUCT_KEY_FORMAT,
58     PROP_PATH_FORMAT,
59     PROP_AVATAR_FORMAT,
60     PROP_PREFERRED_INJECTION_METHOD,
61     PROP_INSTALLATION_SOURCE,
62 
63     LAST_PROP
64 };
65 static GParamSpec *properties[LAST_PROP];
66 
67 typedef struct _OsinfoInstallScriptGenerateData OsinfoInstallScriptGenerateData;
68 typedef struct _OsinfoInstallScriptGenerateOutputData OsinfoInstallScriptGenerateOutputData;
69 typedef struct _OsinfoInstallScriptGenerateSyncData OsinfoInstallScriptGenerateSyncData;
70 
71 
72 static void
osinfo_install_script_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)73 osinfo_install_script_set_property(GObject    *object,
74                                    guint       property_id,
75                                    const GValue     *value,
76                                    GParamSpec *pspec)
77 {
78     OsinfoInstallScript *script = OSINFO_INSTALL_SCRIPT(object);
79     const gchar *data;
80 
81     switch (property_id) {
82     case PROP_TEMPLATE_URI:
83         data = g_value_get_string(value);
84         if (data)
85             osinfo_entity_set_param(OSINFO_ENTITY(script),
86                                     OSINFO_INSTALL_SCRIPT_PROP_TEMPLATE_URI,
87                                     data);
88         break;
89 
90     case PROP_TEMPLATE_DATA:
91         data = g_value_get_string(value);
92         if (data)
93             osinfo_entity_set_param(OSINFO_ENTITY(script),
94                                     OSINFO_INSTALL_SCRIPT_PROP_TEMPLATE_DATA,
95                                     data);
96         break;
97 
98     case PROP_PROFILE:
99         data = g_value_get_string(value);
100         if (data)
101             osinfo_entity_set_param(OSINFO_ENTITY(script),
102                                     OSINFO_INSTALL_SCRIPT_PROP_PROFILE,
103                                     data);
104         break;
105 
106     case PROP_PREFERRED_INJECTION_METHOD:
107         osinfo_install_script_set_preferred_injection_method(script,
108                                                              g_value_get_flags(value));
109         break;
110 
111     case PROP_INSTALLATION_SOURCE:
112         osinfo_install_script_set_installation_source(script,
113                                                       g_value_get_enum(value));
114         break;
115 
116     default:
117         /* We don't have any other property... */
118         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
119         break;
120     }
121 }
122 
123 static void
osinfo_install_script_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)124 osinfo_install_script_get_property(GObject    *object,
125                                    guint       property_id,
126                                    GValue     *value,
127                                    GParamSpec *pspec)
128 {
129     OsinfoInstallScript *script = OSINFO_INSTALL_SCRIPT(object);
130 
131     switch (property_id) {
132     case PROP_TEMPLATE_URI:
133         g_value_set_string(value,
134                            osinfo_install_script_get_template_uri(script));
135         break;
136 
137     case PROP_TEMPLATE_DATA:
138         g_value_set_string(value,
139                            osinfo_install_script_get_template_data(script));
140         break;
141 
142     case PROP_PROFILE:
143         g_value_set_string(value,
144                            osinfo_install_script_get_profile(script));
145         break;
146 
147     case PROP_PRODUCT_KEY_FORMAT:
148         g_value_set_string(value,
149                            osinfo_install_script_get_product_key_format(script));
150         break;
151 
152     case PROP_PATH_FORMAT:
153         g_value_set_enum(value,
154                          osinfo_install_script_get_path_format(script));
155         break;
156 
157     case PROP_AVATAR_FORMAT:
158         g_value_set_object(value,
159                            osinfo_install_script_get_avatar_format(script));
160         break;
161 
162     case PROP_PREFERRED_INJECTION_METHOD:
163         g_value_set_flags(value,
164                           osinfo_install_script_get_preferred_injection_method(script));
165         break;
166 
167     case PROP_INSTALLATION_SOURCE:
168         g_value_set_enum(value,
169                          osinfo_install_script_get_installation_source(script));
170         break;
171 
172     default:
173         /* We don't have any other property... */
174         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
175         break;
176     }
177 }
178 
179 
180 static void
osinfo_install_script_finalize(GObject * object)181 osinfo_install_script_finalize(GObject *object)
182 {
183     OsinfoInstallScript *script = OSINFO_INSTALL_SCRIPT(object);
184     g_free(script->priv->output_prefix);
185     g_free(script->priv->output_filename);
186 
187     if (script->priv->config_params)
188         g_object_unref(script->priv->config_params);
189 
190     if (script->priv->avatar)
191         g_object_unref(script->priv->avatar);
192 
193     /* Chain up to the parent class */
194     G_OBJECT_CLASS(osinfo_install_script_parent_class)->finalize(object);
195 }
196 
197 /* Init functions */
198 static void
osinfo_install_script_class_init(OsinfoInstallScriptClass * klass)199 osinfo_install_script_class_init(OsinfoInstallScriptClass *klass)
200 {
201     GObjectClass *g_klass = G_OBJECT_CLASS(klass);
202 
203     g_klass->get_property = osinfo_install_script_get_property;
204     g_klass->set_property = osinfo_install_script_set_property;
205     g_klass->finalize = osinfo_install_script_finalize;
206 
207     properties[PROP_TEMPLATE_URI] = g_param_spec_string("template-uri",
208                                                         "TemplateURI",
209                                                         _("URI for install script template"),
210                                                         NULL /* default value */,
211                                                         G_PARAM_READABLE |
212                                                         G_PARAM_WRITABLE |
213                                                         G_PARAM_CONSTRUCT_ONLY |
214                                                         G_PARAM_STATIC_STRINGS);
215 
216     properties[PROP_TEMPLATE_DATA] = g_param_spec_string("template-data",
217                                                          "TemplateData",
218                                                          _("Data for install script template"),
219                                                          NULL /* default value */,
220                                                          G_PARAM_READABLE |
221                                                          G_PARAM_WRITABLE |
222                                                          G_PARAM_CONSTRUCT_ONLY |
223                                                          G_PARAM_STATIC_STRINGS);
224 
225     properties[PROP_PROFILE] = g_param_spec_string("profile",
226                                                    "Profile",
227                                                    _("Install script profile name"),
228                                                    NULL /* default value */,
229                                                    G_PARAM_READABLE |
230                                                    G_PARAM_WRITABLE |
231                                                    G_PARAM_CONSTRUCT_ONLY |
232                                                    G_PARAM_STATIC_STRINGS);
233 
234     properties[PROP_PRODUCT_KEY_FORMAT] = g_param_spec_string("product-key-format",
235                                                               "Product Key Format",
236                                                               _("Product key format mask"),
237                                                               NULL /* default value */,
238                                                               G_PARAM_READABLE |
239                                                               G_PARAM_STATIC_STRINGS);
240 
241     properties[PROP_PATH_FORMAT] = g_param_spec_enum("path-format",
242                                                      "Path Format",
243                                                      _("Expected path format"),
244                                                      OSINFO_TYPE_PATH_FORMAT,
245                                                      OSINFO_PATH_FORMAT_UNIX /* default value */,
246                                                      G_PARAM_READABLE |
247                                                      G_PARAM_STATIC_STRINGS);
248 
249     properties[PROP_AVATAR_FORMAT] = g_param_spec_object("avatar-format",
250                                                          "Avatar Format",
251                                                          _("Expected avatar format"),
252                                                          OSINFO_TYPE_AVATAR_FORMAT,
253                                                          G_PARAM_READABLE |
254                                                          G_PARAM_STATIC_STRINGS);
255 
256     properties[PROP_PREFERRED_INJECTION_METHOD] = g_param_spec_flags("preferred-injection-method",
257                                                                      "Preferred Injection Method",
258                                                                      _("The preferred injection method"),
259                                                                      OSINFO_TYPE_INSTALL_SCRIPT_INJECTION_METHOD,
260                                                                      OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_DISK, /* default value */
261                                                                      G_PARAM_READABLE |
262                                                                      G_PARAM_WRITABLE |
263                                                                      G_PARAM_STATIC_STRINGS);
264 
265     properties[PROP_INSTALLATION_SOURCE] = g_param_spec_enum("installation-source",
266                                                              "Installation Source",
267                                                              _("The installation source to be used"),
268                                                              OSINFO_TYPE_INSTALL_SCRIPT_INSTALLATION_SOURCE,
269                                                              OSINFO_INSTALL_SCRIPT_INSTALLATION_SOURCE_MEDIA,
270                                                              G_PARAM_READABLE |
271                                                              G_PARAM_STATIC_STRINGS);
272 
273     g_object_class_install_properties(g_klass, LAST_PROP, properties);
274 }
275 
osinfo_install_script_add_config_param(OsinfoInstallScript * script,OsinfoInstallConfigParam * param)276 void osinfo_install_script_add_config_param(OsinfoInstallScript *script, OsinfoInstallConfigParam *param)
277 {
278     g_return_if_fail(OSINFO_IS_INSTALL_SCRIPT(script));
279     g_return_if_fail(OSINFO_IS_INSTALL_CONFIG_PARAM(param));
280 
281     osinfo_list_add(OSINFO_LIST(script->priv->config_params),
282                     OSINFO_ENTITY(param));
283 }
284 
285 /**
286  * osinfo_install_script_has_config_param:
287  * @script: the install script
288  * @config_param: an #OsinfoInstallConfigParam
289  *
290  * Returns whether the @script has the @config_param searched or not.
291  *
292  * This code assumes that the 'id' and 'name' entity properties are the same.
293  *
294  * Since: 0.2.0
295  */
osinfo_install_script_has_config_param(OsinfoInstallScript * script,OsinfoInstallConfigParam * config_param)296 gboolean osinfo_install_script_has_config_param(OsinfoInstallScript *script, OsinfoInstallConfigParam *config_param)
297 {
298     const char *name = osinfo_install_config_param_get_name(config_param);
299     return osinfo_install_script_has_config_param_name(script, name);
300 }
301 
302 /**
303  * osinfo_install_script_has_config_param_name:
304  * @script: the install script
305  * @name: the configuration parameter name
306  *
307  * Returns whether the @script has a configuration parameter matching @name or not.
308  *
309  * Since: 0.2.0
310  */
osinfo_install_script_has_config_param_name(OsinfoInstallScript * script,const gchar * name)311 gboolean osinfo_install_script_has_config_param_name(OsinfoInstallScript *script, const gchar *name)
312 {
313     OsinfoList *l = OSINFO_LIST(script->priv->config_params);
314     return (osinfo_list_find_by_id(l, name) != NULL);
315 }
316 
317 /**
318  * osinfo_install_script_get_config_param_list:
319  * @script: the install script
320  *
321  * Get the list of valid config parameters for @script.
322  *
323  * Returns: (transfer container) (element-type OsinfoInstallScript): the
324  * list of valid #OsinfoInstallConfigParam parameters. Free with
325  * g_list_free() when done. The elements are owned by libosinfo.
326  *
327  * Since: 0.2.0
328  */
osinfo_install_script_get_config_param_list(OsinfoInstallScript * script)329 GList *osinfo_install_script_get_config_param_list(OsinfoInstallScript *script)
330 {
331     return osinfo_list_get_elements(OSINFO_LIST(script->priv->config_params));
332 }
333 
334 /**
335  * osinfo_install_script_get_config_params:
336  * @script: the install script
337  *
338  * Get the list of valid config parameters for @script.
339  *
340  * Returns: (transfer none): the list of valid #OsinfoInstallConfigParam
341  * parameters.
342  *
343  * Since: 0.2.3
344  */
osinfo_install_script_get_config_params(OsinfoInstallScript * script)345 OsinfoInstallConfigParamList *osinfo_install_script_get_config_params(OsinfoInstallScript *script)
346 {
347     return script->priv->config_params;
348 }
349 
350 /**
351  * osinfo_install_script_get_config_param:
352  * @script: the install script
353  * @name: name of the parameter
354  *
355  * Get a config param from the config param's list
356  *
357  * Returns: (transfer full): the sought config param, if exists.
358  *                           NULL otherwise.
359  *
360  * This code assumes that the 'id' and 'name' entity properties are
361  * the same.
362  *
363  * Since: 0.2.1
364  */
365 OsinfoInstallConfigParam *
osinfo_install_script_get_config_param(OsinfoInstallScript * script,const gchar * name)366 osinfo_install_script_get_config_param(OsinfoInstallScript *script,
367                                        const gchar *name)
368 {
369     OsinfoInstallConfigParam *param;
370     OsinfoList *l = OSINFO_LIST(script->priv->config_params);
371     param = OSINFO_INSTALL_CONFIG_PARAM(osinfo_list_find_by_id(l, name));
372     if (param == NULL)
373         return NULL;
374 
375     return g_object_ref(G_OBJECT(param));
376 }
377 
378 static void
osinfo_install_script_init(OsinfoInstallScript * list)379 osinfo_install_script_init(OsinfoInstallScript *list)
380 {
381     list->priv = osinfo_install_script_get_instance_private(list);
382     list->priv->config_params = osinfo_install_config_paramlist_new();
383 }
384 
385 
386 /**
387  * oisinfo_install_script_new:
388  * @id: a unique identifier
389  *
390  * Construct an empty new install script.
391  *
392  * Returns: (transfer full): a new install script
393  *
394  * Since: 0.2.0
395  */
osinfo_install_script_new(const gchar * id)396 OsinfoInstallScript *osinfo_install_script_new(const gchar *id)
397 {
398     return g_object_new(OSINFO_TYPE_INSTALL_SCRIPT,
399                         "id", id,
400                         NULL);
401 }
402 
403 /**
404  * osinfo_install_script_new_data:
405  * @id: a unique identifier
406  * @profile: the profile of script
407  * @templateData: style sheet data
408  *
409  * Construct a new install script from stylesheet data
410  *
411  * Returns: (transfer full): an new install script
412  *
413  * Since: 0.2.0
414  */
osinfo_install_script_new_data(const gchar * id,const gchar * profile,const gchar * templateData)415 OsinfoInstallScript *osinfo_install_script_new_data(const gchar *id,
416                                                     const gchar *profile,
417                                                     const gchar *templateData)
418 {
419     return g_object_new(OSINFO_TYPE_INSTALL_SCRIPT,
420                         "id", id,
421                         "profile", profile,
422                         "template-data", templateData,
423                         NULL);
424 }
425 
426 
427 /**
428  * osinfo_install_script_new_uri:
429  * @id: a unique identifier
430  * @profile: the profile of script
431  * @templateUri: style sheet URI
432  *
433  * Construct a new install script from a stylesheet URI
434  *
435  * Returns: (transfer full): an new install script
436  *
437  * Since: 0.2.0
438  */
osinfo_install_script_new_uri(const gchar * id,const gchar * profile,const gchar * templateUri)439 OsinfoInstallScript *osinfo_install_script_new_uri(const gchar *id,
440                                                    const gchar *profile,
441                                                    const gchar *templateUri)
442 {
443     return g_object_new(OSINFO_TYPE_INSTALL_SCRIPT,
444                         "id", id,
445                         "profile", profile,
446                         "template-uri", templateUri,
447                         NULL);
448 }
449 
450 
451 /**
452  * osinfo_install_script_get_template_uri:
453  * @script: the install script
454  *
455  * Returns the stylesheet URI used to construct the install script.
456  *
457  * Since: 0.2.0
458  */
osinfo_install_script_get_template_uri(OsinfoInstallScript * script)459 const gchar *osinfo_install_script_get_template_uri(OsinfoInstallScript *script)
460 {
461     return osinfo_entity_get_param_value(OSINFO_ENTITY(script),
462                                          OSINFO_INSTALL_SCRIPT_PROP_TEMPLATE_URI);
463 }
464 
465 /**
466  * osinfo_install_script_get_template_data:
467  * @script: the install script
468  *
469  * Returns the stylesheet data used to construct the install script.
470  *
471  * Since: 0.2.0
472  */
osinfo_install_script_get_template_data(OsinfoInstallScript * script)473 const gchar *osinfo_install_script_get_template_data(OsinfoInstallScript *script)
474 {
475     return osinfo_entity_get_param_value(OSINFO_ENTITY(script),
476                                          OSINFO_INSTALL_SCRIPT_PROP_TEMPLATE_DATA);
477 }
478 
479 /**
480  * osinfo_install_script_get_profile:
481  * @script: the install script
482  *
483  * Returns a string representing the install script profile that's going to be
484  * used.
485  *
486  * The values supported are "jeos" for minimal installations and "desktop" for
487  * workstation/desktop installations.
488  *
489  * Since: 0.2.0
490  */
osinfo_install_script_get_profile(OsinfoInstallScript * script)491 const gchar *osinfo_install_script_get_profile(OsinfoInstallScript *script)
492 {
493     return osinfo_entity_get_param_value(OSINFO_ENTITY(script),
494                                          OSINFO_INSTALL_SCRIPT_PROP_PROFILE);
495 }
496 
497 /**
498  * osinfo_install_script_get_product_key_format:
499  * @script: the install script
500  *
501  * If this function returns a non-NULL string, it means that the @script
502  * requires you to specify product registration key through #OsinfoInstallConfig
503  * instance passed to script generation methods.
504  *
505  * The returned string specifies the expected format of the product key like this:
506  *
507  * @ - any character
508  * % - alphabet
509  * # - numeric character
510  * $ - alphanumeric character
511  *
512  * All other characters represent themselves.
513  *
514  * For example in case of installer for Microsoft Windows XP, you'll get
515  * "$$$$$-$$$$$-$$$$$-$$$$$-$$$$$". That means a product key consists of 24
516  * alphanumeric characters and 4 '-' characters at (0-based) indices 5, 11, 17
517  * and 23.
518  *
519  * Returns: (transfer none): Product key format mask, or NULL.
520  *
521  * Since: 0.2.2
522  */
osinfo_install_script_get_product_key_format(OsinfoInstallScript * script)523 const gchar *osinfo_install_script_get_product_key_format(OsinfoInstallScript *script)
524 {
525     return osinfo_entity_get_param_value(OSINFO_ENTITY(script),
526                                          OSINFO_INSTALL_SCRIPT_PROP_PRODUCT_KEY_FORMAT);
527 }
528 
529 /**
530  * osinfo_install_script_set_output_prefix:
531  * @script: the install script
532  * @prefix: a prefix to be added to the file generated
533  *
534  * Mind that not all installers support any name for the installer scripts.
535  *
536  * Since: 0.2.0
537  */
osinfo_install_script_set_output_prefix(OsinfoInstallScript * script,const gchar * prefix)538 void osinfo_install_script_set_output_prefix(OsinfoInstallScript *script,
539                                              const gchar *prefix)
540 {
541     const char *output_filename =
542         osinfo_install_script_get_expected_filename(script);
543 
544     g_free(script->priv->output_prefix);
545     script->priv->output_prefix = g_strdup(prefix);
546 
547     /* update output_filename whenever output_prefix is changed */
548     g_free(script->priv->output_filename);
549     script->priv->output_filename = g_strjoin("-",
550                                               prefix,
551                                               output_filename,
552                                               NULL);
553 }
554 
555 /**
556  * osinfo_install_script_get_output_prefix:
557  * @script: the install script
558  *
559  * Returns: the prefix of the file generated
560  *
561  * Since: 0.2.8
562  */
osinfo_install_script_get_output_prefix(OsinfoInstallScript * script)563 const gchar *osinfo_install_script_get_output_prefix(OsinfoInstallScript *script)
564 {
565     return script->priv->output_prefix;
566 }
567 
568 /**
569  * osinfo_install_script_get_expected_filename:
570  * @script: the install script
571  *
572  * Some operating systems (as Windows) expect that script filename has
573  * particular name to work.
574  *
575  * Returns: (transfer none): the expected script filename
576  *
577  * Since: 0.2.1
578  */
osinfo_install_script_get_expected_filename(OsinfoInstallScript * script)579 const gchar *osinfo_install_script_get_expected_filename(OsinfoInstallScript *script)
580 {
581     return osinfo_entity_get_param_value(OSINFO_ENTITY(script),
582                                          OSINFO_INSTALL_SCRIPT_PROP_EXPECTED_FILENAME);
583 }
584 
585 /**
586  * osinfo_install_script_get_output_filename:
587  * @script: the install script
588  *
589  * Some operating systems are able to use any script filename, allowing the
590  * application to set the filename as desired. libosinfo provides this
591  * functionality by set the expected filename's prefix using
592  * osinfo_install_script_set_output_prefix() function.
593  *
594  * Returns: (transfer none): the output script filename
595  *
596  * Since: 0.2.0
597  */
osinfo_install_script_get_output_filename(OsinfoInstallScript * script)598 const gchar *osinfo_install_script_get_output_filename(OsinfoInstallScript *script)
599 {
600     if (script->priv->output_filename == NULL)
601         return osinfo_install_script_get_expected_filename(script);
602 
603     return script->priv->output_filename;
604 }
605 
606 void
osinfo_install_script_set_avatar_format(OsinfoInstallScript * script,OsinfoAvatarFormat * avatar)607 osinfo_install_script_set_avatar_format(OsinfoInstallScript *script,
608                                         OsinfoAvatarFormat *avatar)
609 {
610     g_return_if_fail(OSINFO_IS_INSTALL_SCRIPT(script));
611     g_return_if_fail(OSINFO_IS_AVATAR_FORMAT(avatar));
612 
613     if (script->priv->avatar != NULL)
614         g_object_unref(script->priv->avatar);
615     script->priv->avatar = g_object_ref(avatar);
616 }
617 
618 /**
619  * osinfo_install_script_get_avatar_format:
620  * @script: the install script
621  *
622  * Some install scripts have restrictions on the format of the user avatar. Use
623  * this method to retrieve those restrictions in the form of an
624  * #OsinfoAvatarFormat instance.
625  *
626  * Returns: (transfer none): The avatar format, or NULL if there is no restrictions on the
627  *                           format of avatar
628  *
629  * Since: 0.2.2
630  */
osinfo_install_script_get_avatar_format(OsinfoInstallScript * script)631 OsinfoAvatarFormat *osinfo_install_script_get_avatar_format(OsinfoInstallScript *script)
632 {
633     g_return_val_if_fail(OSINFO_IS_INSTALL_SCRIPT(script), NULL);
634 
635     if (script->priv->avatar == NULL)
636         return NULL;
637 
638     return script->priv->avatar;
639 }
640 
641 struct _OsinfoInstallScriptGenerateData {
642     GTask *res;
643     OsinfoOs *os;
644     OsinfoMedia *media;
645     OsinfoTree *tree;
646     OsinfoInstallConfig *config;
647     OsinfoInstallScript *script;
648 };
649 
650 
osinfo_install_script_generate_data_free(OsinfoInstallScriptGenerateData * data)651 static void osinfo_install_script_generate_data_free(OsinfoInstallScriptGenerateData *data)
652 {
653     g_object_unref(data->os);
654     if (data->media != NULL)
655         g_object_unref(data->media);
656     if (data->tree != NULL)
657         g_object_unref(data->tree);
658     g_object_unref(data->config);
659     g_object_unref(data->script);
660     g_object_unref(data->res);
661     g_free(data);
662 }
663 
664 struct _OsinfoInstallScriptGenerateOutputData {
665     GTask *res;
666     GError *error;
667     GFile *file;
668     GFileOutputStream *stream;
669     gchar *output;
670     gssize output_len;
671     gssize output_pos;
672 };
673 
osinfo_install_script_generate_output_data_free(OsinfoInstallScriptGenerateOutputData * data)674 static void osinfo_install_script_generate_output_data_free(OsinfoInstallScriptGenerateOutputData *data)
675 {
676     g_object_unref(data->stream);
677     g_object_unref(data->res);
678     g_free(data);
679 }
680 
681 
osinfo_install_script_load_template(const gchar * uri,const gchar * template,GError ** error)682 static xsltStylesheetPtr osinfo_install_script_load_template(const gchar *uri,
683                                                              const gchar *template,
684                                                              GError **error)
685 {
686     xsltStylesheetPtr xslt = NULL;
687     xmlDocPtr doc = NULL;
688     xmlParserCtxtPtr pctxt;
689 
690     /* Set up a parser context so we can catch the details of XML errors. */
691     pctxt = xmlNewParserCtxt();
692     if (!pctxt || !pctxt->sax) {
693         g_set_error_literal(error, OSINFO_ERROR, 0,
694                             _("Unable to create XML parser context"));
695         goto cleanup;
696     }
697 
698     if (!(doc = xmlCtxtReadDoc(pctxt, BAD_CAST template, uri, NULL,
699                                XML_PARSE_NONET |
700                                XML_PARSE_NOWARNING))) {
701         g_set_error_literal(error, OSINFO_ERROR, 0,
702                             _("Unable to read XSL template"));
703         goto cleanup;
704     }
705 
706     if (!(xslt = xsltParseStylesheetDoc(doc))) {
707         g_set_error_literal(error, OSINFO_ERROR, 0,
708                             _("Unable to parse XSL template"));
709         goto cleanup;
710     }
711 
712  cleanup:
713     xmlFreeParserCtxt(pctxt);
714     return xslt;
715 }
716 
717 
718 static OsinfoDatamap *
osinfo_install_script_get_param_datamap(OsinfoInstallScript * script,const gchar * param_name)719 osinfo_install_script_get_param_datamap(OsinfoInstallScript *script,
720                                         const gchar *param_name)
721 {
722     OsinfoEntity *entity;
723     OsinfoInstallConfigParam *param;
724 
725     if (!script->priv->config_params)
726         return NULL;
727 
728     entity = osinfo_list_find_by_id(OSINFO_LIST(script->priv->config_params),
729                                     param_name);
730     if (entity == NULL) {
731         g_debug("%s is not a known parameter for this config", param_name);
732         return NULL;
733     }
734 
735     param = OSINFO_INSTALL_CONFIG_PARAM(entity);
736     return osinfo_install_config_param_get_value_map(param);
737 }
738 
739 
740 static GList *
osinfo_install_script_get_param_value_list(OsinfoInstallScript * script,OsinfoInstallConfig * config,const gchar * key)741 osinfo_install_script_get_param_value_list(OsinfoInstallScript *script,
742                                            OsinfoInstallConfig *config,
743                                            const gchar *key)
744 {
745     GList *values;
746     GList *it;
747     OsinfoDatamap *map;
748 
749     values = osinfo_entity_get_param_value_list(OSINFO_ENTITY(config), key);
750     if (values == NULL)
751         return NULL;
752 
753     map = osinfo_install_script_get_param_datamap(script, key);
754     if (map != NULL) {
755         for (it = values; it != NULL; it = it->next) {
756             const char *transformed_value;
757             transformed_value = osinfo_datamap_lookup(map, it->data);
758             if (transformed_value == NULL) {
759                 continue;
760             }
761             it->data = (gpointer)transformed_value;
762         }
763     }
764 
765     return values;
766 }
767 
768 static void propagate_libxml_error(GError **error, const char *format, ...) G_GNUC_PRINTF(2, 3);
769 
propagate_libxml_error(GError ** error,const char * format,...)770 static void propagate_libxml_error(GError **error, const char *format, ...)
771 {
772     xmlErrorPtr err = xmlGetLastError();
773     char *prefix;
774     va_list ap;
775 
776     va_start(ap, format);
777     prefix = g_strdup_vprintf(format, ap);
778     va_end(ap);
779 
780     if (err == NULL) {
781         g_set_error_literal(error, OSINFO_ERROR, 0, prefix);
782     } else {
783         g_set_error(error, OSINFO_ERROR, 0, "%s: %s", prefix, err->message);
784     }
785     g_free(prefix);
786 }
787 
osinfo_install_script_generate_entity_xml(OsinfoInstallScript * script,OsinfoEntity * entity,const gchar * name,GError ** error)788 static xmlNodePtr osinfo_install_script_generate_entity_xml(OsinfoInstallScript *script,
789                                                             OsinfoEntity *entity,
790                                                             const gchar *name,
791                                                             GError **error)
792 {
793     xmlNodePtr node = NULL;
794     xmlNodePtr data = NULL;
795     GList *keys = NULL;
796     GList *tmp1;
797 
798     if (!(node = xmlNewDocNode(NULL, NULL, (xmlChar*)name, NULL))) {
799         propagate_libxml_error(error, _("Unable to create XML node '%s'"), name);
800         goto error;
801     }
802 
803     if (!(data = xmlNewDocRawNode(NULL, NULL, (const xmlChar*)"id",
804                                   (const xmlChar*)osinfo_entity_get_id(entity)))) {
805         propagate_libxml_error(error, _("Unable to create XML node 'id'"));
806         goto error;
807     }
808     if (!(xmlAddChild(node, data))) {
809         propagate_libxml_error(error, _("Unable to add XML child"));
810         goto error;
811     }
812     data = NULL;
813 
814     tmp1 = keys = osinfo_entity_get_param_keys(entity);
815     while (tmp1) {
816         GList *values;
817         GList *tmp2;
818 
819         if (OSINFO_IS_INSTALL_CONFIG(entity))
820             values = osinfo_install_script_get_param_value_list(script,
821                                                                 OSINFO_INSTALL_CONFIG(entity),
822                                                                 tmp1->data);
823         else
824             values = osinfo_entity_get_param_value_list(entity, tmp1->data);
825 
826         tmp2 = values;
827         while (tmp2) {
828             if (!(data = xmlNewDocRawNode(NULL, NULL, (const xmlChar*)tmp1->data,
829                                           (const xmlChar*)tmp2->data))) {
830                 propagate_libxml_error(error, _("Unable to create XML node '%s'"),
831                                        (const gchar *)tmp1->data);
832                 goto error;
833             }
834             if (!(xmlAddChild(node, data))) {
835                 propagate_libxml_error(error, _("Unable to add XML child"));
836                 goto error;
837             }
838             data = NULL;
839 
840             tmp2 = tmp2->next;
841         }
842         g_list_free(values);
843 
844         tmp1 = tmp1->next;
845     }
846     g_list_free(keys);
847 
848     return node;
849 
850  error:
851     g_list_free(keys);
852     xmlFreeNode(data);
853     xmlFreeNode(node);
854     return NULL;
855 }
856 
857 
osinfo_install_script_generate_config_xml(OsinfoInstallScript * script,OsinfoOs * os,OsinfoMedia * media,OsinfoTree * tree,OsinfoInstallConfig * config,const gchar * node_name,GError ** error)858 static xmlDocPtr osinfo_install_script_generate_config_xml(OsinfoInstallScript *script,
859                                                            OsinfoOs *os,
860                                                            OsinfoMedia *media,
861                                                            OsinfoTree *tree,
862                                                            OsinfoInstallConfig *config,
863                                                            const gchar *node_name,
864                                                            GError **error)
865 {
866     xmlDocPtr doc = xmlNewDoc((xmlChar *)"1.0");
867     xmlNodePtr root;
868     xmlNodePtr node;
869 
870     root = xmlNewDocNode(NULL,
871                          NULL,
872                          (xmlChar*)node_name,
873                          NULL);
874     xmlDocSetRootElement(doc, root);
875 
876     if (!(node = osinfo_install_script_generate_entity_xml(script,
877                                                            OSINFO_ENTITY(script),
878                                                            "script",
879                                                            error)))
880         goto error;
881     if (!(xmlAddChild(root, node))) {
882         propagate_libxml_error(error, _("Unable to set XML root"));
883         goto error;
884     }
885 
886     if (!(node = osinfo_install_script_generate_entity_xml(script,
887                                                            OSINFO_ENTITY(os),
888                                                            "os",
889                                                            error)))
890         goto error;
891     if (!(xmlAddChild(root, node))) {
892         propagate_libxml_error(error, _("Unable to set XML root"));
893         goto error;
894     }
895 
896     if (media != NULL) {
897         if (!(node = osinfo_install_script_generate_entity_xml(script,
898                                                                OSINFO_ENTITY(media),
899                                                                "media",
900                                                                error)))
901             goto error;
902         if (!(xmlAddChild(root, node))) {
903             propagate_libxml_error(error, _("Unable to set 'media' node"));
904             goto error;
905         }
906     }
907 
908     if (tree != NULL) {
909         if (!(node = osinfo_install_script_generate_entity_xml(script,
910                                                                OSINFO_ENTITY(tree),
911                                                                "tree",
912                                                                error)))
913             goto error;
914         if (!(xmlAddChild(root, node))) {
915             propagate_libxml_error(error, _("Unable to set 'tree' node"));
916             goto error;
917         }
918     }
919 
920     if (!(node = osinfo_install_script_generate_entity_xml(script,
921                                                            OSINFO_ENTITY(config),
922                                                            "config",
923                                                            error)))
924         goto error;
925     if (!(xmlAddChild(root, node))) {
926         propagate_libxml_error(error, _("Unable to set XML root"));
927         goto error;
928     }
929 
930     return doc;
931 
932  error:
933     xmlFreeDoc(doc);
934     doc = NULL;
935     return NULL;
936 }
937 
osinfo_install_script_apply_xslt(xsltStylesheetPtr ss,xmlDocPtr doc,GError ** error)938 static gchar *osinfo_install_script_apply_xslt(xsltStylesheetPtr ss,
939                                                xmlDocPtr doc,
940                                                GError **error)
941 {
942     xsltTransformContextPtr ctxt;
943     xmlChar *xsltResult;
944     gchar *ret = NULL;
945     xmlDocPtr docOut = NULL;
946     int len;
947 
948     if (!(ctxt = xsltNewTransformContext(ss, doc))) {
949         g_set_error_literal(error, OSINFO_ERROR, 0, _("Unable to create XSL transform context"));
950         goto cleanup;
951     }
952 
953     if (!(docOut = xsltApplyStylesheetUser(ss, doc, NULL, NULL, NULL, ctxt))) {
954         g_set_error_literal(error, OSINFO_ERROR, 0, _("Unable to apply XSL transform context"));
955         goto cleanup;
956     }
957 
958     if (xsltSaveResultToString(&xsltResult, &len, docOut, ss) < 0) {
959         g_set_error_literal(error, OSINFO_ERROR, 0, _("Unable to convert XSL output to string"));
960         goto cleanup;
961     }
962     ret = g_strdup((gchar *)xsltResult);
963     xmlFree(xsltResult);
964 
965  cleanup:
966     xmlFreeDoc(docOut);
967     xsltFreeTransformContext(ctxt);
968     return ret;
969 }
970 
971 
osinfo_install_script_apply_template(OsinfoInstallScript * script,OsinfoOs * os,OsinfoMedia * media,OsinfoTree * tree,const gchar * templateUri,const gchar * template,const gchar * node_name,gchar ** result,OsinfoInstallConfig * config,GError ** error)972 static gboolean osinfo_install_script_apply_template(OsinfoInstallScript *script,
973                                                      OsinfoOs *os,
974                                                      OsinfoMedia *media,
975                                                      OsinfoTree *tree,
976                                                      const gchar *templateUri,
977                                                      const gchar *template,
978                                                      const gchar *node_name,
979                                                      gchar **result,
980                                                      OsinfoInstallConfig *config,
981                                                      GError **error)
982 {
983     gboolean ret = FALSE;
984     xsltStylesheetPtr templateXsl = osinfo_install_script_load_template(templateUri, template, error);
985     xmlDocPtr configXml = osinfo_install_script_generate_config_xml(script, os, media, tree, config, node_name, error);
986 
987     if (!templateXsl || !configXml)
988         goto cleanup;
989 
990     if (!(*result = osinfo_install_script_apply_xslt(templateXsl, configXml, error)))
991         goto cleanup;
992 
993     ret = TRUE;
994 
995  cleanup:
996     xsltFreeStylesheet(templateXsl);
997     xmlFreeDoc(configXml);
998     return ret;
999 }
1000 
1001 
osinfo_install_script_template_loaded(GObject * src,GAsyncResult * res,gpointer user_data)1002 static void osinfo_install_script_template_loaded(GObject *src,
1003                                                   GAsyncResult *res,
1004                                                   gpointer user_data)
1005 {
1006     OsinfoInstallScriptGenerateData *data = user_data;
1007     GError *error = NULL;
1008     gchar *input = NULL;
1009     gchar *output = NULL;
1010     gsize length = 0;
1011     GFile *file = G_FILE(src);
1012     gchar *uri = g_file_get_uri(file);
1013 
1014     if (!g_file_load_contents_finish(file,
1015                                      res,
1016                                      &input,
1017                                      &length,
1018                                      NULL,
1019                                      &error)) {
1020         g_prefix_error(&error, _("Failed to load script template %s: "), uri);
1021         g_task_return_error(data->res, error);
1022         goto cleanup;
1023     }
1024 
1025 
1026     if (!osinfo_install_script_apply_template(data->script,
1027                                               data->os,
1028                                               data->media,
1029                                               data->tree,
1030                                               uri,
1031                                               input,
1032                                               "install-script-config",
1033                                               &output,
1034                                               data->config,
1035                                               &error)) {
1036         g_prefix_error(&error, _("Failed to apply script template %s: "), uri);
1037         g_task_return_error(data->res, error);
1038         goto cleanup;
1039     }
1040 
1041     g_task_return_pointer(data->res, output, g_free);
1042 
1043  cleanup:
1044     g_free(input);
1045     osinfo_install_script_generate_data_free(data);
1046     g_free(uri);
1047 }
1048 
1049 
osinfo_install_script_generate_async_common(OsinfoInstallScript * script,OsinfoOs * os,OsinfoMedia * media,OsinfoTree * tree,OsinfoInstallConfig * config,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1050 static void osinfo_install_script_generate_async_common(OsinfoInstallScript *script,
1051                                                         OsinfoOs *os,
1052                                                         OsinfoMedia *media,
1053                                                         OsinfoTree *tree,
1054                                                         OsinfoInstallConfig *config,
1055                                                         GCancellable *cancellable,
1056                                                         GAsyncReadyCallback callback,
1057                                                         gpointer user_data)
1058 {
1059     OsinfoInstallScriptGenerateData *data;
1060     const gchar *templateData;
1061     const gchar *templateUri;
1062 
1063     g_return_if_fail(os != NULL);
1064 
1065     data = g_new0(OsinfoInstallScriptGenerateData, 1);
1066     templateData = osinfo_install_script_get_template_data(script);
1067     templateUri = osinfo_install_script_get_template_uri(script);
1068 
1069     data->os = g_object_ref(os);
1070     if (media != NULL)
1071         data->media = g_object_ref(media);
1072     if (tree != NULL)
1073         data->tree = g_object_ref(tree);
1074     data->config = g_object_ref(config);
1075     data->script = g_object_ref(script);
1076     data->res = g_task_new(G_OBJECT(script),
1077                            cancellable,
1078                            callback,
1079                            user_data);
1080 
1081     if (templateData) {
1082         GError *error = NULL;
1083         gchar *output;
1084         if (!osinfo_install_script_apply_template(script,
1085                                                   os,
1086                                                   media,
1087                                                   NULL,
1088                                                   "<data>",
1089                                                   templateData,
1090                                                   "install-script-config",
1091                                                   &output,
1092                                                   data->config,
1093                                                   &error)) {
1094             g_prefix_error(&error, "%s", _("Failed to apply script template: "));
1095             g_task_return_error(data->res, error);
1096             osinfo_install_script_generate_data_free(data);
1097             return;
1098         }
1099         g_task_return_pointer(data->res, output, g_free);
1100         osinfo_install_script_generate_data_free(data);
1101     } else {
1102         GFile *file = g_file_new_for_uri(templateUri);
1103 
1104         g_file_load_contents_async(file,
1105                                    cancellable,
1106                                    osinfo_install_script_template_loaded,
1107                                    data);
1108         g_object_unref(file);
1109     }
1110 }
1111 
1112 /**
1113  * osinfo_install_script_generate_async:
1114  * @script:     the install script
1115  * @os:         the os
1116  * @config:     the install script config
1117  * @cancellable: (allow-none): a #GCancellable, or %NULL
1118  * @callback: Function to call when result of this call is ready
1119  * @user_data: The user data to pass to @callback, or %NULL
1120  *
1121  * Asynchronous variant of #osinfo_install_script_generate(). From the callback,
1122  * call #osinfo_install_script_generate_finish() to conclude this call and get
1123  * the generated script.
1124  *
1125  * If you are generating the script for a specific media, it is recommended that
1126  * you use #osinfo_install_script_generate_for_media_async() instead.
1127  *
1128  * Since: 0.2.0
1129  */
osinfo_install_script_generate_async(OsinfoInstallScript * script,OsinfoOs * os,OsinfoInstallConfig * config,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1130 void osinfo_install_script_generate_async(OsinfoInstallScript *script,
1131                                           OsinfoOs *os,
1132                                           OsinfoInstallConfig *config,
1133                                           GCancellable *cancellable,
1134                                           GAsyncReadyCallback callback,
1135                                           gpointer user_data)
1136 {
1137     osinfo_install_script_generate_async_common(script,
1138                                                 os,
1139                                                 NULL,
1140                                                 NULL,
1141                                                 config,
1142                                                 cancellable,
1143                                                 callback,
1144                                                 user_data);
1145 }
1146 
osinfo_install_script_generate_finish_common(OsinfoInstallScript * script,GAsyncResult * res,GError ** error)1147 static gpointer osinfo_install_script_generate_finish_common(OsinfoInstallScript *script,
1148                                                              GAsyncResult *res,
1149                                                              GError **error)
1150 {
1151     GTask *task = G_TASK(res);
1152 
1153     g_return_val_if_fail(error == NULL || *error == NULL, NULL);
1154 
1155     return g_task_propagate_pointer(task, error);
1156 }
1157 
1158 /**
1159  * osinfo_install_script_generate_finish:
1160  * @script: the install script
1161  * @res:    a #GAsyncResult
1162  * @error:  The location where to store any error, or NULL
1163  *
1164  * Returns: (transfer full): the generated script, or NULL on error
1165  *
1166  * Since: 0.2.0
1167  */
osinfo_install_script_generate_finish(OsinfoInstallScript * script,GAsyncResult * res,GError ** error)1168 gchar *osinfo_install_script_generate_finish(OsinfoInstallScript *script,
1169                                              GAsyncResult *res,
1170                                              GError **error)
1171 {
1172     return osinfo_install_script_generate_finish_common(script,
1173                                                         res,
1174                                                         error);
1175 }
1176 
1177 /**
1178  * osinfo_install_script_generate_for_media_finish:
1179  * @script: the install script
1180  * @res:    a #GAsyncResult
1181  * @error:  The location where to store any error, or NULL
1182  *
1183  * Returns: (transfer full): the generated script, or NULL on error
1184  *
1185  * Since: 0.2.12
1186  */
osinfo_install_script_generate_for_media_finish(OsinfoInstallScript * script,GAsyncResult * res,GError ** error)1187 gchar *osinfo_install_script_generate_for_media_finish(OsinfoInstallScript *script,
1188                                                        GAsyncResult *res,
1189                                                        GError **error)
1190 {
1191     return osinfo_install_script_generate_finish_common(script,
1192                                                         res,
1193                                                         error);
1194 }
1195 
1196 /**
1197  * osinfo_install_script_generate_for_tree_finish:
1198  * @script: the install script
1199  * @res:    a #GAsyncResult
1200  * @error:  the location where to story any error, or NULL
1201  *
1202  * Returns: (transfer full): the generated script, or NULL or error
1203  *
1204  * Since: 1.6.0
1205  */
osinfo_install_script_generate_for_tree_finish(OsinfoInstallScript * script,GAsyncResult * res,GError ** error)1206 gchar *osinfo_install_script_generate_for_tree_finish(OsinfoInstallScript *script,
1207                                                       GAsyncResult *res,
1208                                                       GError **error)
1209 {
1210     return osinfo_install_script_generate_finish_common(script,
1211                                                         res,
1212                                                         error);
1213 }
1214 
1215 /**
1216  * osinfo_install_script_generate_output_finish:
1217  * @script: the install script
1218  * @res:    a #GAsyncResult
1219  * @error:  The location where to store any error, or NULL
1220  *
1221  * Returns: (transfer full): a file containing the script, or NULL on error
1222  *
1223  * Since: 0.2.3
1224  */
osinfo_install_script_generate_output_finish(OsinfoInstallScript * script,GAsyncResult * res,GError ** error)1225 GFile *osinfo_install_script_generate_output_finish(OsinfoInstallScript *script,
1226                                                     GAsyncResult *res,
1227                                                     GError **error)
1228 {
1229     return osinfo_install_script_generate_finish_common(script,
1230                                                         res,
1231                                                         error);
1232 }
1233 
1234 /**
1235  * osinfo_install_script_generate_output_for_media_finish:
1236  * @script: the install script
1237  * @res:    a #GAsyncResult
1238  * @error:  the location where to store any error, or NULL
1239  *
1240  * Returns: (transfer full): a file containing the script, or NULL on error.
1241  *
1242  * Since: 0.2.12
1243  */
osinfo_install_script_generate_output_for_media_finish(OsinfoInstallScript * script,GAsyncResult * res,GError ** error)1244 GFile *osinfo_install_script_generate_output_for_media_finish(OsinfoInstallScript *script,
1245                                                               GAsyncResult *res,
1246                                                               GError **error)
1247 {
1248     return osinfo_install_script_generate_finish_common(script,
1249                                                         res,
1250                                                         error);
1251 }
1252 
1253 /**
1254  * osinfo_install_script_generate_output_for_tree_finish:
1255  * @script: the install script
1256  * @res:    a #GAsyncResult
1257  * @error:  the location where to store any error, or NULL
1258  *
1259  * Returns: (transfer full): a file containing the script, or NULL on error.
1260  *
1261  * Since: 1.6.0
1262  */
osinfo_install_script_generate_output_for_tree_finish(OsinfoInstallScript * script,GAsyncResult * res,GError ** error)1263 GFile *osinfo_install_script_generate_output_for_tree_finish(OsinfoInstallScript *script,
1264                                                              GAsyncResult *res,
1265                                                              GError **error)
1266 {
1267     return osinfo_install_script_generate_finish_common(script,
1268                                                         res,
1269                                                         error);
1270 }
1271 
1272 struct _OsinfoInstallScriptGenerateSyncData {
1273     GMainLoop *loop;
1274     GError *error;
1275     gchar *output;
1276     GFile *file;
1277 };
1278 
osinfo_install_script_generate_output_done(GObject * src,GAsyncResult * res,gpointer user_data)1279 static void osinfo_install_script_generate_output_done(GObject *src,
1280                                                        GAsyncResult *res,
1281                                                        gpointer user_data)
1282 {
1283     OsinfoInstallScriptGenerateSyncData *data = user_data;
1284 
1285     data->file =
1286         osinfo_install_script_generate_output_finish(OSINFO_INSTALL_SCRIPT(src),
1287                                                      res,
1288                                                      &data->error);
1289     g_main_loop_quit(data->loop);
1290 }
1291 
osinfo_install_script_generate_output_for_media_done(GObject * src,GAsyncResult * res,gpointer user_data)1292 static void osinfo_install_script_generate_output_for_media_done(GObject *src,
1293                                                                  GAsyncResult *res,
1294                                                                  gpointer user_data)
1295 {
1296     OsinfoInstallScriptGenerateSyncData *data = user_data;
1297 
1298     data->file =
1299         osinfo_install_script_generate_output_for_media_finish(OSINFO_INSTALL_SCRIPT(src),
1300                                                                res,
1301                                                                &data->error);
1302     g_main_loop_quit(data->loop);
1303 }
1304 
osinfo_install_script_generate_output_for_tree_done(GObject * src,GAsyncResult * res,gpointer user_data)1305 static void osinfo_install_script_generate_output_for_tree_done(GObject *src,
1306                                                                  GAsyncResult *res,
1307                                                                  gpointer user_data)
1308 {
1309     OsinfoInstallScriptGenerateSyncData *data = user_data;
1310 
1311     data->file =
1312         osinfo_install_script_generate_output_for_tree_finish(OSINFO_INSTALL_SCRIPT(src),
1313                                                               res,
1314                                                               &data->error);
1315     g_main_loop_quit(data->loop);
1316 }
1317 
osinfo_install_script_generate_output_close_file(GObject * src,GAsyncResult * res,gpointer user_data)1318 static void osinfo_install_script_generate_output_close_file(GObject *src,
1319                                                             GAsyncResult *res,
1320                                                             gpointer user_data)
1321 {
1322     OsinfoInstallScriptGenerateOutputData *data = user_data;
1323 
1324     g_output_stream_close_finish(G_OUTPUT_STREAM(src),
1325                                  res,
1326                                  &data->error);
1327 
1328     g_task_return_pointer(data->res, data->file, NULL);
1329 
1330     osinfo_install_script_generate_output_data_free(data);
1331 }
1332 
osinfo_install_script_generate_done(GObject * src,GAsyncResult * res,gpointer user_data)1333 static void osinfo_install_script_generate_done(GObject *src,
1334                                                 GAsyncResult *res,
1335                                                 gpointer user_data)
1336 {
1337     OsinfoInstallScriptGenerateSyncData *data = user_data;
1338 
1339     data->output =
1340         osinfo_install_script_generate_finish(OSINFO_INSTALL_SCRIPT(src),
1341                                               res,
1342                                               &data->error);
1343     g_main_loop_quit(data->loop);
1344 }
1345 
1346 /**
1347  * osinfo_install_script_generate:
1348  * @script:     the install script
1349  * @os:         the os
1350  * @config:     the install script config
1351  * @cancellable: (allow-none): a #GCancellable, or %NULL
1352  * @error: The location where to store any error, or %NULL
1353  *
1354  * Creates an install script.
1355  *
1356  * Returns: (transfer full): the script as string.
1357  *
1358  * If you are generating the script for a specific media, it is recommended
1359  * that you use #osinfo_install_script_generate_for_media() instead.
1360  *
1361  * If you are generating the script for a specific tree, it is recommended
1362  * that you use #osinfo_install_script_generate_for_tree() in instead.
1363  *
1364  * Since: 0.2.0
1365  */
osinfo_install_script_generate(OsinfoInstallScript * script,OsinfoOs * os,OsinfoInstallConfig * config,GCancellable * cancellable,GError ** error)1366 gchar *osinfo_install_script_generate(OsinfoInstallScript *script,
1367                                       OsinfoOs *os,
1368                                       OsinfoInstallConfig *config,
1369                                       GCancellable *cancellable,
1370                                       GError **error)
1371 {
1372     GMainLoop *loop = g_main_loop_new(g_main_context_get_thread_default(),
1373                                       FALSE);
1374     OsinfoInstallScriptGenerateSyncData data = {
1375         loop, NULL, NULL, NULL
1376     };
1377 
1378     osinfo_install_script_generate_async(script,
1379                                          os,
1380                                          config,
1381                                          cancellable,
1382                                          osinfo_install_script_generate_done,
1383                                          &data);
1384 
1385     g_main_loop_run(loop);
1386 
1387     if (data.error)
1388         g_propagate_error(error, data.error);
1389 
1390     g_main_loop_unref(loop);
1391 
1392     return data.output;
1393 }
1394 
1395 /**
1396  * osinfo_install_script_generate_for_media_async:
1397  * @script:     the install script
1398  * @media:      the media
1399  * @config:     the install script config
1400  * @cancellable: (allow-none): a #GCancellable, or %NULL
1401  * @callback: Function to call when result of this call is ready
1402  * @user_data: The user data to pass to @callback, or %NULL
1403  *
1404  * Asynchronous variant of #osinfo_install_script_generate_for_media(). From the
1405  * callback, call #osinfo_install_script_generate_for_media_finish() to
1406  * conclude this call and get the generated script.
1407  *
1408  * Since: 0.2.12
1409  */
osinfo_install_script_generate_for_media_async(OsinfoInstallScript * script,OsinfoMedia * media,OsinfoInstallConfig * config,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1410 void osinfo_install_script_generate_for_media_async(OsinfoInstallScript *script,
1411                                                     OsinfoMedia *media,
1412                                                     OsinfoInstallConfig *config,
1413                                                     GCancellable *cancellable,
1414                                                     GAsyncReadyCallback callback,
1415                                                     gpointer user_data) {
1416     OsinfoOs *os;
1417 
1418     g_return_if_fail(media != NULL);
1419 
1420     os = osinfo_media_get_os(media);
1421 
1422     osinfo_install_script_generate_async_common(script,
1423                                                 os,
1424                                                 media,
1425                                                 NULL,
1426                                                 config,
1427                                                 cancellable,
1428                                                 callback,
1429                                                 user_data);
1430 
1431     g_object_unref(os);
1432 }
1433 
osinfo_install_script_generate_for_media_done(GObject * src,GAsyncResult * res,gpointer user_data)1434 static void osinfo_install_script_generate_for_media_done(GObject *src,
1435                                                           GAsyncResult *res,
1436                                                           gpointer user_data)
1437 {
1438     OsinfoInstallScriptGenerateSyncData *data = user_data;
1439 
1440     data->output =
1441         osinfo_install_script_generate_for_media_finish(OSINFO_INSTALL_SCRIPT(src),
1442                                                         res,
1443                                                         &data->error);
1444     g_main_loop_quit(data->loop);
1445 }
1446 
1447 /**
1448  * osinfo_install_script_generate_for_media:
1449  * @script:     the install script
1450  * @media:      the media
1451  * @config:     the install script config
1452  * @cancellable: (allow-none): a #GCancellable, or %NULL
1453  * @error: The location where to store any error, or %NULL
1454  *
1455  * Creates an install script. The media @media must have been identified
1456  * successfully using #osinfo_db_identify_media() before calling this function.
1457  *
1458  * Returns: (transfer full): the script as string.
1459  *
1460  * Since: 0.2.12
1461  */
osinfo_install_script_generate_for_media(OsinfoInstallScript * script,OsinfoMedia * media,OsinfoInstallConfig * config,GCancellable * cancellable,GError ** error)1462 gchar *osinfo_install_script_generate_for_media(OsinfoInstallScript *script,
1463                                                 OsinfoMedia *media,
1464                                                 OsinfoInstallConfig *config,
1465                                                 GCancellable *cancellable,
1466                                                 GError **error)
1467 {
1468     GMainLoop *loop = g_main_loop_new(g_main_context_get_thread_default(),
1469                                       FALSE);
1470     OsinfoInstallScriptGenerateSyncData data = {
1471         loop, NULL, NULL, NULL
1472     };
1473 
1474     osinfo_install_script_generate_for_media_async(script,
1475                                                    media,
1476                                                    config,
1477                                                    cancellable,
1478                                                    osinfo_install_script_generate_for_media_done,
1479                                                    &data);
1480 
1481     g_main_loop_run(loop);
1482 
1483     if (data.error)
1484         g_propagate_error(error, data.error);
1485 
1486     g_main_loop_unref(loop);
1487 
1488     return data.output;
1489 }
1490 
1491 /**
1492  * osinfo_install_script_generate_for_tree_async:
1493  * @script:     the install script
1494  * @tree:       the tree
1495  * @config:     the install script config
1496  * @cancellable: (allow-none): a #GCancellable, or %NULL
1497  * @callback: Function to call when result of this call is ready
1498  * @user_data: The user data to pass to @callback, or %NULL
1499  *
1500  * Asynchronous variant of #osinfo_install_script_generate_for_tree(). From the
1501  * callback, call #osinfo_install_script_generate_for_tree_finish() to
1502  * conclude this call and get the generated script.
1503  *
1504  * Since: 1.6.0
1505  */
osinfo_install_script_generate_for_tree_async(OsinfoInstallScript * script,OsinfoTree * tree,OsinfoInstallConfig * config,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1506 void osinfo_install_script_generate_for_tree_async(OsinfoInstallScript *script,
1507                                                     OsinfoTree *tree,
1508                                                     OsinfoInstallConfig *config,
1509                                                     GCancellable *cancellable,
1510                                                     GAsyncReadyCallback callback,
1511                                                     gpointer user_data) {
1512     OsinfoOs *os;
1513 
1514     g_return_if_fail(tree != NULL);
1515 
1516     os = osinfo_tree_get_os(tree);
1517 
1518     osinfo_install_script_generate_async_common(script,
1519                                                 os,
1520                                                 NULL,
1521                                                 tree,
1522                                                 config,
1523                                                 cancellable,
1524                                                 callback,
1525                                                 user_data);
1526 
1527     g_object_unref(os);
1528 }
1529 
osinfo_install_script_generate_for_tree_done(GObject * src,GAsyncResult * res,gpointer user_data)1530 static void osinfo_install_script_generate_for_tree_done(GObject *src,
1531                                                          GAsyncResult *res,
1532                                                          gpointer user_data)
1533 {
1534     OsinfoInstallScriptGenerateSyncData *data = user_data;
1535 
1536     data->output =
1537         osinfo_install_script_generate_for_tree_finish(OSINFO_INSTALL_SCRIPT(src),
1538                                                         res,
1539                                                         &data->error);
1540     g_main_loop_quit(data->loop);
1541 }
1542 
1543 /**
1544  * osinfo_install_script_generate_for_tree:
1545  * @script:     the install script
1546  * @tree:       the tree
1547  * @config:     the install script config
1548  * @cancellable: (allow-none): a #GCancellable, or %NULL
1549  * @error: The location where to store any error, or %NULL
1550  *
1551  * Creates an install script. The tree @tree must have been identified
1552  * successfully using #osinfo_db_identify_tree() before calling this function.
1553  *
1554  * Returns: (transfer full): the script as string.
1555  *
1556  * Since: 1.6.0
1557  */
osinfo_install_script_generate_for_tree(OsinfoInstallScript * script,OsinfoTree * tree,OsinfoInstallConfig * config,GCancellable * cancellable,GError ** error)1558 gchar *osinfo_install_script_generate_for_tree(OsinfoInstallScript *script,
1559                                                OsinfoTree *tree,
1560                                                OsinfoInstallConfig *config,
1561                                                GCancellable *cancellable,
1562                                                GError **error)
1563 {
1564     GMainLoop *loop = g_main_loop_new(g_main_context_get_thread_default(),
1565                                       FALSE);
1566     OsinfoInstallScriptGenerateSyncData data = {
1567         loop, NULL, NULL, NULL
1568     };
1569 
1570     osinfo_install_script_generate_for_tree_async(script,
1571                                                    tree,
1572                                                    config,
1573                                                    cancellable,
1574                                                    osinfo_install_script_generate_for_tree_done,
1575                                                    &data);
1576 
1577     g_main_loop_run(loop);
1578 
1579     if (data.error)
1580         g_propagate_error(error, data.error);
1581 
1582     g_main_loop_unref(loop);
1583 
1584     return data.output;
1585 }
1586 
osinfo_install_script_generate_output_write_file(GObject * src,GAsyncResult * res,gpointer user_data)1587 static void osinfo_install_script_generate_output_write_file(GObject *src,
1588                                                              GAsyncResult *res,
1589                                                              gpointer user_data)
1590 {
1591     OsinfoInstallScriptGenerateOutputData *data = user_data;
1592 
1593     if (data->stream == NULL)
1594         data->stream = g_file_replace_finish(G_FILE(src), res, &data->error);
1595     else
1596         data->output_pos += g_output_stream_write_finish(G_OUTPUT_STREAM(data->stream),
1597                                                                          res,
1598                                                                          &data->error);
1599 
1600     if (data->output_pos < data->output_len) {
1601         g_output_stream_write_async(G_OUTPUT_STREAM(data->stream),
1602                                     data->output + data->output_pos,
1603                                     data->output_len - data->output_pos,
1604                                     G_PRIORITY_DEFAULT,
1605                                     g_task_get_cancellable(data->res),
1606                                     osinfo_install_script_generate_output_write_file,
1607                                     data);
1608 
1609     } else {
1610         g_output_stream_close_async(G_OUTPUT_STREAM(data->stream),
1611                                     G_PRIORITY_DEFAULT,
1612                                     g_task_get_cancellable(data->res),
1613                                     osinfo_install_script_generate_output_close_file,
1614                                     data);
1615     }
1616 }
1617 
osinfo_install_script_generate_output_async_common(OsinfoInstallScript * script,OsinfoOs * os,OsinfoMedia * media,OsinfoTree * tree,OsinfoInstallConfig * config,GFile * output_dir,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1618 static void osinfo_install_script_generate_output_async_common(OsinfoInstallScript *script,
1619                                                                OsinfoOs *os,
1620                                                                OsinfoMedia *media,
1621                                                                OsinfoTree *tree,
1622                                                                OsinfoInstallConfig *config,
1623                                                                GFile *output_dir,
1624                                                                GCancellable *cancellable,
1625                                                                GAsyncReadyCallback callback,
1626                                                                gpointer user_data)
1627 {
1628     const gchar *filename;
1629     const gchar *prefix;
1630     OsinfoInstallScriptGenerateOutputData *data =
1631         g_new0(OsinfoInstallScriptGenerateOutputData, 1);
1632 
1633     OsinfoInstallScriptGenerateSyncData *data_sync = user_data;
1634 
1635     data->res = g_task_new(G_OBJECT(script),
1636                            cancellable,
1637                            callback,
1638                            user_data);
1639 
1640     data->error = data_sync->error;
1641     if (media != NULL) {
1642         data->output = osinfo_install_script_generate_for_media(script,
1643                                                                 media,
1644                                                                 config,
1645                                                                 cancellable,
1646                                                                 &data->error);
1647     } else if (tree != NULL) {
1648         data->output = osinfo_install_script_generate_for_tree(script,
1649                                                                tree,
1650                                                                config,
1651                                                                cancellable,
1652                                                                &data->error);
1653     } else {
1654         data->output = osinfo_install_script_generate(script,
1655                                                       os,
1656                                                       config,
1657                                                       cancellable,
1658                                                       &data->error);
1659     }
1660     data->output_pos = 0;
1661     data->output_len = strlen(data->output);
1662 
1663     prefix =
1664         osinfo_install_script_get_output_prefix(script);
1665     filename =
1666         osinfo_install_script_get_output_filename(script);
1667 
1668     if (prefix) {
1669         gchar *output_filename  = g_strdup_printf("%s-%s", prefix, filename);
1670         data->file = g_file_get_child(output_dir, output_filename);
1671         g_free(output_filename);
1672     } else {
1673         data->file = g_file_get_child(output_dir, filename);
1674     }
1675 
1676     g_file_replace_async(data->file,
1677                          NULL,
1678                          TRUE,
1679                          G_FILE_CREATE_NONE,
1680                          G_PRIORITY_DEFAULT,
1681                          cancellable,
1682                          osinfo_install_script_generate_output_write_file,
1683                          data);
1684 }
1685 
1686 /**
1687  * osinfo_install_script_generate_output_async:
1688  * @script:     the install script
1689  * @os:         the os
1690  * @config:     the install script config
1691  * @output_dir: the directory where the file containing the output script
1692  *              will be written
1693  * @cancellable: (allow-none): a #GCancellable, or %NULL
1694  * @callback: Function to call when result of this call is ready
1695  * @user_data: The user data to pass to @callback, or %NULL
1696  *
1697  * Asynchronous variant of #osinfo_install_script_generate_output(). From the
1698  * callback, call #osinfo_install_script_generate_output_finish() to conclude
1699  * this call and get the generated script.
1700  *
1701  * If you are generating the script for a specific media, it is recommended that
1702  * you use #osinfo_install_script_generate_output_for_media_async() instead.
1703  *
1704  * Since: 0.2.0
1705  */
osinfo_install_script_generate_output_async(OsinfoInstallScript * script,OsinfoOs * os,OsinfoInstallConfig * config,GFile * output_dir,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1706 void osinfo_install_script_generate_output_async(OsinfoInstallScript *script,
1707                                                  OsinfoOs *os,
1708                                                  OsinfoInstallConfig *config,
1709                                                  GFile *output_dir,
1710                                                  GCancellable *cancellable,
1711                                                  GAsyncReadyCallback callback,
1712                                                  gpointer user_data)
1713 {
1714     osinfo_install_script_generate_output_async_common(script,
1715                                                        os,
1716                                                        NULL,
1717                                                        NULL,
1718                                                        config,
1719                                                        output_dir,
1720                                                        cancellable,
1721                                                        callback,
1722                                                        user_data);
1723 }
1724 
osinfo_install_script_generate_output_common(OsinfoInstallScript * script,OsinfoOs * os,OsinfoMedia * media,OsinfoTree * tree,OsinfoInstallConfig * config,GFile * output_dir,GCancellable * cancellable,GError ** error)1725 static GFile *osinfo_install_script_generate_output_common(OsinfoInstallScript *script,
1726                                                            OsinfoOs *os,
1727                                                            OsinfoMedia *media,
1728                                                            OsinfoTree *tree,
1729                                                            OsinfoInstallConfig *config,
1730                                                            GFile *output_dir,
1731                                                            GCancellable *cancellable,
1732                                                            GError **error)
1733 {
1734     GMainLoop *loop = g_main_loop_new(g_main_context_get_thread_default(),
1735                                       FALSE);
1736     OsinfoInstallScriptGenerateSyncData data = {
1737         loop, NULL, NULL, NULL
1738     };
1739 
1740     if (media != NULL) {
1741         osinfo_install_script_generate_output_for_media_async
1742             (script,
1743              media,
1744              config,
1745              output_dir,
1746              cancellable,
1747              osinfo_install_script_generate_output_for_media_done,
1748              &data);
1749     } else if (tree != NULL) {
1750         osinfo_install_script_generate_output_for_tree_async
1751             (script,
1752              tree,
1753              config,
1754              output_dir,
1755              cancellable,
1756              osinfo_install_script_generate_output_for_tree_done,
1757              &data);
1758     } else {
1759         osinfo_install_script_generate_output_async
1760             (script,
1761              os,
1762              config,
1763              output_dir,
1764              cancellable,
1765              osinfo_install_script_generate_output_done,
1766              &data);
1767     }
1768 
1769     g_main_loop_run(loop);
1770 
1771     if (data.error)
1772         g_propagate_error(error, data.error);
1773 
1774     g_main_loop_unref(loop);
1775 
1776     return data.file;
1777 }
1778 
1779 /**
1780  * osinfo_install_script_generate_output:
1781  * @script:     the install script
1782  * @os:         the os entity
1783  * @config:     the install script config
1784  * @output_dir: the directory where the file containing the output script
1785  *              will be written
1786  * @cancellable: (allow-none): a #GCancellable, or %NULL
1787  * @error: The location where to store any error, or %NULL
1788  *
1789  * Creates an install script that is written to the returned file.
1790  *
1791  * Returns: (transfer full): a file containing the script
1792  *
1793  * If you are generating the script for a specific media, it is recommended
1794  * that you use #osinfo_install_script_generate_output_for_media() instead.
1795  *
1796  * If you are generating the script for a specific tree, it is recommended
1797  * that you use #osinfo_install_script_generate_output_for_tree() instead.
1798  *
1799  * Since: 0.2.0
1800  */
osinfo_install_script_generate_output(OsinfoInstallScript * script,OsinfoOs * os,OsinfoInstallConfig * config,GFile * output_dir,GCancellable * cancellable,GError ** error)1801 GFile *osinfo_install_script_generate_output(OsinfoInstallScript *script,
1802                                              OsinfoOs *os,
1803                                              OsinfoInstallConfig *config,
1804                                              GFile *output_dir,
1805                                              GCancellable *cancellable,
1806                                              GError **error)
1807 {
1808     return osinfo_install_script_generate_output_common(script,
1809                                                         os,
1810                                                         NULL,
1811                                                         NULL,
1812                                                         config,
1813                                                         output_dir,
1814                                                         cancellable,
1815                                                         error);
1816 }
1817 
1818 /**
1819  * osinfo_install_script_generate_output_for_media_async:
1820  * @script:     the install script
1821  * @media:      the media
1822  * @config:     the install script config
1823  * @output_dir: the directory where the file containing the output script
1824  *              will be written
1825  * @cancellable: (allow-none): a #GCancellable, or %NULL
1826  * @callback: Function to call when result of this call is ready
1827  * @user_data: The user data to pass to @callback, or %NULL
1828  *
1829  * Asynchronous variant of #osinfo_install_script_generate_output_for_media().
1830  * From the callback, call
1831  * #osinfo_install_script_generate_output_for_media_finish() to conclude this
1832  * call and get the generated file.
1833  *
1834  * Since: 0.2.12
1835  */
osinfo_install_script_generate_output_for_media_async(OsinfoInstallScript * script,OsinfoMedia * media,OsinfoInstallConfig * config,GFile * output_dir,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1836 void osinfo_install_script_generate_output_for_media_async(OsinfoInstallScript *script,
1837                                                            OsinfoMedia *media,
1838                                                            OsinfoInstallConfig *config,
1839                                                            GFile *output_dir,
1840                                                            GCancellable *cancellable,
1841                                                            GAsyncReadyCallback callback,
1842                                                            gpointer user_data)
1843 {
1844     osinfo_install_script_generate_output_async_common(script,
1845                                                        NULL,
1846                                                        media,
1847                                                        NULL,
1848                                                        config,
1849                                                        output_dir,
1850                                                        cancellable,
1851                                                        callback,
1852                                                        user_data);
1853 }
1854 
1855 /**
1856  * osinfo_install_script_generate_output_for_media:
1857  * @script:     the install script
1858  * @media:      the media
1859  * @config:     the install script config
1860  * @output_dir: the directory where the file containing the output script
1861  *              will be written
1862  * @cancellable: (allow-none): a #GCancellable, or %NULL
1863  * @error: The location where to store any error, or %NULL
1864  *
1865  * Creates an install script that is written to the returned file.
1866  *
1867  * Returns: (transfer full): a file containing the script.
1868  *
1869  * Since: 0.2.12
1870  */
osinfo_install_script_generate_output_for_media(OsinfoInstallScript * script,OsinfoMedia * media,OsinfoInstallConfig * config,GFile * output_dir,GCancellable * cancellable,GError ** error)1871 GFile *osinfo_install_script_generate_output_for_media(OsinfoInstallScript *script,
1872                                                        OsinfoMedia *media,
1873                                                        OsinfoInstallConfig *config,
1874                                                        GFile *output_dir,
1875                                                        GCancellable *cancellable,
1876                                                        GError **error)
1877 {
1878     return osinfo_install_script_generate_output_common(script,
1879                                                         NULL,
1880                                                         media,
1881                                                         NULL,
1882                                                         config,
1883                                                         output_dir,
1884                                                         cancellable,
1885                                                         error);
1886 }
1887 
1888 /**
1889  * osinfo_install_script_generate_output_for_tree_async:
1890  * @script:     the install script
1891  * @tree:       the tree
1892  * @config:     the install script config
1893  * @output_dir: the directory where the file containing the output script
1894  *              will be written
1895  * @cancellable: (allow-none): a #GCancellable, or %NULL
1896  * @callback: Function to call when result of this call is ready
1897  * @user_data: The user data to pass to @callback, or %NULL
1898  *
1899  * Asynchronous variant of #osinfo_install_script_generate_output_for_tree().
1900  * From the callback, call
1901  * #osinfo_install_script_generate_output_for_tree_finish() to conclude this
1902  * call and get the generated file.
1903  *
1904  * Since: 1.6.0
1905  */
osinfo_install_script_generate_output_for_tree_async(OsinfoInstallScript * script,OsinfoTree * tree,OsinfoInstallConfig * config,GFile * output_dir,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1906 void osinfo_install_script_generate_output_for_tree_async(OsinfoInstallScript *script,
1907                                                           OsinfoTree *tree,
1908                                                           OsinfoInstallConfig *config,
1909                                                           GFile *output_dir,
1910                                                           GCancellable *cancellable,
1911                                                           GAsyncReadyCallback callback,
1912                                                           gpointer user_data)
1913 {
1914     osinfo_install_script_generate_output_async_common(script,
1915                                                        NULL,
1916                                                        NULL,
1917                                                        tree,
1918                                                        config,
1919                                                        output_dir,
1920                                                        cancellable,
1921                                                        callback,
1922                                                        user_data);
1923 }
1924 
1925 /**
1926  * osinfo_install_script_generate_output_for_tree:
1927  * @script:     the install script
1928  * @tree:       the tree
1929  * @config:     the install script config
1930  * @output_dir: the directory where the file containing the output script
1931  *              will be written
1932  * @cancellable: (allow-none): a #GCancellable, or %NULL
1933  * @error: The location where to store any error, or %NULL
1934  *
1935  * Creates an install script that is written to the returned file.
1936  *
1937  * Returns: (transfer full): a file containing the script.
1938  *
1939  * Since: 1.6.0
1940  */
osinfo_install_script_generate_output_for_tree(OsinfoInstallScript * script,OsinfoTree * tree,OsinfoInstallConfig * config,GFile * output_dir,GCancellable * cancellable,GError ** error)1941 GFile *osinfo_install_script_generate_output_for_tree(OsinfoInstallScript *script,
1942                                                       OsinfoTree *tree,
1943                                                       OsinfoInstallConfig *config,
1944                                                       GFile *output_dir,
1945                                                       GCancellable *cancellable,
1946                                                       GError **error)
1947 {
1948     return osinfo_install_script_generate_output_common(script,
1949                                                         NULL,
1950                                                         NULL,
1951                                                         tree,
1952                                                         config,
1953                                                         output_dir,
1954                                                         cancellable,
1955                                                         error);
1956 }
1957 
1958 /**
1959  * osinfo_install_script_generate_command_line:
1960  * @script: the install script
1961  * @os:     the os entity
1962  * @config: the install script config
1963  *
1964  * Some install scripts need to pass a command line to the kernel, Such install
1965  * scripts belong to OSs that provide paths to the kernel and initrd files that
1966  * can be used to directly boot
1967  * (http://wiki.qemu.org/download/qemu-doc.html#direct_005flinux_005fboot)
1968  * the OS in order to pass the needed commandline to it.
1969  *
1970  * If you are generating the command line for a specific media, it is
1971  * recommended that you use
1972  * #osinfo_install_script_generate_command_line_for_media() instead.
1973  *
1974  * If you are generating the command line for a specific tree, it is
1975  * recommended that you use
1976  * #osinfo_install_script_generate_command_line_for_tree() instead.
1977  *
1978  * Returns: (transfer full): The generated command line string, NULL otherwise.
1979  *
1980  * Since: 0.2.7
1981  */
osinfo_install_script_generate_command_line(OsinfoInstallScript * script,OsinfoOs * os,OsinfoInstallConfig * config)1982 gchar *osinfo_install_script_generate_command_line(OsinfoInstallScript *script,
1983                                                    OsinfoOs *os,
1984                                                    OsinfoInstallConfig *config)
1985 {
1986     const gchar *templateData = osinfo_install_script_get_template_data(script);
1987     gchar *output = NULL;
1988 
1989     if (templateData) {
1990         GError *error = NULL;
1991         if (!osinfo_install_script_apply_template(script,
1992                                                   os,
1993                                                   NULL,
1994                                                   NULL,
1995                                                   "<data>",
1996                                                   templateData,
1997                                                   "command-line",
1998                                                   &output,
1999                                                   config,
2000                                                   &error)) {
2001             g_prefix_error(&error, "%s", _("Failed to apply script template: "));
2002         }
2003     }
2004 
2005     return output;
2006 }
2007 
2008 /**
2009  * osinfo_install_script_generate_command_line_for_media:
2010  * @script: the install script
2011  * @media:  the media
2012  * @config: the install script config
2013  *
2014  * Some install scripts need to pass a command line to the kernel, Such install
2015  * scripts belong to OSs that provide paths to the kernel and initrd files that
2016  * can be used to directly boot
2017  * (http://wiki.qemu.org/download/qemu-doc.html#direct_005flinux_005fboot)
2018  * the OS in order to pass the needed commandline to it.
2019  *
2020  * The media @media must have been identified successfully using
2021  * #osinfo_db_identify_media() before calling this function.
2022  *
2023  * Returns: (transfer full): The generated command line string, NULL otherwise.
2024  *
2025  * Since: 0.2.12
2026  */
osinfo_install_script_generate_command_line_for_media(OsinfoInstallScript * script,OsinfoMedia * media,OsinfoInstallConfig * config)2027 gchar *osinfo_install_script_generate_command_line_for_media(OsinfoInstallScript *script,
2028                                                              OsinfoMedia *media,
2029                                                              OsinfoInstallConfig *config)
2030 {
2031     const gchar *templateData = osinfo_install_script_get_template_data(script);
2032     gchar *output = NULL;
2033     OsinfoOs *os;
2034 
2035     g_return_val_if_fail(media != NULL, NULL);
2036 
2037     os = osinfo_media_get_os(media);
2038     g_return_val_if_fail(os != NULL, NULL);
2039 
2040     if (templateData) {
2041         GError *error = NULL;
2042         if (!osinfo_install_script_apply_template(script,
2043                                                   os,
2044                                                   media,
2045                                                   NULL,
2046                                                   "<data>",
2047                                                   templateData,
2048                                                   "command-line",
2049                                                   &output,
2050                                                   config,
2051                                                   &error)) {
2052             g_prefix_error(&error, "%s", _("Failed to apply script template: "));
2053         }
2054     }
2055     g_object_unref(os);
2056 
2057     return output;
2058 }
2059 
2060 /**
2061  * osinfo_install_script_generate_command_line_for_tree:
2062  * @script: the install script
2063  * @tree:   the tree
2064  * @config: the install script config
2065  *
2066  * Some install scripts need to pass a command line to the kernel, Such install
2067  * scripts belong to OSs that provide paths to the kernel and initrd files that
2068  * can be used to directly boot
2069  * (http://wiki.qemu.org/download/qemu-doc.html#direct_005flinux_005fboot)
2070  * the OS in order to pass the needed commandline to it.
2071  *
2072  * The tree @tree must have been identified successfully using
2073  * #osinfo_db_identify_tree() before calling this function.
2074  *
2075  * Returns: (transfer full): The generated command line string, NULL otherwise.
2076  *
2077  * Since: 1.6.0
2078  */
osinfo_install_script_generate_command_line_for_tree(OsinfoInstallScript * script,OsinfoTree * tree,OsinfoInstallConfig * config)2079 gchar *osinfo_install_script_generate_command_line_for_tree(OsinfoInstallScript *script,
2080                                                             OsinfoTree *tree,
2081                                                             OsinfoInstallConfig *config)
2082 {
2083     const gchar *templateData = osinfo_install_script_get_template_data(script);
2084     gchar *output = NULL;
2085     OsinfoOs *os;
2086 
2087     g_return_val_if_fail(tree != NULL, NULL);
2088 
2089     os = osinfo_tree_get_os(tree);
2090     g_return_val_if_fail(os != NULL, NULL);
2091 
2092     if (templateData) {
2093         GError *error = NULL;
2094         if (!osinfo_install_script_apply_template(script,
2095                                                   os,
2096                                                   NULL,
2097                                                   tree,
2098                                                   "<data>",
2099                                                   templateData,
2100                                                   "command-line",
2101                                                   &output,
2102                                                   config,
2103                                                   &error)) {
2104             g_prefix_error(&error, "%s", _("Failed to apply script template: "));
2105         }
2106     }
2107     g_object_unref(os);
2108 
2109     return output;
2110 }
2111 
2112 /**
2113  * osinfo_install_script_get_path_format:
2114  * @script: the install script
2115  *
2116  * Returns the path format to be used for the files and disks which will
2117  * be used during the installation.
2118  *
2119  * Returns: the path format to be used. OSINFO_PATH_FORMAT_UNIX is the
2120  *          default option.
2121  *
2122  * Since: 0.2.2
2123  */
osinfo_install_script_get_path_format(OsinfoInstallScript * script)2124 OsinfoPathFormat osinfo_install_script_get_path_format(OsinfoInstallScript *script)
2125 {
2126     return osinfo_entity_get_param_value_enum
2127         (OSINFO_ENTITY(script),
2128          OSINFO_INSTALL_SCRIPT_PROP_PATH_FORMAT,
2129          OSINFO_TYPE_PATH_FORMAT,
2130          OSINFO_PATH_FORMAT_UNIX);
2131 }
2132 
2133 /**
2134  * osinfo_install_script_get_can_pre_install_drivers:
2135  * @script: the install script
2136  *
2137  * Whether install script can install drivers at the very beginning of
2138  * installation. This is needed for devices for which the OS in question does
2139  * not have out of the box support for and devices are required/preferred to be
2140  * available during actual installation.
2141  *
2142  * Returns: TRUE if install script supports pre-installable drivers, FALSE otherwise.
2143  *
2144  * Since: 0.2.2
2145  */
osinfo_install_script_get_can_pre_install_drivers(OsinfoInstallScript * script)2146 gboolean osinfo_install_script_get_can_pre_install_drivers(OsinfoInstallScript *script)
2147 {
2148     return osinfo_entity_get_param_value_boolean
2149         (OSINFO_ENTITY(script),
2150          OSINFO_INSTALL_SCRIPT_PROP_CAN_PRE_INSTALL_DRIVERS);
2151 }
2152 
2153 /**
2154  * osinfo_install_script_get_can_post_install_drivers:
2155  * @script: the install script
2156  *
2157  * Whether install script can install drivers at the very end of installation
2158  * This can be used for installing devices which the OS in question does not
2159  * have out of the box support.
2160  *
2161  * Returns: TRUE if install script supports post-installable drivers, FALSE otherwise.
2162  *
2163  * Since: 0.2.2
2164  */
osinfo_install_script_get_can_post_install_drivers(OsinfoInstallScript * script)2165 gboolean osinfo_install_script_get_can_post_install_drivers(OsinfoInstallScript *script)
2166 {
2167     return osinfo_entity_get_param_value_boolean
2168         (OSINFO_ENTITY(script),
2169          OSINFO_INSTALL_SCRIPT_PROP_CAN_POST_INSTALL_DRIVERS);
2170 }
2171 
2172 /**
2173  * osinfo_install_script_get_pre_install_drivers_signing_req:
2174  * @script: the install script
2175  *
2176  * If install script can install drivers at the very beginning of installation,
2177  * this function retrieves the requirement about signed status of drivers.
2178  *
2179  * Returns: (type OsinfoDeviceDriverSigningReq):
2180  *
2181  * Since: 0.2.6
2182  */
osinfo_install_script_get_pre_install_drivers_signing_req(OsinfoInstallScript * script)2183 int osinfo_install_script_get_pre_install_drivers_signing_req(OsinfoInstallScript *script)
2184 {
2185     return osinfo_entity_get_param_value_enum
2186         (OSINFO_ENTITY(script),
2187          OSINFO_INSTALL_SCRIPT_PROP_PRE_INSTALL_DRIVERS_SIGNING_REQ,
2188          OSINFO_TYPE_DEVICE_DRIVER_SIGNING_REQ,
2189          OSINFO_DEVICE_DRIVER_SIGNING_REQ_NONE);
2190 }
2191 
2192 /**
2193  * osinfo_install_script_get_post_install_drivers_signing_req:
2194  * @script: the install script
2195  *
2196  * If install script can install drivers at the end of installation, this
2197  * function retrieves the requirement about signed status of drivers.
2198  *
2199  * Returns: (type OsinfoDeviceDriverSigningReq):
2200  *
2201  * Since: 0.2.6
2202  */
osinfo_install_script_get_post_install_drivers_signing_req(OsinfoInstallScript * script)2203 int osinfo_install_script_get_post_install_drivers_signing_req(OsinfoInstallScript *script)
2204 {
2205     return osinfo_entity_get_param_value_enum
2206         (OSINFO_ENTITY(script),
2207          OSINFO_INSTALL_SCRIPT_PROP_POST_INSTALL_DRIVERS_SIGNING_REQ,
2208          OSINFO_TYPE_DEVICE_DRIVER_SIGNING_REQ,
2209          OSINFO_DEVICE_DRIVER_SIGNING_REQ_NONE);
2210 }
2211 
2212 /**
2213  * osinfo_install_script_get_injection_methods:
2214  * @script: the install script
2215  *
2216  * Retrieve the supported method to inject the script in to the installation process.
2217  *
2218  * Returns: (type OsinfoInstallScriptInjectionMethod): bitwise-or of
2219  * supported methods for install script injection.
2220  *
2221  * Since: 0.2.10
2222  */
osinfo_install_script_get_injection_methods(OsinfoInstallScript * script)2223 unsigned int osinfo_install_script_get_injection_methods(OsinfoInstallScript *script)
2224 {
2225     return osinfo_entity_get_param_value_int64_with_default
2226         (OSINFO_ENTITY(script),
2227          OSINFO_INSTALL_SCRIPT_PROP_INJECTION_METHOD,
2228          OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_DISK);
2229 }
2230 
2231 /**
2232  * osinfo_install_script_get_needs_internet:
2233  * @script: the install script
2234  *
2235  * Some install scripts cannot ensure that they work without an internet connection.
2236  *
2237  * Returns: TRUE if script needs an internet connection, FALSE otherwise
2238  * internet connection.
2239  *
2240  * Since: 0.2.11
2241  */
osinfo_install_script_get_needs_internet(OsinfoInstallScript * script)2242 gboolean osinfo_install_script_get_needs_internet(OsinfoInstallScript *script)
2243 {
2244     return osinfo_entity_get_param_value_boolean_with_default
2245         (OSINFO_ENTITY(script),
2246          OSINFO_INSTALL_SCRIPT_PROP_NEEDS_INTERNET,
2247          FALSE);
2248 }
2249 
2250 /**
2251  * osinfo_install_script_set_preferred_injection_method:
2252  * @script: the install script
2253  * @method: one of the injection methods:
2254  * OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_CDROM,
2255  * OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_DISK,
2256  * OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_FLOPPY,
2257  * OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_INITRD,
2258  * OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_WEB
2259  *
2260  * Set the preferred injection method to be used with the @script
2261  *
2262  * Since: 1.3.0
2263  */
osinfo_install_script_set_preferred_injection_method(OsinfoInstallScript * script,OsinfoInstallScriptInjectionMethod method)2264 void osinfo_install_script_set_preferred_injection_method(OsinfoInstallScript *script,
2265                                                           OsinfoInstallScriptInjectionMethod method)
2266 {
2267     GFlagsClass *flags_class;
2268     guint i;
2269 
2270     flags_class = g_type_class_ref(OSINFO_TYPE_INSTALL_SCRIPT_INJECTION_METHOD);
2271     for (i = 0; i < flags_class->n_values; i++) {
2272         if ((flags_class->values[i].value & method) != 0) {
2273             osinfo_entity_set_param(OSINFO_ENTITY(script),
2274                                     OSINFO_INSTALL_SCRIPT_PROP_PREFERRED_INJECTION_METHOD,
2275                                     flags_class->values[i].value_nick);
2276             break;
2277         }
2278     }
2279     g_type_class_unref(flags_class);
2280 }
2281 
2282 /**
2283  * osinfo_install_script_get_preferred_injection_method:
2284  * @script: the install script
2285  *
2286  * Returns: the preferred injection method for the script. If none is set and
2287  * OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_DISK is supported,
2288  * OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_DISK is returned, otherwise
2289  * OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_INITRD is returned.
2290  *
2291  * Since: 1.3.0
2292  */
2293 OsinfoInstallScriptInjectionMethod
osinfo_install_script_get_preferred_injection_method(OsinfoInstallScript * script)2294 osinfo_install_script_get_preferred_injection_method(OsinfoInstallScript *script)
2295 {
2296     GFlagsClass *flags_class;
2297     GFlagsValue *value;
2298     const gchar *nick;
2299     guint supported_methods;
2300 
2301     nick = osinfo_entity_get_param_value(OSINFO_ENTITY(script),
2302             OSINFO_INSTALL_SCRIPT_PROP_PREFERRED_INJECTION_METHOD);
2303 
2304     if (nick == NULL) {
2305         supported_methods = osinfo_install_script_get_injection_methods(script);
2306         if ((supported_methods & OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_DISK) != 0)
2307             return OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_DISK;
2308         else if ((supported_methods & OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_INITRD) != 0)
2309             return OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_INITRD;
2310         else
2311             return OSINFO_INSTALL_SCRIPT_INJECTION_METHOD_DISK;
2312     }
2313 
2314     flags_class = g_type_class_ref(OSINFO_TYPE_INSTALL_SCRIPT_INJECTION_METHOD);
2315     value = g_flags_get_value_by_nick(flags_class, nick);
2316     g_type_class_unref(flags_class);
2317 
2318     return value->value;
2319 }
2320 
2321 /**
2322  * osinfo_install_script_set_installation_source:
2323  * @script: the install script
2324  * @source: one of the installation sources:
2325  * OSINFO_INSTALL_SCRIPT_INSTALLATION_SOURCE_MEDIA,
2326  * OSINFO_INSTALL_SCRIPT_INSTALLATION_SOURCE_NETWORK
2327  *
2328  * Set the installation source to be used with the @script.
2329  *
2330  * Since: 1.3.0
2331  */
osinfo_install_script_set_installation_source(OsinfoInstallScript * script,OsinfoInstallScriptInstallationSource source)2332 void osinfo_install_script_set_installation_source(OsinfoInstallScript *script,
2333                                                    OsinfoInstallScriptInstallationSource source)
2334 {
2335     osinfo_entity_set_param_enum(OSINFO_ENTITY(script),
2336             OSINFO_INSTALL_SCRIPT_PROP_INSTALLATION_SOURCE,
2337             source,
2338             OSINFO_TYPE_INSTALL_SCRIPT_INSTALLATION_SOURCE);
2339 }
2340 
2341 /**
2342  * osinfo_install_script_get_installation_source:
2343  * @script: the install script
2344  *
2345  * Returns: the installation source to be used with the script. If none is set, it defaults to
2346  * OSINFO_INSTALL_SCRIPT_INSTALLATION_SOURCE_MEDIA.
2347  *
2348  * Since: 1.3.0
2349  */
2350 OsinfoInstallScriptInstallationSource
osinfo_install_script_get_installation_source(OsinfoInstallScript * script)2351 osinfo_install_script_get_installation_source(OsinfoInstallScript *script)
2352 {
2353     return osinfo_entity_get_param_value_enum(OSINFO_ENTITY(script),
2354             OSINFO_INSTALL_SCRIPT_PROP_INSTALLATION_SOURCE,
2355             OSINFO_TYPE_INSTALL_SCRIPT_INSTALLATION_SOURCE,
2356             OSINFO_INSTALL_SCRIPT_INSTALLATION_SOURCE_MEDIA);
2357 }
2358