Pino Toscano
2015-Jul-08 14:42 UTC
[Libguestfs] [PATCH 0/6] RFC: basic subscription-manager support in virt-customize
Hi, this series introduces a basic support for registering/attaching/unregistering RHEL guests using subscription-manager, so it is possible to do for example: $ cat <<EOF > sm.conf [general] username=user password=pass [attach-0] pool=ID EOF $ virt-customize -a rhel-guest.qcow2 \ --sm-config sm.conf --sm-register --sm-attach 0 \ --install pkg1 --install pkg2 .. \ --sm-remove --sm-unregister The same operations are doable also using --run-command, but this avoids showing username/passwords/pools on command lines, and in general encapsulate them for better control. Thanks, -- Pino Pino Toscano (6): Move ini_reader from builder to mllib mllib: add a real_uri parameter to Ini_reader.read_ini mllib: add duplicate fields check to Ini_reader.read_ini mllib: add duplicate sections check to Ini_reader.read_ini mllib: add quick section/key lookup method customize: add basic subscription-manager operations .gitignore | 6 +- builder/Makefile.am | 40 ++++------- builder/index-parse.y | 176 --------------------------------------------- builder/index-parser-c.c | 121 ------------------------------- builder/index-scan.l | 144 ------------------------------------- builder/index-struct.c | 60 ---------------- builder/index-struct.h | 67 ----------------- builder/index_parser.ml | 22 +----- builder/ini_reader.ml | 40 ----------- builder/ini_reader.mli | 24 ------- builder/sources.ml | 3 +- customize/Makefile.am | 8 ++- customize/customize_run.ml | 58 +++++++++++++++ generator/customize.ml | 101 ++++++++++++++++++++++++++ mllib/Makefile.am | 16 ++++- mllib/index-parse.y | 176 +++++++++++++++++++++++++++++++++++++++++++++ mllib/index-parser-c.c | 121 +++++++++++++++++++++++++++++++ mllib/index-scan.l | 144 +++++++++++++++++++++++++++++++++++++ mllib/index-struct.c | 60 ++++++++++++++++ mllib/index-struct.h | 67 +++++++++++++++++ mllib/ini_reader.ml | 98 +++++++++++++++++++++++++ mllib/ini_reader.mli | 29 ++++++++ po/POTFILES | 8 +-- po/POTFILES-ml | 2 +- sysprep/Makefile.am | 8 ++- 25 files changed, 908 insertions(+), 691 deletions(-) delete mode 100644 builder/index-parse.y delete mode 100644 builder/index-parser-c.c delete mode 100644 builder/index-scan.l delete mode 100644 builder/index-struct.c delete mode 100644 builder/index-struct.h delete mode 100644 builder/ini_reader.ml delete mode 100644 builder/ini_reader.mli create mode 100644 mllib/index-parse.y create mode 100644 mllib/index-parser-c.c create mode 100644 mllib/index-scan.l create mode 100644 mllib/index-struct.c create mode 100644 mllib/index-struct.h create mode 100644 mllib/ini_reader.ml create mode 100644 mllib/ini_reader.mli -- 2.1.0
Pino Toscano
2015-Jul-08 14:42 UTC
[Libguestfs] [PATCH 1/6] Move ini_reader from builder to mllib
Move the C INI reader and its OCaml binding from builder to mllib, so it can be used also elsewhere. --- .gitignore | 6 +- builder/Makefile.am | 40 ++++------- builder/index-parse.y | 176 ----------------------------------------------- builder/index-parser-c.c | 121 -------------------------------- builder/index-scan.l | 144 -------------------------------------- builder/index-struct.c | 60 ---------------- builder/index-struct.h | 67 ------------------ builder/ini_reader.ml | 40 ----------- builder/ini_reader.mli | 24 ------- mllib/Makefile.am | 16 ++++- mllib/index-parse.y | 176 +++++++++++++++++++++++++++++++++++++++++++++++ mllib/index-parser-c.c | 121 ++++++++++++++++++++++++++++++++ mllib/index-scan.l | 144 ++++++++++++++++++++++++++++++++++++++ mllib/index-struct.c | 60 ++++++++++++++++ mllib/index-struct.h | 67 ++++++++++++++++++ mllib/ini_reader.ml | 40 +++++++++++ mllib/ini_reader.mli | 24 +++++++ po/POTFILES | 8 +-- po/POTFILES-ml | 2 +- 19 files changed, 668 insertions(+), 668 deletions(-) delete mode 100644 builder/index-parse.y delete mode 100644 builder/index-parser-c.c delete mode 100644 builder/index-scan.l delete mode 100644 builder/index-struct.c delete mode 100644 builder/index-struct.h delete mode 100644 builder/ini_reader.ml delete mode 100644 builder/ini_reader.mli create mode 100644 mllib/index-parse.y create mode 100644 mllib/index-parser-c.c create mode 100644 mllib/index-scan.l create mode 100644 mllib/index-struct.c create mode 100644 mllib/index-struct.h create mode 100644 mllib/ini_reader.ml create mode 100644 mllib/ini_reader.mli diff --git a/.gitignore b/.gitignore index 6089122..8aded3b 100644 --- a/.gitignore +++ b/.gitignore @@ -55,9 +55,6 @@ Makefile.in /bash/virt-sparsify /build-aux /builder/.depend -/builder/index-parse.c -/builder/index-parse.h -/builder/index-scan.c /builder/libguestfs.conf /builder/*.qcow2 /builder/stamp-virt-builder.pod @@ -312,6 +309,9 @@ Makefile.in /mllib/common_utils_tests /mllib/config.ml /mllib/dummy +/mllib/index-parse.c +/mllib/index-parse.h +/mllib/index-scan.c /mllib/JSON_tests /mllib/libdir.ml /mllib/oUnit-* diff --git a/builder/Makefile.am b/builder/Makefile.am index d69e25f..1d9ad54 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am @@ -17,8 +17,6 @@ include $(top_srcdir)/subdir-rules.mk -AM_YFLAGS = -d - EXTRA_DIST = \ $(SOURCES_MLI) $(SOURCES_ML) $(SOURCES_C) \ libguestfs.gpg \ @@ -40,7 +38,6 @@ SOURCES_MLI = \ cache.mli \ downloader.mli \ index_parser.mli \ - ini_reader.mli \ languages.mli \ list_entries.mli \ pxzcat.mli \ @@ -52,7 +49,6 @@ SOURCES_ML = \ utils.ml \ pxzcat.ml \ setlocale.ml \ - ini_reader.ml \ paths.ml \ languages.ml \ cache.ml \ @@ -68,14 +64,14 @@ SOURCES_C = \ $(top_srcdir)/mllib/fsync-c.c \ $(top_srcdir)/mllib/uri-c.c \ $(top_srcdir)/mllib/mkdtemp-c.c \ + $(top_srcdir)/mllib/index-parse.c \ + $(top_srcdir)/mllib/index-parser-c.c \ + $(top_srcdir)/mllib/index-scan.c \ + $(top_srcdir)/mllib/index-struct.c \ $(top_srcdir)/customize/perl_edit-c.c \ $(top_srcdir)/customize/crypt-c.c \ $(top_srcdir)/fish/uri.c \ $(top_srcdir)/fish/file-edit.c \ - index-scan.c \ - index-struct.c \ - index-parse.c \ - index-parser-c.c \ pxzcat-c.c \ setlocale-c.c @@ -95,7 +91,8 @@ virt_builder_CPPFLAGS = \ -I$(shell $(OCAMLC) -where) \ -I$(top_srcdir)/gnulib/lib \ -I$(top_srcdir)/src \ - -I$(top_srcdir)/fish + -I$(top_srcdir)/fish \ + -I$(top_srcdir)/mllib virt_builder_CFLAGS = \ -pthread \ $(WARN_CFLAGS) $(WERROR_CFLAGS) \ @@ -115,6 +112,7 @@ BOBJECTS = \ $(top_builddir)/mllib/JSON.cmo \ $(top_builddir)/mllib/uRI.cmo \ $(top_builddir)/mllib/mkdtemp.cmo \ + $(top_builddir)/mllib/ini_reader.cmo \ $(top_builddir)/customize/customize_utils.cmo \ $(top_builddir)/customize/urandom.cmo \ $(top_builddir)/customize/random_seed.cmo \ @@ -273,10 +271,10 @@ install-exec-hook: bin_PROGRAMS += virt-index-validate virt_index_validate_SOURCES = \ - index-parse.y \ - index-scan.l \ - index-struct.h \ - index-struct.c \ + $(top_srcdir)/mllib/index-parse.c \ + $(top_srcdir)/mllib/index-scan.c \ + $(top_srcdir)/mllib/index-struct.h \ + $(top_srcdir)/mllib/index-struct.c \ index-validate.c virt_index_validate_CPPFLAGS = \ @@ -284,7 +282,8 @@ virt_index_validate_CPPFLAGS = \ -I. \ -I$(top_builddir) \ -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \ - -I$(top_srcdir)/src + -I$(top_srcdir)/src \ + -I$(top_srcdir)/mllib virt_index_validate_CFLAGS = \ $(WARN_CFLAGS) $(WERROR_CFLAGS) \ -Wno-unused-macros @@ -306,21 +305,8 @@ stamp-virt-index-validate.pod: virt-index-validate.pod touch $@ CLEANFILES += \ - index-parse.c \ - index-parse.h \ - index-scan.c \ stamp-virt-index-validate.pod -if HAVE_OCAML -# Automake-generated makefile has a rule ".y.c" but lacks a rule ".y.h". -index-parse.h: index-parse.y - touch $(srcdir)/index-parse.y - $(MAKE) index-parse.c -# Also it doesn't generate dependencies for the C files that include -# index-parse.h. -index-parser-c.c index-scan.c index-validate.c: index-parse.h -endif - # Apparently there's no clean way with Automake to not have them # in the distribution, so just remove them from the distdir. dist-hook: diff --git a/builder/index-parse.y b/builder/index-parse.y deleted file mode 100644 index 82ea9d2..0000000 --- a/builder/index-parse.y +++ /dev/null @@ -1,176 +0,0 @@ -/* libguestfs virt-builder tool -*- fundamental -*- - * Copyright (C) 2013 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -%{ -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "index-struct.h" -#include "index-parse.h" - -#define YY_EXTRA_TYPE struct parse_context * - -extern void yyerror (YYLTYPE * yylloc, yyscan_t scanner, struct parse_context *context, const char *msg); -extern int yylex (YYSTYPE * yylval, YYLTYPE * yylloc, yyscan_t scanner); - -extern int do_parse (struct parse_context *context, FILE *in); -extern void scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in); -extern void scanner_destroy (yyscan_t scanner); - -/* Join two strings with \n */ -static char * -concat_newline (const char *str1, const char *str2) -{ - size_t len1, len2, len; - char *ret; - - if (str2 == NULL) - return strdup (str1); - - len1 = strlen (str1); - len2 = strlen (str2); - len = len1 + 1 /* \n */ + len2 + 1 /* \0 */; - ret = malloc (len); - memcpy (ret, str1, len1); - ret[len1] = '\n'; - memcpy (ret + len1 + 1, str2, len2); - ret[len-1] = '\0'; - - return ret; -} - -%} - -%code requires { -#ifndef YY_TYPEDEF_YY_SCANNER_T -#define YY_TYPEDEF_YY_SCANNER_T -typedef void *yyscan_t; -#endif -} - -%locations - -%union { - struct section *section; - struct field *field; - char *str; -} - -%token <str> SECTION_HEADER -%token <field> FIELD -%token <str> VALUE_CONT -%token EMPTY_LINE -%token PGP_PROLOGUE -%token PGP_EPILOGUE -%token UNKNOWN_LINE - -%type <section> sections section -%type <field> fields field -%type <str> continuations - -%pure-parser - -%lex-param { yyscan_t scanner } -%parse-param { yyscan_t scanner } -%parse-param { struct parse_context *context } - -%destructor { section_free ($$); } <section> -%destructor { field_free ($$); } <field> - -%% - -index: - sections - { context->parsed_index = $1; } - | PGP_PROLOGUE sections PGP_EPILOGUE - { context->parsed_index = $2; } - -sections: - emptylines section emptylines - { $$ = $2; } - | emptylines section EMPTY_LINE emptylines sections - { $$ = $2; $$->next = $5; } - | emptylines - { $$ = NULL; } - -section: - SECTION_HEADER fields - { $$ = malloc (sizeof (struct section)); - $$->next = NULL; - $$->name = $1; - $$->fields = $2; } - -fields: - /* empty */ - { $$ = NULL; } - | field fields - { $$ = $1; $$->next = $2; } - -field: FIELD continuations - { $$ = $1; - char *old_value = $$->value; - $$->value = concat_newline (old_value, $2); - free (old_value); - free ($2); } - -continuations: - /* empty */ - { $$ = NULL; } - | VALUE_CONT continuations - { $$ = concat_newline ($1, $2); - free ($1); - free ($2); } - -emptylines: - /* empty */ - {} - | EMPTY_LINE emptylines - {} - -%% - -void -yyerror (YYLTYPE * yylloc, yyscan_t scanner, struct parse_context *context, const char *msg) -{ - int has_suffix = context->error_suffix != NULL && context->error_suffix[0] != 0; - - fprintf (stderr, "%s%s%s%ssyntax error at line %d: %s%s%s\n", - context->progname ? context->progname : "", - context->progname ? ": " : "", - context->input_file ? context->input_file : "", - context->input_file ? ": " : "", - yylloc->first_line, msg, - has_suffix ? " " : "", - has_suffix ? context->error_suffix : ""); -} - -int -do_parse (struct parse_context *context, FILE *in) -{ - yyscan_t scanner; - int res; - - scanner_init (&scanner, context, in); - res = yyparse (scanner, context); - scanner_destroy (scanner); - - return res; -} diff --git a/builder/index-parser-c.c b/builder/index-parser-c.c deleted file mode 100644 index 52c8b86..0000000 --- a/builder/index-parser-c.c +++ /dev/null @@ -1,121 +0,0 @@ -/* virt-builder - * Copyright (C) 2013 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/* This file handles the interface between the C/lex/yacc index file - * parser, and the OCaml world. See index_parser.ml for the OCaml - * type definition. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> - -#include <caml/alloc.h> -#include <caml/fail.h> -#include <caml/memory.h> -#include <caml/mlvalues.h> - -#ifdef HAVE_CAML_UNIXSUPPORT_H -#include <caml/unixsupport.h> -#else -#define Nothing ((value) 0) -extern void unix_error (int errcode, char * cmdname, value arg) Noreturn; -#endif - -#include "index-struct.h" -#include "index-parse.h" - -extern int do_parse (struct parse_context *context, FILE *in); - -extern value virt_builder_parse_index (value progv, value error_suffixv, value filenamev); - -value -virt_builder_parse_index (value progv, value error_suffixv, value filenamev) -{ - CAMLparam2 (progv, filenamev); - CAMLlocal5 (rv, v, sv, sv2, fv); - struct section *sections; - size_t i, nr_sections; - struct parse_context context; - FILE *in; - - parse_context_init (&context); - context.progname = String_val (progv); - context.input_file = String_val (filenamev); - context.error_suffix = String_val (error_suffixv); - - in = fopen (String_val (filenamev), "r"); - if (in == NULL) - unix_error (errno, (char *) "fopen", filenamev); - - if (do_parse (&context, in) != 0) { - fclose (in); - caml_invalid_argument ("parse error"); - } - - if (fclose (in) == EOF) - unix_error (errno, (char *) "fclose", filenamev); - - /* Convert the parsed data to OCaml structures. */ - nr_sections = 0; - for (sections = context.parsed_index; sections != NULL; sections = sections->next) - nr_sections++; - rv = caml_alloc (nr_sections, 0); - - for (i = 0, sections = context.parsed_index; sections != NULL; - i++, sections = sections->next) { - struct field *fields; - size_t j, nr_fields; - - nr_fields = 0; - for (fields = sections->fields; fields != NULL; fields = fields->next) - nr_fields++; - fv = caml_alloc (nr_fields, 0); - - for (j = 0, fields = sections->fields; fields != NULL; - j++, fields = fields->next) { - v = caml_alloc_tuple (3); - sv = caml_copy_string (fields->key); - Store_field (v, 0, sv); /* (key, Some subkey, value) */ - if (fields->subkey) { - sv2 = caml_copy_string (fields->subkey); - sv = caml_alloc (1, 0); - Store_field (sv, 0, sv2); - } else - sv = Val_int (0); - Store_field (v, 1, sv); - sv = caml_copy_string (fields->value); - Store_field (v, 2, sv); - Store_field (fv, j, v); /* assign to return array of fields */ - } - - v = caml_alloc_tuple (2); - sv = caml_copy_string (sections->name); - Store_field (v, 0, sv); /* (name, fields) */ - Store_field (v, 1, fv); - Store_field (rv, i, v); /* assign to return array of sections */ - } - - /* Free parsed data. */ - parse_context_free (&context); - - CAMLreturn (rv); -} diff --git a/builder/index-scan.l b/builder/index-scan.l deleted file mode 100644 index 7125913..0000000 --- a/builder/index-scan.l +++ /dev/null @@ -1,144 +0,0 @@ -/* libguestfs virt-builder tool -*- fundamental -*- - * Copyright (C) 2013 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -%top{ -#include <config.h> -} - -%{ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* Silence gcc warnings from the generated code. */ -#if defined(__GNUC__) -#pragma GCC diagnostic push -/* flex creates macros that it doesn't use */ -#pragma GCC diagnostic ignored "-Wunused-macros" -/* on aarch64, flex doesn't know that char is unsigned */ -#pragma GCC diagnostic ignored "-Wsign-compare" -/* on debian-mipsel, flex doesn't create prototypes for all functions */ -#pragma GCC diagnostic ignored "-Wmissing-prototypes" -#endif - -#include "index-struct.h" -#include "index-parse.h" - -#define YY_EXTRA_TYPE struct parse_context * -#define YY_USER_ACTION yylloc->first_line = yylloc->last_line = yylineno; - -extern void scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in); -extern void scanner_destroy (yyscan_t scanner); - -%} - -%option nounput -%option noyywrap -%option yylineno -%option reentrant -%option bison-bridge -%option bison-locations - -%% - - /* Apart from the PGP prologue/epilogue which is a hack, the - * scanning strategy is to deal with the file strictly line by - * line, and pass those lines up to the parser which deals with - * whether they appear in the right order to be meaningful. - * Note that flex does longest-match. - */ - - /* Ignore comments - '#' MUST appear at the start of a line. */ -^"#".*\n { yyextra->seen_comments++; } - - /* An empty line is significant. */ -^\n { return EMPTY_LINE; } - - /* [...] marks beginning of a section. */ -^"["[-A-Za-z0-9._]+"]"\n { - yylval->str = strndup (yytext+1, yyleng-3); - return SECTION_HEADER; - } - - /* field=value or field[subfield]=value */ -^[A-Za-z0-9_.]+("["[A-Za-z0-9_,.]+"]")?"=".*\n { - size_t i = strcspn (yytext, "=["); - yylval->field = malloc (sizeof (struct field)); - yylval->field->next = NULL; - yylval->field->key = strndup (yytext, i); - if (yytext[i] == '[') { - size_t j = strcspn (yytext+i+1, "]"); - yylval->field->subkey = strndup (yytext+i+1, j); - i += 1+j+1; - } else { - yylval->field->subkey = NULL; - } - /* Note we chop the final \n off here. */ - yylval->field->value = strndup (yytext+i+1, yyleng-(i+2)); - return FIELD; - } - - /* Continuation line for multi-line values. */ -^[[:blank:]].*\n { - yylval->str = strndup (yytext+1, yyleng-2); - return VALUE_CONT; - } - - /* Hack to eat the PGP prologue. */ -^"-----BEGIN PGP SIGNED MESSAGE-----\n" { - int c, prevnl = 0; - - /* Eat everything to the first blank line. */ - while ((c = input (yyscanner)) != EOF) { - if (c == '\n' && prevnl) - break; - prevnl = c == '\n'; - } - - return PGP_PROLOGUE; -} - - /* Hack to eat the PGP epilogue. */ -^"-----BEGIN PGP SIGNATURE-----\n" { - /* Eat everything to the end of the file. */ - while (input (yyscanner) != EOF) - ; - - return PGP_EPILOGUE; -} - - /* anything else is an error */ -. { - return UNKNOWN_LINE; -} - -%% - -void -scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in) -{ - yylex_init (scanner); - yyset_extra (context, *scanner); - yyset_in (in, *scanner); -} - -void -scanner_destroy (yyscan_t scanner) -{ - yylex_destroy (scanner); -} diff --git a/builder/index-struct.c b/builder/index-struct.c deleted file mode 100644 index eacca6c..0000000 --- a/builder/index-struct.c +++ /dev/null @@ -1,60 +0,0 @@ -/* libguestfs virt-builder tool - * Copyright (C) 2013 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "index-struct.h" - -void -parse_context_init (struct parse_context *context) -{ - memset (context, 0, sizeof *context); -} - -void -parse_context_free (struct parse_context *context) -{ - section_free (context->parsed_index); -} - -void -section_free (struct section *section) -{ - if (section) { - section_free (section->next); - free (section->name); - field_free (section->fields); - free (section); - } -} - -void -field_free (struct field *field) -{ - if (field) { - field_free (field->next); - free (field->key); - free (field->subkey); - free (field->value); - free (field); - } -} diff --git a/builder/index-struct.h b/builder/index-struct.h deleted file mode 100644 index ada35e3..0000000 --- a/builder/index-struct.h +++ /dev/null @@ -1,67 +0,0 @@ -/* libguestfs virt-builder tool - * Copyright (C) 2013 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/* The data structures produced when parsing the index file. */ - -#ifndef INDEX_STRUCT_H -#define INDEX_STRUCT_H - -/* A section or list of sections. */ -struct section { - struct section *next; - char *name; - struct field *fields; -}; - -/* A field or list of fields. */ -struct field { - struct field *next; - char *key; - char *subkey; - char *value; -}; - -/* A struct holding the data needed during the parsing. */ -struct parse_context { - struct section *parsed_index; /* The result of the parsing. */ - /* yyparse sets this if any comments were seen. Required for checking - * compatibility with virt-builder 1.24. - */ - int seen_comments; - const char *input_file; - const char *progname; - const char *error_suffix; -}; - -/* Initialize the content of a parse_context. */ -extern void parse_context_init (struct parse_context *state); - -/* Free the content of a parse_context. The actual pointer is not freed. */ -extern void parse_context_free (struct parse_context *state); - -/* Free the content of a section, recursively freeing also its fields. - * The actual pointer is not freed. - */ -extern void section_free (struct section *section); - -/* Free the content of a field, recursively freeing also its next field. - * The actual pointer is not freed. - */ -extern void field_free (struct field *field); - -#endif /* INDEX_STRUCT_H */ diff --git a/builder/ini_reader.ml b/builder/ini_reader.ml deleted file mode 100644 index 50a06f9..0000000 --- a/builder/ini_reader.ml +++ /dev/null @@ -1,40 +0,0 @@ -(* virt-builder - * Copyright (C) 2013-2015 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - *) - -open Common_utils - -type sections = section list -and section = string * fields (* [name] + fields *) -and fields = field list -and field = string * string option * string (* key + subkey + value *) - -(* Types returned by the C index parser. *) -type c_sections = c_section array -and c_section = string * c_fields (* [name] + fields *) -and c_fields = field array - -(* Calls yyparse in the C code. *) -external parse_index : prog:string -> error_suffix:string -> string -> c_sections = "virt_builder_parse_index" - -let read_ini ?(error_suffix = "") file - let sections = parse_index ~prog ~error_suffix file in - let sections = Array.to_list sections in - List.map ( - fun (n, fields) -> - n, Array.to_list fields - ) sections diff --git a/builder/ini_reader.mli b/builder/ini_reader.mli deleted file mode 100644 index 62567e8..0000000 --- a/builder/ini_reader.mli +++ /dev/null @@ -1,24 +0,0 @@ -(* virt-builder - * Copyright (C) 2013-2015 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - *) - -type sections = section list -and section = string * fields (* [name] + fields *) -and fields = field list -and field = string * string option * string (* key + subkey + value *) - -val read_ini : ?error_suffix:string -> string -> sections diff --git a/mllib/Makefile.am b/mllib/Makefile.am index 272c981..f7f3a66 100644 --- a/mllib/Makefile.am +++ b/mllib/Makefile.am @@ -17,6 +17,8 @@ include $(top_srcdir)/subdir-rules.mk +AM_YFLAGS = -d + EXTRA_DIST = \ $(SOURCES_MLI) \ $(filter-out config.ml libdir.ml,$(SOURCES_ML)) \ @@ -29,6 +31,7 @@ CLEANFILES = *~ *.annot *.cmi *.cmo *.cmx *.cmxa *.o SOURCES_MLI = \ common_utils.mli \ fsync.mli \ + ini_reader.mli \ JSON.mli \ mkdtemp.mli \ planner.mli \ @@ -42,6 +45,7 @@ SOURCES_ML = \ common_gettext.ml \ common_utils.ml \ fsync.ml \ + ini_reader.ml \ progress.ml \ uRI.ml \ mkdtemp.ml \ @@ -53,6 +57,10 @@ SOURCES_C = \ $(top_srcdir)/fish/progress.c \ $(top_srcdir)/fish/uri.c \ fsync-c.c \ + index-scan.l \ + index-struct.c \ + index-parse.y \ + index-parser-c.c \ mkdtemp-c.c \ progress-c.c \ uri-c.c @@ -74,7 +82,8 @@ dummy_CPPFLAGS = \ -I$(top_srcdir)/fish dummy_CFLAGS = \ $(WARN_CFLAGS) $(WERROR_CFLAGS) \ - $(LIBVIRT_CFLAGS) $(LIBXML2_CFLAGS) + $(LIBVIRT_CFLAGS) $(LIBXML2_CFLAGS) \ + -Wno-unused-macros BOBJECTS = $(SOURCES_ML:.ml=.cmo) XOBJECTS = $(BOBJECTS:.cmo=.cmx) @@ -213,6 +222,11 @@ depend: .depend endif +CLEANFILES += \ + index-parse.c \ + index-parse.h \ + index-scan.c + DISTCLEANFILES = .depend .PHONY: depend docs diff --git a/mllib/index-parse.y b/mllib/index-parse.y new file mode 100644 index 0000000..82ea9d2 --- /dev/null +++ b/mllib/index-parse.y @@ -0,0 +1,176 @@ +/* libguestfs virt-builder tool -*- fundamental -*- + * Copyright (C) 2013 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +%{ +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "index-struct.h" +#include "index-parse.h" + +#define YY_EXTRA_TYPE struct parse_context * + +extern void yyerror (YYLTYPE * yylloc, yyscan_t scanner, struct parse_context *context, const char *msg); +extern int yylex (YYSTYPE * yylval, YYLTYPE * yylloc, yyscan_t scanner); + +extern int do_parse (struct parse_context *context, FILE *in); +extern void scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in); +extern void scanner_destroy (yyscan_t scanner); + +/* Join two strings with \n */ +static char * +concat_newline (const char *str1, const char *str2) +{ + size_t len1, len2, len; + char *ret; + + if (str2 == NULL) + return strdup (str1); + + len1 = strlen (str1); + len2 = strlen (str2); + len = len1 + 1 /* \n */ + len2 + 1 /* \0 */; + ret = malloc (len); + memcpy (ret, str1, len1); + ret[len1] = '\n'; + memcpy (ret + len1 + 1, str2, len2); + ret[len-1] = '\0'; + + return ret; +} + +%} + +%code requires { +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void *yyscan_t; +#endif +} + +%locations + +%union { + struct section *section; + struct field *field; + char *str; +} + +%token <str> SECTION_HEADER +%token <field> FIELD +%token <str> VALUE_CONT +%token EMPTY_LINE +%token PGP_PROLOGUE +%token PGP_EPILOGUE +%token UNKNOWN_LINE + +%type <section> sections section +%type <field> fields field +%type <str> continuations + +%pure-parser + +%lex-param { yyscan_t scanner } +%parse-param { yyscan_t scanner } +%parse-param { struct parse_context *context } + +%destructor { section_free ($$); } <section> +%destructor { field_free ($$); } <field> + +%% + +index: + sections + { context->parsed_index = $1; } + | PGP_PROLOGUE sections PGP_EPILOGUE + { context->parsed_index = $2; } + +sections: + emptylines section emptylines + { $$ = $2; } + | emptylines section EMPTY_LINE emptylines sections + { $$ = $2; $$->next = $5; } + | emptylines + { $$ = NULL; } + +section: + SECTION_HEADER fields + { $$ = malloc (sizeof (struct section)); + $$->next = NULL; + $$->name = $1; + $$->fields = $2; } + +fields: + /* empty */ + { $$ = NULL; } + | field fields + { $$ = $1; $$->next = $2; } + +field: FIELD continuations + { $$ = $1; + char *old_value = $$->value; + $$->value = concat_newline (old_value, $2); + free (old_value); + free ($2); } + +continuations: + /* empty */ + { $$ = NULL; } + | VALUE_CONT continuations + { $$ = concat_newline ($1, $2); + free ($1); + free ($2); } + +emptylines: + /* empty */ + {} + | EMPTY_LINE emptylines + {} + +%% + +void +yyerror (YYLTYPE * yylloc, yyscan_t scanner, struct parse_context *context, const char *msg) +{ + int has_suffix = context->error_suffix != NULL && context->error_suffix[0] != 0; + + fprintf (stderr, "%s%s%s%ssyntax error at line %d: %s%s%s\n", + context->progname ? context->progname : "", + context->progname ? ": " : "", + context->input_file ? context->input_file : "", + context->input_file ? ": " : "", + yylloc->first_line, msg, + has_suffix ? " " : "", + has_suffix ? context->error_suffix : ""); +} + +int +do_parse (struct parse_context *context, FILE *in) +{ + yyscan_t scanner; + int res; + + scanner_init (&scanner, context, in); + res = yyparse (scanner, context); + scanner_destroy (scanner); + + return res; +} diff --git a/mllib/index-parser-c.c b/mllib/index-parser-c.c new file mode 100644 index 0000000..52c8b86 --- /dev/null +++ b/mllib/index-parser-c.c @@ -0,0 +1,121 @@ +/* virt-builder + * Copyright (C) 2013 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* This file handles the interface between the C/lex/yacc index file + * parser, and the OCaml world. See index_parser.ml for the OCaml + * type definition. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> + +#include <caml/alloc.h> +#include <caml/fail.h> +#include <caml/memory.h> +#include <caml/mlvalues.h> + +#ifdef HAVE_CAML_UNIXSUPPORT_H +#include <caml/unixsupport.h> +#else +#define Nothing ((value) 0) +extern void unix_error (int errcode, char * cmdname, value arg) Noreturn; +#endif + +#include "index-struct.h" +#include "index-parse.h" + +extern int do_parse (struct parse_context *context, FILE *in); + +extern value virt_builder_parse_index (value progv, value error_suffixv, value filenamev); + +value +virt_builder_parse_index (value progv, value error_suffixv, value filenamev) +{ + CAMLparam2 (progv, filenamev); + CAMLlocal5 (rv, v, sv, sv2, fv); + struct section *sections; + size_t i, nr_sections; + struct parse_context context; + FILE *in; + + parse_context_init (&context); + context.progname = String_val (progv); + context.input_file = String_val (filenamev); + context.error_suffix = String_val (error_suffixv); + + in = fopen (String_val (filenamev), "r"); + if (in == NULL) + unix_error (errno, (char *) "fopen", filenamev); + + if (do_parse (&context, in) != 0) { + fclose (in); + caml_invalid_argument ("parse error"); + } + + if (fclose (in) == EOF) + unix_error (errno, (char *) "fclose", filenamev); + + /* Convert the parsed data to OCaml structures. */ + nr_sections = 0; + for (sections = context.parsed_index; sections != NULL; sections = sections->next) + nr_sections++; + rv = caml_alloc (nr_sections, 0); + + for (i = 0, sections = context.parsed_index; sections != NULL; + i++, sections = sections->next) { + struct field *fields; + size_t j, nr_fields; + + nr_fields = 0; + for (fields = sections->fields; fields != NULL; fields = fields->next) + nr_fields++; + fv = caml_alloc (nr_fields, 0); + + for (j = 0, fields = sections->fields; fields != NULL; + j++, fields = fields->next) { + v = caml_alloc_tuple (3); + sv = caml_copy_string (fields->key); + Store_field (v, 0, sv); /* (key, Some subkey, value) */ + if (fields->subkey) { + sv2 = caml_copy_string (fields->subkey); + sv = caml_alloc (1, 0); + Store_field (sv, 0, sv2); + } else + sv = Val_int (0); + Store_field (v, 1, sv); + sv = caml_copy_string (fields->value); + Store_field (v, 2, sv); + Store_field (fv, j, v); /* assign to return array of fields */ + } + + v = caml_alloc_tuple (2); + sv = caml_copy_string (sections->name); + Store_field (v, 0, sv); /* (name, fields) */ + Store_field (v, 1, fv); + Store_field (rv, i, v); /* assign to return array of sections */ + } + + /* Free parsed data. */ + parse_context_free (&context); + + CAMLreturn (rv); +} diff --git a/mllib/index-scan.l b/mllib/index-scan.l new file mode 100644 index 0000000..7125913 --- /dev/null +++ b/mllib/index-scan.l @@ -0,0 +1,144 @@ +/* libguestfs virt-builder tool -*- fundamental -*- + * Copyright (C) 2013 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +%top{ +#include <config.h> +} + +%{ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Silence gcc warnings from the generated code. */ +#if defined(__GNUC__) +#pragma GCC diagnostic push +/* flex creates macros that it doesn't use */ +#pragma GCC diagnostic ignored "-Wunused-macros" +/* on aarch64, flex doesn't know that char is unsigned */ +#pragma GCC diagnostic ignored "-Wsign-compare" +/* on debian-mipsel, flex doesn't create prototypes for all functions */ +#pragma GCC diagnostic ignored "-Wmissing-prototypes" +#endif + +#include "index-struct.h" +#include "index-parse.h" + +#define YY_EXTRA_TYPE struct parse_context * +#define YY_USER_ACTION yylloc->first_line = yylloc->last_line = yylineno; + +extern void scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in); +extern void scanner_destroy (yyscan_t scanner); + +%} + +%option nounput +%option noyywrap +%option yylineno +%option reentrant +%option bison-bridge +%option bison-locations + +%% + + /* Apart from the PGP prologue/epilogue which is a hack, the + * scanning strategy is to deal with the file strictly line by + * line, and pass those lines up to the parser which deals with + * whether they appear in the right order to be meaningful. + * Note that flex does longest-match. + */ + + /* Ignore comments - '#' MUST appear at the start of a line. */ +^"#".*\n { yyextra->seen_comments++; } + + /* An empty line is significant. */ +^\n { return EMPTY_LINE; } + + /* [...] marks beginning of a section. */ +^"["[-A-Za-z0-9._]+"]"\n { + yylval->str = strndup (yytext+1, yyleng-3); + return SECTION_HEADER; + } + + /* field=value or field[subfield]=value */ +^[A-Za-z0-9_.]+("["[A-Za-z0-9_,.]+"]")?"=".*\n { + size_t i = strcspn (yytext, "=["); + yylval->field = malloc (sizeof (struct field)); + yylval->field->next = NULL; + yylval->field->key = strndup (yytext, i); + if (yytext[i] == '[') { + size_t j = strcspn (yytext+i+1, "]"); + yylval->field->subkey = strndup (yytext+i+1, j); + i += 1+j+1; + } else { + yylval->field->subkey = NULL; + } + /* Note we chop the final \n off here. */ + yylval->field->value = strndup (yytext+i+1, yyleng-(i+2)); + return FIELD; + } + + /* Continuation line for multi-line values. */ +^[[:blank:]].*\n { + yylval->str = strndup (yytext+1, yyleng-2); + return VALUE_CONT; + } + + /* Hack to eat the PGP prologue. */ +^"-----BEGIN PGP SIGNED MESSAGE-----\n" { + int c, prevnl = 0; + + /* Eat everything to the first blank line. */ + while ((c = input (yyscanner)) != EOF) { + if (c == '\n' && prevnl) + break; + prevnl = c == '\n'; + } + + return PGP_PROLOGUE; +} + + /* Hack to eat the PGP epilogue. */ +^"-----BEGIN PGP SIGNATURE-----\n" { + /* Eat everything to the end of the file. */ + while (input (yyscanner) != EOF) + ; + + return PGP_EPILOGUE; +} + + /* anything else is an error */ +. { + return UNKNOWN_LINE; +} + +%% + +void +scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in) +{ + yylex_init (scanner); + yyset_extra (context, *scanner); + yyset_in (in, *scanner); +} + +void +scanner_destroy (yyscan_t scanner) +{ + yylex_destroy (scanner); +} diff --git a/mllib/index-struct.c b/mllib/index-struct.c new file mode 100644 index 0000000..eacca6c --- /dev/null +++ b/mllib/index-struct.c @@ -0,0 +1,60 @@ +/* libguestfs virt-builder tool + * Copyright (C) 2013 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "index-struct.h" + +void +parse_context_init (struct parse_context *context) +{ + memset (context, 0, sizeof *context); +} + +void +parse_context_free (struct parse_context *context) +{ + section_free (context->parsed_index); +} + +void +section_free (struct section *section) +{ + if (section) { + section_free (section->next); + free (section->name); + field_free (section->fields); + free (section); + } +} + +void +field_free (struct field *field) +{ + if (field) { + field_free (field->next); + free (field->key); + free (field->subkey); + free (field->value); + free (field); + } +} diff --git a/mllib/index-struct.h b/mllib/index-struct.h new file mode 100644 index 0000000..ada35e3 --- /dev/null +++ b/mllib/index-struct.h @@ -0,0 +1,67 @@ +/* libguestfs virt-builder tool + * Copyright (C) 2013 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* The data structures produced when parsing the index file. */ + +#ifndef INDEX_STRUCT_H +#define INDEX_STRUCT_H + +/* A section or list of sections. */ +struct section { + struct section *next; + char *name; + struct field *fields; +}; + +/* A field or list of fields. */ +struct field { + struct field *next; + char *key; + char *subkey; + char *value; +}; + +/* A struct holding the data needed during the parsing. */ +struct parse_context { + struct section *parsed_index; /* The result of the parsing. */ + /* yyparse sets this if any comments were seen. Required for checking + * compatibility with virt-builder 1.24. + */ + int seen_comments; + const char *input_file; + const char *progname; + const char *error_suffix; +}; + +/* Initialize the content of a parse_context. */ +extern void parse_context_init (struct parse_context *state); + +/* Free the content of a parse_context. The actual pointer is not freed. */ +extern void parse_context_free (struct parse_context *state); + +/* Free the content of a section, recursively freeing also its fields. + * The actual pointer is not freed. + */ +extern void section_free (struct section *section); + +/* Free the content of a field, recursively freeing also its next field. + * The actual pointer is not freed. + */ +extern void field_free (struct field *field); + +#endif /* INDEX_STRUCT_H */ diff --git a/mllib/ini_reader.ml b/mllib/ini_reader.ml new file mode 100644 index 0000000..50a06f9 --- /dev/null +++ b/mllib/ini_reader.ml @@ -0,0 +1,40 @@ +(* virt-builder + * Copyright (C) 2013-2015 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *) + +open Common_utils + +type sections = section list +and section = string * fields (* [name] + fields *) +and fields = field list +and field = string * string option * string (* key + subkey + value *) + +(* Types returned by the C index parser. *) +type c_sections = c_section array +and c_section = string * c_fields (* [name] + fields *) +and c_fields = field array + +(* Calls yyparse in the C code. *) +external parse_index : prog:string -> error_suffix:string -> string -> c_sections = "virt_builder_parse_index" + +let read_ini ?(error_suffix = "") file + let sections = parse_index ~prog ~error_suffix file in + let sections = Array.to_list sections in + List.map ( + fun (n, fields) -> + n, Array.to_list fields + ) sections diff --git a/mllib/ini_reader.mli b/mllib/ini_reader.mli new file mode 100644 index 0000000..62567e8 --- /dev/null +++ b/mllib/ini_reader.mli @@ -0,0 +1,24 @@ +(* virt-builder + * Copyright (C) 2013-2015 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *) + +type sections = section list +and section = string * fields (* [name] + fields *) +and fields = field list +and field = string * string option * string (* key + subkey + value *) + +val read_ini : ?error_suffix:string -> string -> sections diff --git a/po/POTFILES b/po/POTFILES index 7f1580c..d1115a0 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -1,8 +1,4 @@ align/scan.c -builder/index-parse.c -builder/index-parser-c.c -builder/index-scan.c -builder/index-struct.c builder/index-validate.c builder/pxzcat-c.c builder/setlocale-c.c @@ -259,6 +255,10 @@ lua/lua-guestfs.c make-fs/make-fs.c mllib/dummy.c mllib/fsync-c.c +mllib/index-parse.c +mllib/index-parser-c.c +mllib/index-scan.c +mllib/index-struct.c mllib/mkdtemp-c.c mllib/progress-c.c mllib/uri-c.c diff --git a/po/POTFILES-ml b/po/POTFILES-ml index 8725385..ee0294c 100644 --- a/po/POTFILES-ml +++ b/po/POTFILES-ml @@ -3,7 +3,6 @@ builder/cache.ml builder/cmdline.ml builder/downloader.ml builder/index_parser.ml -builder/ini_reader.ml builder/languages.ml builder/list_entries.ml builder/paths.ml @@ -33,6 +32,7 @@ mllib/common_utils.ml mllib/common_utils_tests.ml mllib/config.ml mllib/fsync.ml +mllib/ini_reader.ml mllib/libdir.ml mllib/mkdtemp.ml mllib/planner.ml -- 2.1.0
Pino Toscano
2015-Jul-08 14:42 UTC
[Libguestfs] [PATCH 2/6] mllib: add a real_uri parameter to Ini_reader.read_ini
Pass the string to the real URI being parsed, if different than the passed file argument. --- builder/index_parser.ml | 2 +- mllib/ini_reader.ml | 2 +- mllib/ini_reader.mli | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/builder/index_parser.ml b/builder/index_parser.ml index aff0b00..219003a 100644 --- a/builder/index_parser.ml +++ b/builder/index_parser.ml @@ -127,7 +127,7 @@ let get_index ~downloader ~sigchecker Sigchecker.verify sigchecker tmpfile; (* Try parsing the file. *) - let sections = Ini_reader.read_ini tmpfile in + let sections = Ini_reader.read_ini ~real_uri:uri tmpfile in if delete_tmpfile then (try Unix.unlink tmpfile with _ -> ()); diff --git a/mllib/ini_reader.ml b/mllib/ini_reader.ml index 50a06f9..6d1d347 100644 --- a/mllib/ini_reader.ml +++ b/mllib/ini_reader.ml @@ -31,7 +31,7 @@ and c_fields = field array (* Calls yyparse in the C code. *) external parse_index : prog:string -> error_suffix:string -> string -> c_sections = "virt_builder_parse_index" -let read_ini ?(error_suffix = "") file +let read_ini ?(error_suffix = "") ?real_uri file let sections = parse_index ~prog ~error_suffix file in let sections = Array.to_list sections in List.map ( diff --git a/mllib/ini_reader.mli b/mllib/ini_reader.mli index 62567e8..7005e62 100644 --- a/mllib/ini_reader.mli +++ b/mllib/ini_reader.mli @@ -21,4 +21,4 @@ and section = string * fields (* [name] + fields *) and fields = field list and field = string * string option * string (* key + subkey + value *) -val read_ini : ?error_suffix:string -> string -> sections +val read_ini : ?error_suffix:string -> ?real_uri:string -> string -> sections -- 2.1.0
Pino Toscano
2015-Jul-08 14:42 UTC
[Libguestfs] [PATCH 3/6] mllib: add duplicate fields check to Ini_reader.read_ini
Move the existing check from Index_parser in virt-builder, so it can be used also in other contexts (the Source reader, for example, which currently does not do any duplicate check). --- builder/index_parser.ml | 22 ++-------------------- builder/sources.ml | 3 ++- mllib/ini_reader.ml | 35 ++++++++++++++++++++++++++++++++--- mllib/ini_reader.mli | 2 +- 4 files changed, 37 insertions(+), 25 deletions(-) diff --git a/builder/index_parser.ml b/builder/index_parser.ml index 219003a..fad0781 100644 --- a/builder/index_parser.ml +++ b/builder/index_parser.ml @@ -127,7 +127,8 @@ let get_index ~downloader ~sigchecker Sigchecker.verify sigchecker tmpfile; (* Try parsing the file. *) - let sections = Ini_reader.read_ini ~real_uri:uri tmpfile in + let sections = Ini_reader.read_ini ~check_duplicated_fields:true + ~real_uri:uri tmpfile in if delete_tmpfile then (try Unix.unlink tmpfile with _ -> ()); @@ -152,25 +153,6 @@ let get_index ~downloader ~sigchecker Hashtbl.add nseen id true ) name_arch_map; - (* Check for repeated fields. *) - List.iter ( - fun (n, fields) -> - let fseen = Hashtbl.create 13 in - List.iter ( - fun (field, subkey, _) -> - let hashkey = (field, subkey) in - if Hashtbl.mem fseen hashkey then ( - (match subkey with - | Some value -> - eprintf (f_"%s: index is corrupt: %s: field '%s[%s]' appears two or more times\n") prog n field value - | None -> - eprintf (f_"%s: index is corrupt: %s: field '%s' appears two or more times\n") prog n field); - corrupt_file () - ); - Hashtbl.add fseen hashkey true - ) fields - ) sections; - (* Turn the sections into the final index. *) let entries List.map ( diff --git a/builder/sources.ml b/builder/sources.ml index b774762..7cd522c 100644 --- a/builder/sources.ml +++ b/builder/sources.ml @@ -35,7 +35,8 @@ let parse_conf file if verbose () then ( printf (f_"%s: trying to read %s\n") prog file; ); - let sections = Ini_reader.read_ini ~error_suffix:"[ignored]" file in + let sections = Ini_reader.read_ini ~error_suffix:"[ignored]" + ~check_duplicated_fields:true file in let sources = List.fold_right ( fun (n, fields) acc -> diff --git a/mllib/ini_reader.ml b/mllib/ini_reader.ml index 6d1d347..ea3bbda 100644 --- a/mllib/ini_reader.ml +++ b/mllib/ini_reader.ml @@ -16,6 +16,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *) +open Common_gettext.Gettext open Common_utils type sections = section list @@ -31,10 +32,38 @@ and c_fields = field array (* Calls yyparse in the C code. *) external parse_index : prog:string -> error_suffix:string -> string -> c_sections = "virt_builder_parse_index" -let read_ini ?(error_suffix = "") ?real_uri file +let read_ini ?(error_suffix = "") ?real_uri + ?(check_duplicated_fields = false) file let sections = parse_index ~prog ~error_suffix file in let sections = Array.to_list sections in - List.map ( + let sections = List.map ( fun (n, fields) -> n, Array.to_list fields - ) sections + ) sections in + + let uri + match real_uri with + | None -> file + | Some uri -> uri in + + (* Check for repeated fields. *) + if check_duplicated_fields then ( + List.iter ( + fun (n, fields) -> + let fseen = Hashtbl.create 13 in + List.iter ( + fun (field, subkey, _) -> + let hashkey = (field, subkey) in + if Hashtbl.mem fseen hashkey then ( + match subkey with + | Some value -> + error (f_"%s is corrupt: %s: field '%s[%s]' appears two or more times") uri n field value + | None -> + error (f_"%s is corrupt: %s: field '%s' appears two or more times") uri n field + ); + Hashtbl.add fseen hashkey true + ) fields + ) sections + ); + + sections diff --git a/mllib/ini_reader.mli b/mllib/ini_reader.mli index 7005e62..ceda015 100644 --- a/mllib/ini_reader.mli +++ b/mllib/ini_reader.mli @@ -21,4 +21,4 @@ and section = string * fields (* [name] + fields *) and fields = field list and field = string * string option * string (* key + subkey + value *) -val read_ini : ?error_suffix:string -> ?real_uri:string -> string -> sections +val read_ini : ?error_suffix:string -> ?real_uri:string -> ?check_duplicated_fields:bool -> string -> sections -- 2.1.0
Pino Toscano
2015-Jul-08 14:42 UTC
[Libguestfs] [PATCH 4/6] mllib: add duplicate sections check to Ini_reader.read_ini
Not currently used, since repository configurations and indexes in virt-builder allow more sections with the same name. --- mllib/ini_reader.ml | 15 ++++++++++++++- mllib/ini_reader.mli | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/mllib/ini_reader.ml b/mllib/ini_reader.ml index ea3bbda..08f3ec7 100644 --- a/mllib/ini_reader.ml +++ b/mllib/ini_reader.ml @@ -33,7 +33,8 @@ and c_fields = field array external parse_index : prog:string -> error_suffix:string -> string -> c_sections = "virt_builder_parse_index" let read_ini ?(error_suffix = "") ?real_uri - ?(check_duplicated_fields = false) file + ?(check_duplicated_sections = false) ?(check_duplicated_fields = false) + file let sections = parse_index ~prog ~error_suffix file in let sections = Array.to_list sections in let sections = List.map ( @@ -46,6 +47,18 @@ let read_ini ?(error_suffix = "") ?real_uri | None -> file | Some uri -> uri in + (* Check for duplicated sections. *) + if check_duplicated_sections then ( + let gseen = Hashtbl.create 13 in + List.iter ( + fun (n, _) -> + if Hashtbl.mem gseen n then + error (f_"%s is corrupt: section '%s' appears two or more times") + uri n; + Hashtbl.add gseen n true + ) sections + ); + (* Check for repeated fields. *) if check_duplicated_fields then ( List.iter ( diff --git a/mllib/ini_reader.mli b/mllib/ini_reader.mli index ceda015..63e7572 100644 --- a/mllib/ini_reader.mli +++ b/mllib/ini_reader.mli @@ -21,4 +21,4 @@ and section = string * fields (* [name] + fields *) and fields = field list and field = string * string option * string (* key + subkey + value *) -val read_ini : ?error_suffix:string -> ?real_uri:string -> ?check_duplicated_fields:bool -> string -> sections +val read_ini : ?error_suffix:string -> ?real_uri:string -> ?check_duplicated_sections:bool -> ?check_duplicated_fields:bool -> string -> sections -- 2.1.0
Pino Toscano
2015-Jul-08 14:42 UTC
[Libguestfs] [PATCH 5/6] mllib: add quick section/key lookup method
Add an helper method to lookup the value of a key within a parsed ini configuration. --- mllib/ini_reader.ml | 16 ++++++++++++++++ mllib/ini_reader.mli | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/mllib/ini_reader.ml b/mllib/ini_reader.ml index 08f3ec7..3c9dcee 100644 --- a/mllib/ini_reader.ml +++ b/mllib/ini_reader.ml @@ -24,6 +24,9 @@ and section = string * fields (* [name] + fields *) and fields = field list and field = string * string option * string (* key + subkey + value *) +exception Section_not_found of string (* section *) +exception Key_not_found of (string * string * string option) (* section, key, subkey *) + (* Types returned by the C index parser. *) type c_sections = c_section array and c_section = string * c_fields (* [name] + fields *) @@ -80,3 +83,16 @@ let read_ini ?(error_suffix = "") ?real_uri ); sections + +let ini_get_value ?subkey ini group key + let confgroup + match List.filter (fun (n, _) -> n = group) ini with + | [] -> raise (Section_not_found group) + | (_, fields) :: _ -> fields in + let confkey = List.filter ( + fun (field, subfield, _) -> + field = key && subfield = subkey + ) confgroup in + match confkey with + | [] -> raise (Key_not_found (group, key, subkey)) + | (_, _, value) :: _ -> value diff --git a/mllib/ini_reader.mli b/mllib/ini_reader.mli index 63e7572..f55f596 100644 --- a/mllib/ini_reader.mli +++ b/mllib/ini_reader.mli @@ -21,4 +21,9 @@ and section = string * fields (* [name] + fields *) and fields = field list and field = string * string option * string (* key + subkey + value *) +exception Section_not_found of string (* section *) +exception Key_not_found of (string * string * string option) (* section, key, subkey *) + val read_ini : ?error_suffix:string -> ?real_uri:string -> ?check_duplicated_sections:bool -> ?check_duplicated_fields:bool -> string -> sections + +val ini_get_value : ?subkey:string -> sections -> string -> string -> string -- 2.1.0
Pino Toscano
2015-Jul-08 14:42 UTC
[Libguestfs] [PATCH 6/6] customize: add basic subscription-manager operations
Add simple operations for RHEL guests using subscription-manager, so it is possible to e.g. install software on them. --- customize/Makefile.am | 8 +++- customize/customize_run.ml | 58 ++++++++++++++++++++++++++ generator/customize.ml | 101 +++++++++++++++++++++++++++++++++++++++++++++ sysprep/Makefile.am | 8 +++- 4 files changed, 173 insertions(+), 2 deletions(-) diff --git a/customize/Makefile.am b/customize/Makefile.am index 8f0a2d8..d664ba4 100644 --- a/customize/Makefile.am +++ b/customize/Makefile.am @@ -67,6 +67,10 @@ SOURCES_C = \ $(top_srcdir)/fish/file-edit.c \ $(top_srcdir)/fish/file-edit.h \ $(top_srcdir)/mllib/uri-c.c \ + $(top_srcdir)/mllib/index-parse.c \ + $(top_srcdir)/mllib/index-scan.c \ + $(top_srcdir)/mllib/index-struct.c \ + $(top_srcdir)/mllib/index-parser-c.c \ crypt-c.c \ perl_edit-c.c @@ -85,7 +89,8 @@ virt_customize_CPPFLAGS = \ virt_customize_CFLAGS = \ $(WARN_CFLAGS) $(WERROR_CFLAGS) \ $(LIBVIRT_CFLAGS) \ - $(LIBXML2_CFLAGS) + $(LIBXML2_CFLAGS) \ + -Wno-unused-macros BOBJECTS = \ $(top_builddir)/mllib/config.cmo \ @@ -93,6 +98,7 @@ BOBJECTS = \ $(top_builddir)/mllib/common_utils.cmo \ $(top_builddir)/mllib/regedit.cmo \ $(top_builddir)/mllib/uRI.cmo \ + $(top_builddir)/mllib/ini_reader.cmo \ $(SOURCES_ML:.ml=.cmo) XOBJECTS = $(BOBJECTS:.cmo=.cmx) diff --git a/customize/customize_run.ml b/customize/customize_run.ml index d9547a0..9fb2b14 100644 --- a/customize/customize_run.ml +++ b/customize/customize_run.ml @@ -153,6 +153,33 @@ exec >>%s 2>&1 Hashtbl.replace passwords user pw in + (* Parse the subscription-manager configuration. *) + let sm_config + match ops.flags.sm_config with + | None -> None + | Some c -> + try + Some (Ini_reader.read_ini ~check_duplicated_sections:true + ~check_duplicated_fields:true c) + with exn -> + error (f_"cannot parse the subscription-manager configuration: %s") + (Printexc.to_string exn) + in + let sm_config_get_value group key + let conf + match sm_config with + | None -> + error (f_"subscription-manager configuration required for this operation") + | Some c -> c in + try Ini_reader.ini_get_value conf group key + with + | Ini_reader.Section_not_found s -> + error (f_"subscription-manager configuration lacks the group '%s'") s + | Ini_reader.Key_not_found (s, k, _) -> + error (f_"subscription-manager configuration lacks the key '%s' in group '%s'") + k s + in + (* Perform the remaining customizations in command-line order. *) List.iter ( function @@ -249,6 +276,37 @@ exec >>%s 2>&1 message (f_"Scrubbing: %s") path; g#scrub_file path + | `SMAttach id -> + (match id with + | "auto" -> + message (f_"Attaching to compatible subscriptions"); + let cmd = "subscription-manager attach --auto" in + do_run ~display:cmd cmd + | id -> + let pool_id = sm_config_get_value ("attach-" ^ id) "pool" in + message (f_"Attaching to the pool %s") pool_id; + let cmd = sprintf "subscription-manager attach --pool=%s" pool_id in + do_run ~display:cmd cmd + ) + + | `SMRegister -> + message (f_"Registering with subscription-manager"); + let username = sm_config_get_value "general" "username" in + let password = sm_config_get_value "general" "password" in + let cmd = sprintf "subscription-manager register --username='%s' --password='%s'" + username password in + do_run ~display:"subscription-manager register" cmd + + | `SMRemove -> + message (f_"Removing all the subscriptions"); + let cmd = "subscription-manager remove --all" in + do_run ~display:cmd cmd + + | `SMUnregister -> + message (f_"Unregistering with subscription-manager"); + let cmd = "subscription-manager unregister" in + do_run ~display:cmd cmd + | `SSHInject (user, selector) -> (match g#inspect_get_type root with | "linux" | "freebsd" | "netbsd" | "openbsd" | "hurd" -> diff --git a/generator/customize.ml b/generator/customize.ml index f57aba6..bb31c25 100644 --- a/generator/customize.ml +++ b/generator/customize.ml @@ -327,6 +327,64 @@ It cannot delete directories, only regular files. =back"; }; + { op_name = "sm-attach"; + op_type = String "ID"; + op_discrim = "`SMAttach"; + op_shortdesc = "Attach to a subscription-manager pool"; + op_pod_longdesc = "\ +Attach to a pool using C<subscription-manager>. C<ID> can be any of +the following: + +=over 4 + +=item C<auto> + +subscription-manager attaches to the best-fitting subscriptions for +the system. + +=item C<ID> + +This requires a configuration file specified with the settings +(see also I<--sm-config>), containing the following: + + [attach-ID] + pool=0123... + +That is, a group named after the specified C<ID>, containing a C<pool> +key with the actual pool ID. + +=back"; + }; + + { op_name = "sm-register"; + op_type = Unit; + op_discrim = "`SMRegister"; + op_shortdesc = "Register using subscription-manager"; + op_pod_longdesc = "\ +Register the guest using C<subscription-manager>. + +This requires a configuration file specified with the settings +(see also I<--sm-config>), with the C<username> and C<password> +keys in the C<general> group."; + }; + + { op_name = "sm-remove"; + op_type = Unit; + op_discrim = "`SMRemove"; + op_shortdesc = "Remove all the subscriptions"; + op_pod_longdesc = "\ +Remove all the subscriptions from the guest using +C<subscription-manager>."; + }; + + { op_name = "sm-unregister"; + op_type = Unit; + op_discrim = "`SMUnregister"; + op_shortdesc = "Unregister using subscription-manager"; + op_pod_longdesc = "\ +Unregister the guest using C<subscription-manager>."; + }; + { op_name = "ssh-inject"; op_type = SSHKeySelector "USER[:SELECTOR]"; op_discrim = "`SSHInject"; @@ -428,6 +486,7 @@ type flag = { and flag_type | FlagBool of bool (* boolean is the default value *) | FlagPasswordCrypto of string +| FlagSMConfig of string let flags = [ { flag_name = "no-logfile"; @@ -477,6 +536,25 @@ Relabel files in the guest so that they have the correct SELinux label. You should only use this option for guests which support SELinux."; }; + + { flag_name = "sm-config"; + flag_type = FlagSMConfig "config"; + flag_ml_var = "sm_config"; + flag_shortdesc = "configuration for subscription-manager"; + flag_pod_longdesc = "\ +Defines a configuration for subscription-manager operations. +This file has a simple text like the following: + + [general] + username=user + password=secret + + [attach-0] + pool=0123... + +Different subscription-manager commands may require different sections."; + }; + ] let rec generate_customize_cmdline_mli () @@ -532,6 +610,8 @@ let rec argspec () pr " let %s = ref %b in\n" var default | { flag_type = FlagPasswordCrypto _; flag_ml_var = var } -> pr " let %s = ref None in\n" var + | { flag_type = FlagSMConfig _; flag_ml_var = var } -> + pr " let %s = ref None in\n" var ) flags; pr "\ @@ -699,6 +779,18 @@ let rec argspec () pr " \"%s\" ^ \" \" ^ s_\"%s\"\n" v shortdesc; pr " ),\n"; pr " Some %S, %S;\n" v longdesc + | { flag_type = FlagSMConfig v; flag_ml_var = var; + flag_name = name; flag_shortdesc = shortdesc; + flag_pod_longdesc = longdesc } -> + pr " (\n"; + pr " \"--%s\",\n" name; + pr " Arg.String (\n"; + pr " fun s ->\n"; + pr " %s := Some s\n" var; + pr " ),\n"; + pr " \"%s\" ^ \" \" ^ s_\"%s\"\n" v shortdesc; + pr " ),\n"; + pr " Some %S, %S;\n" v longdesc ) flags; pr " ] @@ -809,6 +901,10 @@ type ops = { flag_name = name } -> pr " %s : Password.password_crypto option;\n (* --%s %s *)\n" var name v + | { flag_type = FlagSMConfig v; flag_ml_var = var; + flag_name = name } -> + pr " %s : string option;\n (* --%s %s *)\n" + var name v ) flags; pr "}\n" @@ -832,6 +928,8 @@ let generate_customize_synopsis_pod () n, sprintf "[--%s]" n | { flag_type = FlagPasswordCrypto v; flag_name = n } -> n, sprintf "[--%s %s]" n v + | { flag_type = FlagSMConfig v; flag_name = n } -> + n, sprintf "[--%s %s]" n v ) flags in (* Print the option names in the synopsis, line-wrapped. *) @@ -874,6 +972,9 @@ let generate_customize_options_pod () | { flag_type = FlagPasswordCrypto v; flag_name = n; flag_pod_longdesc = ld } -> n, sprintf "B<--%s> %s" n v, ld + | { flag_type = FlagSMConfig v; + flag_name = n; flag_pod_longdesc = ld } -> + n, sprintf "B<--%s> %s" n v, ld ) flags in let cmp (arg1, _, _) (arg2, _, _) compare (String.lowercase arg1) (String.lowercase arg2) diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am index c1d1245..e7977bd 100644 --- a/sysprep/Makefile.am +++ b/sysprep/Makefile.am @@ -81,6 +81,10 @@ SOURCES_ML = \ SOURCES_C = \ $(top_srcdir)/mllib/uri-c.c \ $(top_srcdir)/mllib/mkdtemp-c.c \ + $(top_srcdir)/mllib/index-parse.c \ + $(top_srcdir)/mllib/index-scan.c \ + $(top_srcdir)/mllib/index-struct.c \ + $(top_srcdir)/mllib/index-parser-c.c \ $(top_srcdir)/customize/crypt-c.c \ $(top_srcdir)/customize/perl_edit-c.c \ $(top_srcdir)/fish/uri.c \ @@ -100,7 +104,8 @@ virt_sysprep_CPPFLAGS = \ -I$(top_srcdir)/fish virt_sysprep_CFLAGS = \ $(WARN_CFLAGS) $(WERROR_CFLAGS) \ - $(LIBXML2_CFLAGS) + $(LIBXML2_CFLAGS) \ + -Wno-unused-macros BOBJECTS = \ $(top_builddir)/mllib/config.cmo \ @@ -109,6 +114,7 @@ BOBJECTS = \ $(top_builddir)/mllib/uRI.cmo \ $(top_builddir)/mllib/mkdtemp.cmo \ $(top_builddir)/mllib/regedit.cmo \ + $(top_builddir)/mllib/ini_reader.cmo \ $(top_builddir)/customize/customize_utils.cmo \ $(top_builddir)/customize/crypt.cmo \ $(top_builddir)/customize/urandom.cmo \ -- 2.1.0
Richard W.M. Jones
2015-Jul-09 12:39 UTC
Re: [Libguestfs] [PATCH 6/6] customize: add basic subscription-manager operations
On Wed, Jul 08, 2015 at 04:42:18PM +0200, Pino Toscano wrote:> + error (f_"subscription-manager configuration required for this operation")This error message should refer to the --sm-config option in some way, so the error message is actionable. --- Patches 1-5 are fine and can go upstream now. I can't say that I'm overjoyed by the new config file format that we need here. Is it not possible to encode the configuration settings into --sm-* parameters? What about quoting - what happens if the password contains quotes or newlines? Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into KVM guests. http://libguestfs.org/virt-v2v
Possibly Parallel Threads
- [PATCH 1/2] builder: add an optional suffix string for INI parsing errors
- [PATCH 1/3] builder: make the C index parser reentrant
- [PATCH 0/4] Only tell people to use -v -x when reporting bugs if they're not using those flags.
- [PATCH v2 0/4] Only tell people to use -v -x when reporting bugs if they're not using those flags.
- [PATCH 1/3] builder/virt-index-validate: try to cleanup in any occasion