Pino Toscano
2019-Dec-20 10:36 UTC
[Libguestfs] [common/libguestfs PATCH 0/2] Fix OCaml/Python linking
Make sure they can build also in no as-neede setups. Pino Toscano (1): utils: split string list functions in own file build: use split stringlist functions from common/utils utils/Makefile.am | 2 + utils/guestfs-stringlists-utils.h | 30 +++++ utils/guestfs-utils.h | 7 +- utils/stringlists-utils.c | 197 ++++++++++++++++++++++++++++++ utils/utils.c | 165 ------------------------- 5 files changed, 230 insertions(+), 171 deletions(-) create mode 100644 utils/guestfs-stringlists-utils.h create mode 100644 utils/stringlists-utils.c -- 2.24.1
Pino Toscano
2019-Dec-20 10:36 UTC
[Libguestfs] [common/libguestfs PATCH 1/2] utils: split string list functions in own file
Few of them are used also when the whole libutils.a is not needed (or usable), also because the whole utils.c indirectly pulls gnulib. As solution, split them in an own file, with an own header so they can be used alone. To maintain compatibility with users of the whole libutils.a, include the new header in the existing guestfs-utils.h. --- utils/Makefile.am | 2 + utils/guestfs-stringlists-utils.h | 30 +++++ utils/guestfs-utils.h | 7 +- utils/stringlists-utils.c | 197 ++++++++++++++++++++++++++++++ utils/utils.c | 165 ------------------------- 5 files changed, 230 insertions(+), 171 deletions(-) create mode 100644 utils/guestfs-stringlists-utils.h create mode 100644 utils/stringlists-utils.c diff --git a/utils/Makefile.am b/utils/Makefile.am index 9eb39a3..4878e3b 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -23,9 +23,11 @@ libutils_la_SOURCES = \ cleanups.c \ cleanups.h \ gnulib-cleanups.c \ + guestfs-stringlists-utils.h \ guestfs-utils.h \ libxml2-cleanups.c \ libxml2-writer-macros.h \ + stringlists-utils.c \ utils.c libutils_la_CPPFLAGS = \ -DGUESTFS_NO_DEPRECATED=1 \ diff --git a/utils/guestfs-stringlists-utils.h b/utils/guestfs-stringlists-utils.h new file mode 100644 index 0000000..0bac158 --- /dev/null +++ b/utils/guestfs-stringlists-utils.h @@ -0,0 +1,30 @@ +/* libguestfs + * Copyright (C) 2013-2019 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef GUESTFS_STRINGLISTS_UTILS_H_ +#define GUESTFS_STRINGLISTS_UTILS_H_ + +/* stringlists-utils.c */ +extern void guestfs_int_free_string_list (char **); +extern size_t guestfs_int_count_strings (char *const *); +extern char *guestfs_int_concat_strings (char *const *); +extern char **guestfs_int_copy_string_list (char *const *); +extern char *guestfs_int_join_strings (const char *sep, char *const *); +extern char **guestfs_int_split_string (char sep, const char *); + +#endif /* GUESTFS_STRINGLISTS_UTILS_H_ */ diff --git a/utils/guestfs-utils.h b/utils/guestfs-utils.h index 52aeca0..b5f5f3c 100644 --- a/utils/guestfs-utils.h +++ b/utils/guestfs-utils.h @@ -36,17 +36,12 @@ #include "guestfs-internal-all.h" #include "cleanups.h" +#include "guestfs-stringlists-utils.h" #define _(str) dgettext(PACKAGE, (str)) #define N_(str) dgettext(PACKAGE, (str)) /* utils.c */ -extern void guestfs_int_free_string_list (char **); -extern size_t guestfs_int_count_strings (char *const *); -extern char *guestfs_int_concat_strings (char *const *); -extern char **guestfs_int_copy_string_list (char *const *); -extern char *guestfs_int_join_strings (const char *sep, char *const *); -extern char **guestfs_int_split_string (char sep, const char *); extern char *guestfs_int_replace_string (const char *str, const char *s1, const char *s2); extern char *guestfs_int_exit_status_to_string (int status, const char *cmd_name, char *buffer, size_t buflen); extern int guestfs_int_random_string (char *ret, size_t len); diff --git a/utils/stringlists-utils.c b/utils/stringlists-utils.c new file mode 100644 index 0000000..92c8030 --- /dev/null +++ b/utils/stringlists-utils.c @@ -0,0 +1,197 @@ +/* libguestfs + * Copyright (C) 2009-2019 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * Utility functions used by the library, tools and language bindings. + * + * These functions I<must not> call internal library functions + * such as C<safe_*>, C<error> or C<perrorf>, or any C<guestfs_int_*>. + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> + +/* NB: MUST NOT include "guestfs-internal.h". */ +#include "guestfs-stringlists-utils.h" + +void +guestfs_int_free_string_list (char **argv) +{ + size_t i; + + if (argv == NULL) + return; + + for (i = 0; argv[i] != NULL; ++i) + free (argv[i]); + free (argv); +} + +size_t +guestfs_int_count_strings (char *const *argv) +{ + size_t r; + + for (r = 0; argv[r]; ++r) + ; + + return r; +} + +char ** +guestfs_int_copy_string_list (char *const *argv) +{ + const size_t n = guestfs_int_count_strings (argv); + size_t i, j; + char **ret; + + ret = malloc ((n+1) * sizeof (char *)); + if (ret == NULL) + return NULL; + ret[n] = NULL; + + for (i = 0; i < n; ++i) { + ret[i] = strdup (argv[i]); + if (ret[i] == NULL) { + for (j = 0; j < i; ++j) + free (ret[j]); + free (ret); + return NULL; + } + } + + return ret; +} + +/* Note that near-identical functions exist in the daemon. */ +char * +guestfs_int_concat_strings (char *const *argv) +{ + return guestfs_int_join_strings ("", argv); +} + +char * +guestfs_int_join_strings (const char *sep, char *const *argv) +{ + size_t i, len, seplen, rlen; + char *r; + + seplen = strlen (sep); + + len = 0; + for (i = 0; argv[i] != NULL; ++i) { + if (i > 0) + len += seplen; + len += strlen (argv[i]); + } + len++; /* for final \0 */ + + r = malloc (len); + if (r == NULL) + return NULL; + + rlen = 0; + for (i = 0; argv[i] != NULL; ++i) { + if (i > 0) { + memcpy (&r[rlen], sep, seplen); + rlen += seplen; + } + len = strlen (argv[i]); + memcpy (&r[rlen], argv[i], len); + rlen += len; + } + r[rlen] = '\0'; + + return r; +} + +/** + * Split string at separator character C<sep>, returning the list of + * strings. Returns C<NULL> on memory allocation failure. + * + * Note (assuming C<sep> is C<:>): + * + * =over 4 + * + * =item C<str == NULL> + * + * aborts + * + * =item C<str == ""> + * + * returns C<[]> + * + * =item C<str == "abc"> + * + * returns C<["abc"]> + * + * =item C<str == ":"> + * + * returns C<["", ""]> + * + * =back + */ +char ** +guestfs_int_split_string (char sep, const char *str) +{ + size_t i, n, c; + const size_t len = strlen (str); + char reject[2] = { sep, '\0' }; + char **ret; + + /* We have to handle the empty string case differently else the code + * below will return [""]. + */ + if (str[0] == '\0') { + ret = malloc (1 * sizeof (char *)); + if (!ret) + return NULL; + ret[0] = NULL; + return ret; + } + + for (n = i = 0; i < len; ++i) + if (str[i] == sep) + n++; + + /* We always return a list of length 1 + (# separator characters). + * We also have to add a trailing NULL. + */ + ret = malloc ((n+2) * sizeof (char *)); + if (!ret) + return NULL; + ret[n+1] = NULL; + + for (n = i = 0; i <= len; ++i, ++n) { + c = strcspn (&str[i], reject); + ret[n] = strndup (&str[i], c); + if (ret[n] == NULL) { + for (i = 0; i < n; ++i) + free (ret[i]); + free (ret); + return NULL; + } + i += c; + if (str[i] == '\0') /* end of string? */ + break; + } + + return ret; +} diff --git a/utils/utils.c b/utils/utils.c index 18725f6..60ae113 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -49,171 +49,6 @@ #include "guestfs.h" #include "guestfs-utils.h" -void -guestfs_int_free_string_list (char **argv) -{ - size_t i; - - if (argv == NULL) - return; - - for (i = 0; argv[i] != NULL; ++i) - free (argv[i]); - free (argv); -} - -size_t -guestfs_int_count_strings (char *const *argv) -{ - size_t r; - - for (r = 0; argv[r]; ++r) - ; - - return r; -} - -char ** -guestfs_int_copy_string_list (char *const *argv) -{ - const size_t n = guestfs_int_count_strings (argv); - size_t i, j; - char **ret; - - ret = malloc ((n+1) * sizeof (char *)); - if (ret == NULL) - return NULL; - ret[n] = NULL; - - for (i = 0; i < n; ++i) { - ret[i] = strdup (argv[i]); - if (ret[i] == NULL) { - for (j = 0; j < i; ++j) - free (ret[j]); - free (ret); - return NULL; - } - } - - return ret; -} - -/* Note that near-identical functions exist in the daemon. */ -char * -guestfs_int_concat_strings (char *const *argv) -{ - return guestfs_int_join_strings ("", argv); -} - -char * -guestfs_int_join_strings (const char *sep, char *const *argv) -{ - size_t i, len, seplen, rlen; - char *r; - - seplen = strlen (sep); - - len = 0; - for (i = 0; argv[i] != NULL; ++i) { - if (i > 0) - len += seplen; - len += strlen (argv[i]); - } - len++; /* for final \0 */ - - r = malloc (len); - if (r == NULL) - return NULL; - - rlen = 0; - for (i = 0; argv[i] != NULL; ++i) { - if (i > 0) { - memcpy (&r[rlen], sep, seplen); - rlen += seplen; - } - len = strlen (argv[i]); - memcpy (&r[rlen], argv[i], len); - rlen += len; - } - r[rlen] = '\0'; - - return r; -} - -/** - * Split string at separator character C<sep>, returning the list of - * strings. Returns C<NULL> on memory allocation failure. - * - * Note (assuming C<sep> is C<:>): - * - * =over 4 - * - * =item C<str == NULL> - * - * aborts - * - * =item C<str == ""> - * - * returns C<[]> - * - * =item C<str == "abc"> - * - * returns C<["abc"]> - * - * =item C<str == ":"> - * - * returns C<["", ""]> - * - * =back - */ -char ** -guestfs_int_split_string (char sep, const char *str) -{ - size_t i, n, c; - const size_t len = strlen (str); - char reject[2] = { sep, '\0' }; - char **ret; - - /* We have to handle the empty string case differently else the code - * below will return [""]. - */ - if (str[0] == '\0') { - ret = malloc (1 * sizeof (char *)); - if (!ret) - return NULL; - ret[0] = NULL; - return ret; - } - - for (n = i = 0; i < len; ++i) - if (str[i] == sep) - n++; - - /* We always return a list of length 1 + (# separator characters). - * We also have to add a trailing NULL. - */ - ret = malloc ((n+2) * sizeof (char *)); - if (!ret) - return NULL; - ret[n+1] = NULL; - - for (n = i = 0; i <= len; ++i, ++n) { - c = strcspn (&str[i], reject); - ret[n] = strndup (&str[i], c); - if (ret[n] == NULL) { - for (i = 0; i < n; ++i) - free (ret[i]); - free (ret); - return NULL; - } - i += c; - if (str[i] == '\0') /* end of string? */ - break; - } - - return ret; -} - /** * Replace every instance of C<s1> appearing in C<str> with C<s2>. A * newly allocated string is returned which must be freed by the -- 2.24.1
Pino Toscano
2019-Dec-20 10:36 UTC
[Libguestfs] [common/libguestfs PATCH 2/2] build: use split stringlist functions from common/utils
The OCaml and Python bindings directly use the utils.c source in common/utils, mostly for guestfs_int_free_string_list. That source contained also functions using gnulib functions, however without linking to gnulib. When building with default build flags (e.g. without as-needed mode), the gnulib symbols cannot be resolved, leading to unusable OCaml and Python libraries. As solution, update the common submodule to get the split of the split of the stringlist functions in common/utils, and adapt the OCaml and Python bindings: - both now use stringlists-utils.c instead of utils.c - fix the Python distutils setup to include only the sources really needed --- .gitignore | 9 ++------- generator/python.ml | 2 +- ocaml/Makefile.am | 2 +- python/MANIFEST.in | 6 +----- python/Makefile.am | 45 ++++++++++----------------------------------- python/setup.py.in | 2 +- 6 files changed, 16 insertions(+), 50 deletions(-) diff --git a/.gitignore b/.gitignore index 7efd9b907..1abb1c8b7 100644 --- a/.gitignore +++ b/.gitignore @@ -451,9 +451,6 @@ Makefile.in /python/actions.h /python/bindtests.py /python/build -/python/c-ctype.h -/python/cleanups.c -/python/cleanups.h /python/config.h /python/dist /python/examples/guestfs-python.3 @@ -461,17 +458,15 @@ Makefile.in /python/guestfs.py /python/guestfs.pyc /python/guestfs.pyo -/python/guestfs-internal-all.h -/python/guestfs-utils.h -/python/ignore-value.h +/python/guestfs-stringlists-utils.h /python/MANIFEST /python/module.c +/python/stringlists-utils.c /python/structs.c /python/__pycache__ /python/setup.py /python/stamp-extra-files /python/t/tests_helper.py -/python/utils.c /rescue/stamp-virt-rescue.pod /rescue/virt-rescue /rescue/virt-rescue.1 diff --git a/generator/python.ml b/generator/python.ml index e436f4bda..821c66755 100644 --- a/generator/python.ml +++ b/generator/python.ml @@ -42,7 +42,7 @@ let rec generate_python_actions_h () #define GUESTFS_PYTHON_ACTIONS_H_ #include \"guestfs.h\" -#include \"guestfs-utils.h\" +#include \"guestfs-stringlists-utils.h\" #define PY_SSIZE_T_CLEAN 1 diff --git a/ocaml/Makefile.am b/ocaml/Makefile.am index b31e8fc65..c85efee64 100644 --- a/ocaml/Makefile.am +++ b/ocaml/Makefile.am @@ -94,7 +94,7 @@ libguestfsocaml_a_SOURCES = \ guestfs-c-actions.c \ guestfs-c-errnos.c \ ../common/utils/cleanups.c \ - ../common/utils/utils.c + ../common/utils/stringlists-utils.c if HAVE_OCAMLDOC diff --git a/python/MANIFEST.in b/python/MANIFEST.in index 9de894c3c..979f99233 100644 --- a/python/MANIFEST.in +++ b/python/MANIFEST.in @@ -16,9 +16,5 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. include actions.h -include c-ctype.h -include cleanups.h include config.h -include guestfs-internal-all.h -include guestfs-utils.h -include ignore-value.h +include guestfs-stringlists-utils.h diff --git a/python/Makefile.am b/python/Makefile.am index c2f57a6ba..b470d2df2 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -63,7 +63,8 @@ libguestfsmod_la_SOURCES = \ actions.h \ handle.c \ module.c \ - structs.c + structs.c \ + ../common/utils/stringlists-utils.c libguestfsmod_la_CPPFLAGS = \ -DGUESTFS_PRIVATE=1 \ @@ -75,7 +76,6 @@ libguestfsmod_la_CFLAGS = \ $(WARN_CFLAGS) $(WERROR_CFLAGS) libguestfsmod_la_LIBADD = \ - $(top_builddir)/common/utils/libutils_la-utils.lo \ $(top_builddir)/lib/libguestfs.la libguestfsmod_la_LDFLAGS = -avoid-version -shared -module -shrext $(PYTHON_EXT_SUFFIX) @@ -97,39 +97,19 @@ setup-install: setup.py stamp-extra-files # Python's crappy MANIFEST file cannot graft single files, so we have # to hard-link any extra files we need into the local directory. stamp-extra-files: \ - c-ctype.h \ - cleanups.c \ - cleanups.h \ config.h \ - guestfs-internal-all.h \ - guestfs-utils.h \ - ignore-value.h \ - utils.c + guestfs-stringlists-utils.h \ + stringlists-utils.c touch $@ config.h: ln ../config.h $@ -c-ctype.h: - ln $(top_srcdir)/gnulib/lib/c-ctype.h $@ - -cleanups.c: - ln $(top_srcdir)/common/utils/cleanups.c $@ - -cleanups.h: - ln $(top_srcdir)/common/utils/cleanups.h $@ - -ignore-value.h: - ln $(top_srcdir)/gnulib/lib/ignore-value.h $@ - -guestfs-internal-all.h: - ln $(top_srcdir)/lib/guestfs-internal-all.h $@ - -guestfs-utils.h: - ln $(top_srcdir)/common/utils/guestfs-utils.h $@ +guestfs-stringlists-utils.h: + ln $(top_srcdir)/common/utils/guestfs-stringlists-utils.h $@ -utils.c: - ln $(top_srcdir)/common/utils/utils.c $@ +stringlists-utils.c: + ln $(top_srcdir)/common/utils/stringlists-utils.c $@ # Tests. @@ -148,15 +128,10 @@ CLEANFILES += \ *.pyc \ examples/*~ examples/*.pyc \ t/*~ t/*.pyc \ - c-ctype.h \ config.h \ - cleanups.c \ - cleanups.h \ - guestfs-internal-all.h \ - guestfs-utils.h \ - ignore-value.h \ + guestfs-stringlists-utils.h \ stamp-extra-files \ - utils.c + stringlists-utils.c clean-local: rm -rf build dist __pycache__ t/__pycache__ diff --git a/python/setup.py.in b/python/setup.py.in index 079920d0e..0c8cff13b 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -62,7 +62,7 @@ This package contains the Python bindings for libguestfs. 'handle.c', 'module.c', 'structs.c', - 'utils.c'], + 'stringlists-utils.c'], include_dirs=['.', '../lib'], libraries=['guestfs'], -- 2.24.1
Richard W.M. Jones
2020-Jan-09 13:37 UTC
Re: [Libguestfs] [common/libguestfs PATCH 2/2] build: use split stringlist functions from common/utils
Looks good, ACK series. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://libguestfs.org
Apparently Analagous Threads
- [common/libguestfs PATCH 0/2] Fix OCaml/Python linking
- Plans for buster
- [common/libguestfs PATCH] utils: conditionally include config.h on HAVE_CONFIG_H
- [PATCH] generator: Passing "" to StringList tests should turn into empty list.
- [PATCH] python: remove also __pycache__ directories on clean