[libvirt] [PATCH 0/3] improve i18n

This patch series depends on these two previous patches (not reviewed yet): https://www.redhat.com/archives/libvir-list/2010-November/msg00733.html https://www.redhat.com/archives/libvir-list/2010-November/msg00626.html It also replaces my earlier patch here: https://www.redhat.com/archives/libvir-list/2010-September/msg00583.html It also makes it possible to boostrap on FreeBSD, as a side-effect of updating bootstrap. Eric Blake (3): maint: improve i18n on non-Linux maint: update to latest gnulib virt-aa-helper: translate error messages .gitignore | 65 +++++++------ .gnulib | 2 +- .x-sc_bindtextdomain | 2 + Makefile.am | 1 + bootstrap | 44 ++++++--- build-aux/.gitignore | 16 --- cfg.mk | 2 + daemon/libvirtd.c | 10 ++- m4/.gitignore | 37 ------- po/.gitignore | 17 ---- po/POTFILES.in | 1 + src/internal.h | 11 ++- src/lxc/lxc_controller.c | 9 ++ src/security/security_apparmor.c | 1 + src/security/virt-aa-helper.c | 194 ++++++++++++++++++++------------------ src/storage/parthelper.c | 15 +++- tools/virsh.c | 4 +- 17 files changed, 215 insertions(+), 216 deletions(-) create mode 100644 .x-sc_bindtextdomain delete mode 100644 build-aux/.gitignore delete mode 100644 m4/.gitignore delete mode 100644 po/.gitignore -- 1.7.3.2

Per the gettext developer: http://lists.gnu.org/archive/html/bug-gnu-utils/2010-10/msg00019.html http://lists.gnu.org/archive/html/bug-gnu-utils/2010-10/msg00021.html gettext() doesn't work correctly on all platforms unless you have called setlocale(). Furthermore, gnulib's gettext.h has provisions for setting up a default locale, which is the preferred method for libraries to use gettext without having to call textdomain() and override the main program's default domain (virInitialize already calls bindtextdomain(), but this is insufficient without the setlocale() added in this patch; and a redundant bindtextdomain() in this patch doesn't hurt, but serves as a good example for other packages that need to bind a second translation domain). This patch is needed to silence a new gnulib 'make syntax-check' rule in the next patch. * daemon/libvirtd.c (main): Setup locale and gettext. * src/lxc/lxc_controller.c (main): Likewise. * src/security/virt-aa-helper.c (main): Likewise. * src/storage/parthelper.c (main): Likewise. * tools/virsh.c (main): Fix exit status. * src/internal.h (DEFAULT_TEXT_DOMAIN): Define, for gettext.h. (_): Simplify definition accordingly. * po/POTFILES.in: Add src/storage/parthelper.c. --- daemon/libvirtd.c | 10 +++++++--- po/POTFILES.in | 1 + src/internal.h | 11 ++++++++--- src/lxc/lxc_controller.c | 9 +++++++++ src/security/security_apparmor.c | 1 + src/security/virt-aa-helper.c | 7 +++++++ src/storage/parthelper.c | 15 ++++++++++++--- tools/virsh.c | 4 ++-- 8 files changed, 47 insertions(+), 11 deletions(-) diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index aab7667..c43fc67 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -47,6 +47,7 @@ #include <grp.h> #include <signal.h> #include <netdb.h> +#include <locale.h> #include "libvirt_internal.h" #include "virterror_internal.h" @@ -3076,9 +3077,12 @@ int main(int argc, char **argv) { {0, 0, 0, 0} }; - if (virInitialize() < 0) { - fprintf (stderr, _("%s: initialization failed\n"), argv0); - exit (EXIT_FAILURE); + if (setlocale (LC_ALL, "") == NULL || + bindtextdomain (PACKAGE, LOCALEDIR) == NULL || + textdomain(PACKAGE) == NULL || + virInitialize() < 0) { + fprintf(stderr, _("%s: initialization failed\n"), argv0); + exit(EXIT_FAILURE); } while (1) { diff --git a/po/POTFILES.in b/po/POTFILES.in index ed3a151..2820ac1 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -63,6 +63,7 @@ src/security/security_apparmor.c src/security/security_driver.c src/security/security_selinux.c src/security/virt-aa-helper.c +src/storage/parthelper.c src/storage/storage_backend.c src/storage/storage_backend_disk.c src/storage/storage_backend_fs.c diff --git a/src/internal.h b/src/internal.h index a98daa3..8473c3c 100644 --- a/src/internal.h +++ b/src/internal.h @@ -27,7 +27,15 @@ */ # define VIR_DEPRECATED /*empty*/ +/* All uses of _() within the library should pick up translations from + * libvirt's message files, rather than from the package that is + * linking in the library. Setting this macro before including + * "gettext.h" means that gettext() (and _()) will properly expand to + * dgettext. */ +# define DEFAULT_TEXT_DOMAIN PACKAGE # include "gettext.h" +# define _(str) gettext(str) +# define N_(str) str # include "libvirt/libvirt.h" # include "libvirt/virterror.h" @@ -52,9 +60,6 @@ # define INET_ADDRSTRLEN 16 # endif -# define _(str) dgettext(PACKAGE, (str)) -# define N_(str) str - /* String equality tests, suggested by Jim Meyering. */ # define STREQ(a,b) (strcmp(a,b) == 0) # define STRCASEEQ(a,b) (strcasecmp(a,b) == 0) diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 478f0d1..af0b70c 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2010 Red Hat, Inc. * Copyright IBM Corp. 2008 * * lxc_controller.c: linux container process controller @@ -34,6 +35,7 @@ #include <signal.h> #include <getopt.h> #include <sys/mount.h> +#include <locale.h> #if HAVE_CAPNG # include <cap-ng.h> @@ -717,6 +719,13 @@ int main(int argc, char *argv[]) { 0, 0, 0, 0 }, }; + if (setlocale(LC_ALL, "") == NULL || + bindtextdomain(PACKAGE, LOCALEDIR) == NULL || + textdomain(PACKAGE) == NULL) { + fprintf(stderr, _("%s: initialization failed\n"), argv[0]); + exit(EXIT_FAILURE); + } + while (1) { int c; diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index b43c4ac..f172cfd 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -25,6 +25,7 @@ #include <unistd.h> #include <wait.h> #include <stdbool.h> +#include <locale.h> #include "internal.h" diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 0f94fe4..3b13298 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1134,6 +1134,13 @@ main(int argc, char **argv) char profile[PATH_MAX]; char include_file[PATH_MAX]; + if (setlocale(LC_ALL, "") == NULL || + bindtextdomain(PACKAGE, LOCALEDIR) == NULL || + textdomain(PACKAGE) == NULL) { + fprintf(stderr, _("%s: initialization failed\n"), argv0); + exit(EXIT_FAILURE); + } + /* clear the environment */ environ = NULL; if (setenv("PATH", "/sbin:/usr/sbin", 1) != 0) { diff --git a/src/storage/parthelper.c b/src/storage/parthelper.c index 2a70250..6ef413d 100644 --- a/src/storage/parthelper.c +++ b/src/storage/parthelper.c @@ -39,9 +39,11 @@ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> +#include <locale.h> #include "util.h" #include "c-ctype.h" +#include "configmake.h" /* we don't need to include the full internal.h just for this */ #define STREQ(a,b) (strcmp(a,b) == 0) @@ -79,10 +81,17 @@ int main(int argc, char **argv) char *canonical_path; const char *partsep; + if (setlocale(LC_ALL, "") == NULL || + bindtextdomain(PACKAGE, LOCALEDIR) == NULL || + textdomain(PACKAGE) == NULL) { + fprintf(stderr, _("%s: initialization failed\n"), argv[0]); + exit(EXIT_FAILURE); + } + if (argc == 3 && STREQ(argv[2], "-g")) { cmd = DISK_GEOMETRY; } else if (argc != 2) { - fprintf(stderr, "syntax: %s DEVICE [-g]\n", argv[0]); + fprintf(stderr, _("syntax: %s DEVICE [-g]\n"), argv[0]); return 1; } @@ -103,7 +112,7 @@ int main(int argc, char **argv) } if ((dev = ped_device_get(path)) == NULL) { - fprintf(stderr, "unable to access device %s\n", path); + fprintf(stderr, _("unable to access device %s\n"), path); return 2; } @@ -117,7 +126,7 @@ int main(int argc, char **argv) } if ((disk = ped_disk_new(dev)) == NULL) { - fprintf(stderr, "unable to access disk %s\n", argv[1]); + fprintf(stderr, _("unable to access disk %s\n"), argv[1]); return 2; } diff --git a/tools/virsh.c b/tools/virsh.c index 743d5a1..36e74e5 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -11789,11 +11789,11 @@ main(int argc, char **argv) } if (!bindtextdomain(PACKAGE, LOCALEDIR)) { perror("bindtextdomain"); - return -1; + return EXIT_FAILURE; } if (!textdomain(PACKAGE)) { perror("textdomain"); - return -1; + return EXIT_FAILURE; } if (!(progname = strrchr(argv[0], '/'))) -- 1.7.3.2

On Tue, Nov 16, 2010 at 03:35:16PM -0700, Eric Blake wrote:
Per the gettext developer: http://lists.gnu.org/archive/html/bug-gnu-utils/2010-10/msg00019.html http://lists.gnu.org/archive/html/bug-gnu-utils/2010-10/msg00021.html
gettext() doesn't work correctly on all platforms unless you have called setlocale(). Furthermore, gnulib's gettext.h has provisions for setting up a default locale, which is the preferred method for libraries to use gettext without having to call textdomain() and override the main program's default domain (virInitialize already calls bindtextdomain(), but this is insufficient without the setlocale() added in this patch; and a redundant bindtextdomain() in this patch doesn't hurt, but serves as a good example for other packages that need to bind a second translation domain).
This patch is needed to silence a new gnulib 'make syntax-check' rule in the next patch.
* daemon/libvirtd.c (main): Setup locale and gettext. * src/lxc/lxc_controller.c (main): Likewise. * src/security/virt-aa-helper.c (main): Likewise. * src/storage/parthelper.c (main): Likewise. * tools/virsh.c (main): Fix exit status. * src/internal.h (DEFAULT_TEXT_DOMAIN): Define, for gettext.h. (_): Simplify definition accordingly. * po/POTFILES.in: Add src/storage/parthelper.c. ---
daemon/libvirtd.c | 10 +++++++--- po/POTFILES.in | 1 + src/internal.h | 11 ++++++++--- src/lxc/lxc_controller.c | 9 +++++++++ src/security/security_apparmor.c | 1 + src/security/virt-aa-helper.c | 7 +++++++ src/storage/parthelper.c | 15 ++++++++++++--- tools/virsh.c | 4 ++-- 8 files changed, 47 insertions(+), 11 deletions(-)
ACK Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Allows bootstrap to work on FreeBSD, where gzip doesn't have a '.' in its version; and silences false positives in the new 'make syntax-check' rule. * .gnulib: Update to latest. * bootstrap: Synchronize to upstream. * .x-sc_bindtextdomain: New exemptions. * Makefile.am (syntax_check_exceptions): Ship new file. * .gitignore: Regenerate per latest bootstrap, anchor entries that are only in the root directory, and consolidate entries from other generated .gitignore files. * build-aux/.gitignore, m4/.gitignore, po/.gitignore: Remove from version control, since bootstrap generates them. --- .gitignore | 65 +++++++++++++++++++++++++++---------------------- .gnulib | 2 +- .x-sc_bindtextdomain | 2 + Makefile.am | 1 + bootstrap | 44 +++++++++++++++++++++++---------- build-aux/.gitignore | 16 ------------ m4/.gitignore | 37 ---------------------------- po/.gitignore | 17 ------------- 8 files changed, 70 insertions(+), 114 deletions(-) create mode 100644 .x-sc_bindtextdomain delete mode 100644 build-aux/.gitignore delete mode 100644 m4/.gitignore delete mode 100644 po/.gitignore diff --git a/.gitignore b/.gitignore index a9235b2..f07904c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +!/m4/compiler-flags.m4 +!/po/*.po +!/po/POTFILES.in +!/po/libvirt.pot *#*# *.#*# *.a @@ -12,45 +16,48 @@ .git .git-module-status .sc-start-sc_* +/ABOUT-NLS +/COPYING +/ChangeLog /GNUmakefile +/INSTALL +/NEWS +/aclocal.m4 +/autom4te.cache +/build-aux/ +/config.cache +/config.guess +/config.h +/config.h.in +/config.log +/config.rpath +/config.status +/config.sub +/configure +/configure.lineno +/gnulib/ +/libtool +/libvirt-*.tar.gz /libvirt-[0-9]* +/libvirt.pc +/libvirt.spec +/ltconfig +/ltmain.sh +/m4/ /maint.mk +/mingw32-libvirt.spec +/mkinstalldirs +/po/ /proxy/ -ABOUT-NLS -COPYING -ChangeLog -INSTALL +/tests/*.log +/tests/nwfilterxml2xmltest +/update.log Makefile Makefile.in -NEWS -aclocal.m4 -autom4te.cache -config.cache -config.guess -config.h -config.h.in -config.log -config.rpath -config.status -config.sub -configure -configure.lineno coverage cscope.files cscope.out -gnulib/ -libtool -libvirt-*.tar.gz -libvirt.pc -libvirt.spec -ltconfig -ltmain.sh -mingw32-libvirt.spec -mkinstalldirs results.log stamp-h stamp-h.in stamp-h1 -tests/*.log -tests/nwfilterxml2xmltest -update.log diff --git a/.gnulib b/.gnulib index cac3889..48b1a1a 160000 --- a/.gnulib +++ b/.gnulib @@ -1 +1 @@ -Subproject commit cac3889c1830d38e5b55ae69fc3d458498a0b33e +Subproject commit 48b1a1ae7d5b0f1494aabd4c8a02fbfcec531026 diff --git a/.x-sc_bindtextdomain b/.x-sc_bindtextdomain new file mode 100644 index 0000000..08acb01 --- /dev/null +++ b/.x-sc_bindtextdomain @@ -0,0 +1,2 @@ +^tests/.* +^examples/.* diff --git a/Makefile.am b/Makefile.am index 0a3c24f..e5fad6f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,6 +18,7 @@ syntax_check_exceptions = \ .x-sc_avoid_ctype_macros \ .x-sc_avoid_if_before_free \ .x-sc_avoid_write \ + .x-sc_bindtextdomain \ .x-sc_m4_quote_check \ .x-sc_po_check \ .x-sc_prohibit_always_true_header_tests \ diff --git a/bootstrap b/bootstrap index 2b3f24b..12fec20 100755 --- a/bootstrap +++ b/bootstrap @@ -1,6 +1,6 @@ #! /bin/sh # Print a version string. -scriptversion=2010-10-08.16; # UTC +scriptversion=2010-11-12.21; # UTC # Bootstrap this package from checked-out sources. @@ -261,6 +261,21 @@ insert_sorted_if_absent() { || exit 1 } +# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with +# insert_sorted_if_absent. +insert_vc_ignore() { + vc_ignore_file="$1" + pattern="$2" + case $vc_ignore_file in + *.gitignore) + # A .gitignore entry that does not start with `/' applies + # recursively to subdirectories, so prepend `/' to every + # .gitignore entry. + pattern=`echo "$pattern" | sed s,^,/,`;; + esac + insert_sorted_if_absent "$vc_ignore_file" "$pattern" +} + # Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac. found_aux_dir=no grep '^[ ]*AC_CONFIG_AUX_DIR(\['"$build_aux"'\])' configure.ac \ @@ -279,7 +294,7 @@ if test ! -d $build_aux; then mkdir $build_aux for dot_ig in x $vc_ignore; do test $dot_ig = x && continue - insert_sorted_if_absent $dot_ig $build_aux + insert_vc_ignore $dot_ig $build_aux done fi @@ -329,17 +344,18 @@ get_version() { $app --version >/dev/null 2>&1 || return 1 $app --version 2>&1 | - sed -n '# extract version within line - s/.*[v ]\{1,\}\([0-9]\{1,\}\.[.a-z0-9-]*\).*/\1/ - t done + sed -n '# Move version to start of line. + s/.*[v ]\([0-9]\)/\1/ + + # Skip lines that do not start with version. + /^[0-9]/!d - # extract version at start of line - s/^\([0-9]\{1,\}\.[.a-z0-9-]*\).*/\1/ - t done + # Remove characters after the version. + s/[^.a-z0-9-].*// - d + # The first component must be digits only. + s/^\([0-9]*\)[a-z-].*/\1/ - :done #the following essentially does s/5.005/5.5/ s/\.0*\([1-9]\)/.\1/g p @@ -565,7 +581,7 @@ symlink_to_dir() for dot_ig in x $vc_ignore; do test $dot_ig = x && continue ig=$parent/$dot_ig - insert_sorted_if_absent $ig `echo "$dst_dir"|sed 's,.*/,,'` + insert_vc_ignore $ig `echo "$dst_dir"|sed 's,.*/,,'` done fi @@ -725,7 +741,7 @@ slurp() { test $dot_ig = x && continue ig=$dir/$dot_ig if test -n "$copied"; then - insert_sorted_if_absent $ig "$copied" + insert_vc_ignore $ig "$copied" # If an ignored file name ends with .in.h, then also add # the name with just ".h". Many gnulib headers are generated, # e.g., stdint.in.h -> stdint.h, dirent.in.h ->..., etc. @@ -738,12 +754,12 @@ slurp() { s/\.gperf$/.h/ ' ` - insert_sorted_if_absent $ig "$f" + insert_vc_ignore $ig "$f" # For files like sys_stat.in.h and sys_time.in.h, record as # ignorable the directory we might eventually create: sys/. f=`echo "$copied"|sed 's/sys_.*\.in\.h$/sys/'` - insert_sorted_if_absent $ig "$f" + insert_vc_ignore $ig "$f" fi done done diff --git a/build-aux/.gitignore b/build-aux/.gitignore deleted file mode 100644 index 8717628..0000000 --- a/build-aux/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -* -/arg-nonnull.h -/gitlog-to-changelog -/link-warning.h -/mktempd -/useless-if-before-free -/vc-list-files -arg-nonnull.h -c++defs.h -config.rpath -gitlog-to-changelog -mkinstalldirs -mktempd -useless-if-before-free -vc-list-files -warn-on-use.h diff --git a/m4/.gitignore b/m4/.gitignore deleted file mode 100644 index 030be96..0000000 --- a/m4/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -Makefile -Makefile.in -acinclude.m4 -aclocal.m4 -codeset.m4 -gettext.m4 -glibc21.m4 -iconv.m4 -intdiv0.m4 -intmax.m4 -inttypes-pri.m4 -inttypes.m4 -inttypes_h.m4 -isc-posix.m4 -lcmessage.m4 -lib-ld.m4 -lib-link.m4 -lib-prefix.m4 -libtool.m4 -longdouble.m4 -longlong.m4 -ltoptions.m4 -ltsugar.m4 -ltversion.m4 -lt~obsolete.m4 -nls.m4 -po.m4 -printf-posix.m4 -progtest.m4 -signed.m4 -size_max.m4 -stdint_h.m4 -uintmax_t.m4 -ulonglong.m4 -wchar_t.m4 -wint_t.m4 -xsize.m4 diff --git a/po/.gitignore b/po/.gitignore deleted file mode 100644 index 9f7b57f..0000000 --- a/po/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -*.gmo -Makefile -Makefile.in -Makefile.in.in -Makevars -Makevars.template -POTFILES -Rules-quot -boldquot.sed -en@boldquot.header -en@quot.header -insert-header.sed -insert-header.sin -quot.sed -remove-potcdate.sed -remove-potcdate.sin -stamp-po -- 1.7.3.2

On Tue, Nov 16, 2010 at 03:35:17PM -0700, Eric Blake wrote:
Allows bootstrap to work on FreeBSD, where gzip doesn't have a '.' in its version; and silences false positives in the new 'make syntax-check' rule.
* .gnulib: Update to latest. * bootstrap: Synchronize to upstream. * .x-sc_bindtextdomain: New exemptions. * Makefile.am (syntax_check_exceptions): Ship new file. * .gitignore: Regenerate per latest bootstrap, anchor entries that are only in the root directory, and consolidate entries from other generated .gitignore files. * build-aux/.gitignore, m4/.gitignore, po/.gitignore: Remove from version control, since bootstrap generates them. --- .gitignore | 65 +++++++++++++++++++++++++++---------------------- .gnulib | 2 +- .x-sc_bindtextdomain | 2 + Makefile.am | 1 + bootstrap | 44 +++++++++++++++++++++++---------- build-aux/.gitignore | 16 ------------ m4/.gitignore | 37 ---------------------------- po/.gitignore | 17 ------------- 8 files changed, 70 insertions(+), 114 deletions(-) create mode 100644 .x-sc_bindtextdomain delete mode 100644 build-aux/.gitignore delete mode 100644 m4/.gitignore delete mode 100644 po/.gitignore
ACK Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

These messages are visible to the user, so they should be consistently translated. * cfg.mk (msg_gen_function): Add vah_error, vah_warning. * src/security/virt-aa-helper.c: Translate messages. (catchXMLError): Fix capitalization. --- cfg.mk | 2 + src/security/virt-aa-helper.c | 187 +++++++++++++++++++++-------------------- 2 files changed, 98 insertions(+), 91 deletions(-) diff --git a/cfg.mk b/cfg.mk index d47af80..03d77d5 100644 --- a/cfg.mk +++ b/cfg.mk @@ -337,6 +337,8 @@ msg_gen_function += qemudReportError msg_gen_function += regerror msg_gen_function += remoteDispatchFormatError msg_gen_function += umlReportError +msg_gen_function += vah_error +msg_gen_function += vah_warning msg_gen_function += vboxError msg_gen_function += virConfError msg_gen_function += virDomainReportError diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 3b13298..12adbbb 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1,6 +1,8 @@ /* * virt-aa-helper: wrapper program used by AppArmor security driver. + * + * Copyright (C) 2010 Red Hat, Inc. * Copyright (C) 2009-2010 Canonical Ltd. * * See COPYING.LIB for the License of this software @@ -82,28 +84,28 @@ vahDeinit(vahControl * ctl) static void vah_usage(void) { - fprintf(stdout, "\n%s [options] [< def.xml]\n\n" - " Options:\n" - " -a | --add load profile\n" - " -c | --create create profile from template\n" - " -D | --delete unload and delete profile\n" - " -f | --add-file <file> add file to profile\n" - " -F | --append-file <file> append file to profile\n" - " -r | --replace reload profile\n" - " -R | --remove unload profile\n" - " -h | --help this help\n" - " -u | --uuid <uuid> uuid (profile name)\n" - "\n", progname); - - fprintf(stdout, "This command is intended to be used by libvirtd " - "and not used directly.\n"); + fprintf(stdout, _("\n%s [options] [< def.xml]\n\n + Options:\n + -a | --add load profile\n + -c | --create create profile from template\n + -D | --delete unload and delete profile\n + -f | --add-file <file> add file to profile\n + -F | --append-file <file> append file to profile\n + -r | --replace reload profile\n + -R | --remove unload profile\n + -h | --help this help\n + -u | --uuid <uuid> uuid (profile name)\n +\n", progname); + + fputs(_("This command is intended to be used by libvirtd " + "and not used directly.\n")); return; } static void vah_error(vahControl * ctl, int doexit, const char *str) { - fprintf(stderr, _("%s: error: %s\n"), progname, str); + fprintf(stderr, _("%s: error: %s%c"), progname, str, '\n'); if (doexit) { if (ctl != NULL) @@ -115,13 +117,13 @@ vah_error(vahControl * ctl, int doexit, const char *str) static void vah_warning(const char *str) { - fprintf(stderr, _("%s: warning: %s\n"), progname, str); + fprintf(stderr, _("%s: warning: %s%c"), progname, str, '\n'); } static void vah_info(const char *str) { - fprintf(stderr, _("%s:\n%s\n"), progname, str); + fprintf(stderr, _("%s:\n%s%c"), progname, str, '\n'); } /* @@ -138,12 +140,12 @@ replace_string(char *orig, const size_t len, const char *oldstr, char *tmp = NULL; if ((pos = strstr(orig, oldstr)) == NULL) { - vah_error(NULL, 0, "could not find replacement string"); + vah_error(NULL, 0, _("could not find replacement string")); return -1; } if (VIR_ALLOC_N(tmp, len) < 0) { - vah_error(NULL, 0, "could not allocate memory for string"); + vah_error(NULL, 0, _("could not allocate memory for string")); return -1; } tmp[0] = '\0'; @@ -155,7 +157,7 @@ replace_string(char *orig, const size_t len, const char *oldstr, /* add the replacement string */ if (strlen(tmp) + strlen(repstr) > len - 1) { - vah_error(NULL, 0, "not enough space in target buffer"); + vah_error(NULL, 0, _("not enough space in target buffer")); VIR_FREE(tmp); return -1; } @@ -163,7 +165,7 @@ replace_string(char *orig, const size_t len, const char *oldstr, /* add everything after oldstr */ if (strlen(tmp) + strlen(orig) - (idx + strlen(oldstr)) > len - 1) { - vah_error(NULL, 0, "not enough space in target buffer"); + vah_error(NULL, 0, _("not enough space in target buffer")); VIR_FREE(tmp); return -1; } @@ -171,7 +173,7 @@ replace_string(char *orig, const size_t len, const char *oldstr, strlen(orig) - (idx + strlen(oldstr))); if (virStrcpy(orig, tmp, len) == NULL) { - vah_error(NULL, 0, "error replacing string"); + vah_error(NULL, 0, _("error replacing string")); VIR_FREE(tmp); return -1; } @@ -192,7 +194,7 @@ parserCommand(const char *profile_name, const char cmd) int ret; if (strchr("arR", cmd) == NULL) { - vah_error(NULL, 0, "invalid flag"); + vah_error(NULL, 0, _("invalid flag")); return -1; } @@ -200,12 +202,12 @@ parserCommand(const char *profile_name, const char cmd) if (snprintf(profile, PATH_MAX, "%s/%s", APPARMOR_DIR "/libvirt", profile_name) > PATH_MAX - 1) { - vah_error(NULL, 0, "profile name exceeds maximum length"); + vah_error(NULL, 0, _("profile name exceeds maximum length")); return -1; } if (!virFileExists(profile)) { - vah_error(NULL, 0, "profile does not exist"); + vah_error(NULL, 0, _("profile does not exist")); return -1; } else { const char * const argv[] = { @@ -214,12 +216,13 @@ parserCommand(const char *profile_name, const char cmd) if ((ret = virRun(argv, &status)) != 0 || (WIFEXITED(status) && WEXITSTATUS(status) != 0)) { if (ret != 0) { - vah_error(NULL, 0, "failed to run apparmor_parser"); + vah_error(NULL, 0, _("failed to run apparmor_parser")); return -1; - } else if (cmd == 'R' && WIFEXITED(status) && WEXITSTATUS(status) == 234) { - vah_warning("unable to unload already unloaded profile (non-fatal)"); + } else if (cmd == 'R' && WIFEXITED(status) && + WEXITSTATUS(status) == 234) { + vah_warning(_("unable to unload already unloaded profile")); } else { - vah_error(NULL, 0, "apparmor_parser exited with error"); + vah_error(NULL, 0, _("apparmor_parser exited with error")); return -1; } } @@ -251,19 +254,19 @@ update_include_file(const char *include_file, const char *included_files, if (append && virFileExists(include_file)) { if (virAsprintf(&pcontent, "%s%s", existing, included_files) == -1) { - vah_error(NULL, 0, "could not allocate memory for profile"); + vah_error(NULL, 0, _("could not allocate memory for profile")); goto clean; } } else { if (virAsprintf(&pcontent, "%s%s", warning, included_files) == -1) { - vah_error(NULL, 0, "could not allocate memory for profile"); + vah_error(NULL, 0, _("could not allocate memory for profile")); goto clean; } } plen = strlen(pcontent); if (plen > MAX_FILE_LEN) { - vah_error(NULL, 0, "invalid length for new profile"); + vah_error(NULL, 0, _("invalid length for new profile")); goto clean; } @@ -275,18 +278,18 @@ update_include_file(const char *include_file, const char *included_files, /* write the file */ if ((fd = open(include_file, O_CREAT | O_TRUNC | O_WRONLY, 0644)) == -1) { - vah_error(NULL, 0, "failed to create include file"); + vah_error(NULL, 0, _("failed to create include file")); goto clean; } if (safewrite(fd, pcontent, plen) < 0) { /* don't write the '\0' */ VIR_FORCE_CLOSE(fd); - vah_error(NULL, 0, "failed to write to profile"); + vah_error(NULL, 0, _("failed to write to profile")); goto clean; } if (VIR_CLOSE(fd) != 0) { - vah_error(NULL, 0, "failed to close or write to profile"); + vah_error(NULL, 0, _("failed to close or write to profile")_; goto clean; } rc = 0; @@ -317,45 +320,45 @@ create_profile(const char *profile, const char *profile_name, int rc = -1; if (virFileExists(profile)) { - vah_error(NULL, 0, "profile exists"); + vah_error(NULL, 0, _("profile exists")); goto end; } if (snprintf(template, PATH_MAX, "%s/TEMPLATE", APPARMOR_DIR "/libvirt") > PATH_MAX - 1) { - vah_error(NULL, 0, "template name exceeds maximum length"); + vah_error(NULL, 0, _("template name exceeds maximum length")); goto end; } if (!virFileExists(template)) { - vah_error(NULL, 0, "template does not exist"); + vah_error(NULL, 0, _("template does not exist")); goto end; } if ((tlen = virFileReadAll(template, MAX_FILE_LEN, &tcontent)) < 0) { - vah_error(NULL, 0, "failed to read AppArmor template"); + vah_error(NULL, 0, _("failed to read AppArmor template")); goto end; } if (strstr(tcontent, template_name) == NULL) { - vah_error(NULL, 0, "no replacement string in template"); + vah_error(NULL, 0, _("no replacement string in template")); goto clean_tcontent; } if (strstr(tcontent, template_end) == NULL) { - vah_error(NULL, 0, "no replacement string in template"); + vah_error(NULL, 0, _("no replacement string in template")); goto clean_tcontent; } /* '\nprofile <profile_name>\0' */ if (virAsprintf(&replace_name, "\nprofile %s", profile_name) == -1) { - vah_error(NULL, 0, "could not allocate memory for profile name"); + vah_error(NULL, 0, _("could not allocate memory for profile name")); goto clean_tcontent; } /* '\n<profile_files>\n}\0' */ if (virAsprintf(&replace_files, "\n%s\n}", profile_files) == -1) { - vah_error(NULL, 0, "could not allocate memory for profile files"); + vah_error(NULL, 0, _("could not allocate memory for profile files")); VIR_FREE(replace_name); goto clean_tcontent; } @@ -363,12 +366,12 @@ create_profile(const char *profile, const char *profile_name, plen = tlen + strlen(replace_name) - strlen(template_name) + strlen(replace_files) - strlen(template_end) + 1; if (plen > MAX_FILE_LEN || plen < tlen) { - vah_error(NULL, 0, "invalid length for new profile"); + vah_error(NULL, 0, _("invalid length for new profile")); goto clean_replace; } if (VIR_ALLOC_N(pcontent, plen) < 0) { - vah_error(NULL, 0, "could not allocate memory for profile"); + vah_error(NULL, 0, _("could not allocate memory for profile")); goto clean_replace; } pcontent[0] = '\0'; @@ -382,18 +385,18 @@ create_profile(const char *profile, const char *profile_name, /* write the file */ if ((fd = open(profile, O_CREAT | O_EXCL | O_WRONLY, 0644)) == -1) { - vah_error(NULL, 0, "failed to create profile"); + vah_error(NULL, 0, _("failed to create profile")); goto clean_all; } if (safewrite(fd, pcontent, plen - 1) < 0) { /* don't write the '\0' */ VIR_FORCE_CLOSE(fd); - vah_error(NULL, 0, "failed to write to profile"); + vah_error(NULL, 0, _("failed to write to profile")); goto clean_all; } if (VIR_CLOSE(fd) != 0) { - vah_error(NULL, 0, "failed to close or write to profile"); + vah_error(NULL, 0, _("failed to close or write to profile")_; goto clean_all; } rc = 0; @@ -532,7 +535,7 @@ valid_path(const char *path, const bool readonly) }; if (path == NULL || strlen(path) > PATH_MAX - 1) { - vah_error(NULL, 0, "bad pathname"); + vah_error(NULL, 0, _("bad pathname")); return -1; } @@ -547,7 +550,7 @@ valid_path(const char *path, const bool readonly) return 1; if (!virFileExists(path)) - vah_warning("path does not exist, skipping file type checks"); + vah_warning(_("path does not exist, skipping file type checks")); else { if (stat(path, &sb) == -1) return -1; @@ -597,7 +600,7 @@ catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) if (virAsprintf(&err_str, "XML error at line %d: %s", ctxt->lastError.line, ctxt->lastError.message) == -1) - vah_error(NULL, 0, "Could not get XML error"); + vah_error(NULL, 0, _("could not get XML error")); else { vah_error(NULL, 0, err_str); VIR_FREE(err_str); @@ -613,20 +616,20 @@ verify_xpath_context(xmlXPathContextPtr ctxt) char *tmp = NULL; if (!ctxt) { - vah_warning("Invalid context"); + vah_warning(_("Invalid context")); goto error; } /* check if have <name> */ if (!(tmp = virXPathString("string(./name[1])", ctxt))) { - vah_warning("Could not find <name>"); + vah_warning(_("Could not find <name>")); goto error; } VIR_FREE(tmp); /* check if have <uuid> */ if (!(tmp = virXPathString("string(./uuid[1])", ctxt))) { - vah_warning("Could not find <uuid>"); + vah_warning(_("Could not find <uuid>")); goto error; } VIR_FREE(tmp); @@ -665,22 +668,22 @@ caps_mockup(vahControl * ctl, const char *xmlStr) XML_PARSE_NOWARNING); if (!xml) { if (virGetLastError() == NULL) - vah_error(NULL, 0, "failed to parse xml document"); + vah_error(NULL, 0, _("failed to parse xml document")); goto cleanup; } if ((root = xmlDocGetRootElement(xml)) == NULL) { - vah_error(NULL, 0, "missing root element"); + vah_error(NULL, 0, _("missing root element")); goto cleanup; } if (!xmlStrEqual(root->name, BAD_CAST "domain")) { - vah_error(NULL, 0, "incorrect root element"); + vah_error(NULL, 0, _("incorrect root element")); goto cleanup; } if ((ctxt = xmlXPathNewContext(xml)) == NULL) { - vah_error(ctl, 0, "could not allocate memory"); + vah_error(ctl, 0, _("could not allocate memory")); goto cleanup; } ctxt->node = root; @@ -691,7 +694,7 @@ caps_mockup(vahControl * ctl, const char *xmlStr) ctl->hvm = virXPathString("string(./os/type[1])", ctxt); if (!ctl->hvm || STRNEQ(ctl->hvm, "hvm")) { - vah_error(ctl, 0, "os.type is not 'hvm'"); + vah_error(ctl, 0, _("os.type is not 'hvm'")); goto cleanup; } ctl->arch = virXPathString("string(./os/type[1]/@arch)", ctxt); @@ -704,7 +707,7 @@ caps_mockup(vahControl * ctl, const char *xmlStr) /* Really, this never fails - look at the man-page. */ uname (&utsname); if ((ctl->arch = strdup(utsname.machine)) == NULL) { - vah_error(ctl, 0, "could not allocate memory"); + vah_error(ctl, 0, _("could not allocate memory")); goto cleanup; } } @@ -737,7 +740,7 @@ get_definition(vahControl * ctl, const char *xmlStr) goto exit; if ((ctl->caps = virCapabilitiesNew(ctl->arch, 1, 1)) == NULL) { - vah_error(ctl, 0, "could not allocate memory"); + vah_error(ctl, 0, _("could not allocate memory")); goto exit; } @@ -749,24 +752,24 @@ get_definition(vahControl * ctl, const char *xmlStr) NULL, 0, NULL)) == NULL) { - vah_error(ctl, 0, "could not allocate memory"); + vah_error(ctl, 0, _("could not allocate memory")); goto exit; } ctl->def = virDomainDefParseString(ctl->caps, xmlStr, VIR_DOMAIN_XML_INACTIVE); if (ctl->def == NULL) { - vah_error(ctl, 0, "could not parse XML"); + vah_error(ctl, 0, _("could not parse XML")); goto exit; } if (!ctl->def->name) { - vah_error(ctl, 0, "could not find name in XML"); + vah_error(ctl, 0, _("could not find name in XML")); goto exit; } if (valid_name(ctl->def->name) != 0) { - vah_error(ctl, 0, "bad name"); + vah_error(ctl, 0, _("bad name")); goto exit; } @@ -792,14 +795,14 @@ vah_add_file(virBufferPtr buf, const char *path, const char *perms) */ if (STRNEQLEN(path, "/", 1)) { vah_warning(path); - vah_warning(" skipped non-absolute path"); + vah_warning(_(" skipped non-absolute path")); return 0; } if (virFileExists(path)) { if ((tmp = realpath(path, NULL)) == NULL) { vah_error(NULL, 0, path); - vah_error(NULL, 0, " could not find realpath for disk"); + vah_error(NULL, 0, _(" could not find realpath for disk")); return rc; } } else @@ -813,7 +816,7 @@ vah_add_file(virBufferPtr buf, const char *path, const char *perms) if (rc != 0) { if (rc > 0) { vah_error(NULL, 0, path); - vah_error(NULL, 0, " skipped restricted file"); + vah_error(NULL, 0, _(" skipped restricted file")); } goto clean; } @@ -883,12 +886,12 @@ get_files(vahControl * ctl) /* verify uuid is same as what we were given on the command line */ virUUIDFormat(ctl->def->uuid, uuidstr); if (virAsprintf(&uuid, "%s%s", AA_PREFIX, uuidstr) == -1) { - vah_error(ctl, 0, "could not allocate memory"); + vah_error(ctl, 0, _("could not allocate memory")); return rc; } if (STRNEQ(uuid, ctl->uuid)) { - vah_error(ctl, 0, "given uuid does not match XML uuid"); + vah_error(ctl, 0, _("given uuid does not match XML uuid")); goto clean; } @@ -1009,7 +1012,7 @@ get_files(vahControl * ctl) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); - vah_error(NULL, 0, "failed to allocate file buffer"); + vah_error(NULL, 0, _("failed to allocate file buffer")); goto clean; } @@ -1058,7 +1061,7 @@ vahParseArgv(vahControl * ctl, int argc, char **argv) case 'f': case 'F': if ((ctl->newfile = strdup(optarg)) == NULL) - vah_error(ctl, 1, "could not allocate memory for disk"); + vah_error(ctl, 1, _("could not allocate memory for disk")_; ctl->append = arg == 'F'; break; case 'h': @@ -1073,10 +1076,10 @@ vahParseArgv(vahControl * ctl, int argc, char **argv) break; case 'u': if (strlen(optarg) > PROFILE_NAME_SIZE - 1) - vah_error(ctl, 1, "invalid UUID"); + vah_error(ctl, 1, _("invalid UUID")); if (virStrcpy((char *) ctl->uuid, optarg, PROFILE_NAME_SIZE) == NULL) - vah_error(ctl, 1, "error copying UUID"); + vah_error(ctl, 1, _("error copying UUID")); break; case 'p': if (STREQ(optarg, "1")) @@ -1085,15 +1088,15 @@ vahParseArgv(vahControl * ctl, int argc, char **argv) ctl->allowDiskFormatProbing = false; break; default: - vah_error(ctl, 1, "unsupported option"); + vah_error(ctl, 1, _("unsupported option")); break; } } if (strchr("acDrR", ctl->cmd) == NULL) - vah_error(ctl, 1, "bad command"); + vah_error(ctl, 1, _("bad command")); if (valid_uuid(ctl->uuid) != 0) - vah_error(ctl, 1, "invalid UUID"); + vah_error(ctl, 1, _("invalid UUID")); if (!ctl->cmd) { vah_usage(); @@ -1103,16 +1106,16 @@ vahParseArgv(vahControl * ctl, int argc, char **argv) if (ctl->cmd == 'c' || ctl->cmd == 'r') { char *xmlStr = NULL; if (virFileReadLimFD(STDIN_FILENO, MAX_FILE_LEN, &xmlStr) < 0) - vah_error(ctl, 1, "could not read xml file"); + vah_error(ctl, 1, _("could not read xml file")); if (get_definition(ctl, xmlStr) != 0 || ctl->def == NULL) { VIR_FREE(xmlStr); - vah_error(ctl, 1, "could not get VM definition"); + vah_error(ctl, 1, _("could not get VM definition")); } VIR_FREE(xmlStr); if (get_files(ctl) != 0) - vah_error(ctl, 1, "invalid VM definition"); + vah_error(ctl, 1, _("invalid VM definition")); } return 0; } @@ -1144,10 +1147,11 @@ main(int argc, char **argv) /* clear the environment */ environ = NULL; if (setenv("PATH", "/sbin:/usr/sbin", 1) != 0) { - vah_error(ctl, 1, "could not set PATH"); + vah_error(ctl, 1, _("could not set PATH")); } + if (setenv("IFS", " \t\n", 1) != 0) { - vah_error(ctl, 1, "could not set IFS"); + vah_error(ctl, 1, _("could not set IFS")); } if (!(progname = strrchr(argv[0], '/'))) @@ -1158,15 +1162,15 @@ main(int argc, char **argv) memset(ctl, 0, sizeof(vahControl)); if (vahParseArgv(ctl, argc, argv) != 0) - vah_error(ctl, 1, "could not parse arguments"); + vah_error(ctl, 1, _("could not parse arguments")); if (snprintf(profile, PATH_MAX, "%s/%s", APPARMOR_DIR "/libvirt", ctl->uuid) > PATH_MAX - 1) - vah_error(ctl, 1, "profile name exceeds maximum length"); + vah_error(ctl, 1, _("profile name exceeds maximum length")); if (snprintf(include_file, PATH_MAX, "%s/%s.files", APPARMOR_DIR "/libvirt", ctl->uuid) > PATH_MAX - 1) - vah_error(ctl, 1, "disk profile name exceeds maximum length"); + vah_error(ctl, 1, _("disk profile name exceeds maximum length")); if (ctl->cmd == 'a') rc = parserLoad(ctl->uuid); @@ -1179,8 +1183,9 @@ main(int argc, char **argv) } else if (ctl->cmd == 'c' || ctl->cmd == 'r') { char *included_files = NULL; - if (ctl->cmd == 'c' && virFileExists(profile)) - vah_error(ctl, 1, "profile exists"); + if (ctl->cmd == 'c' && virFileExists(profile)) { + vah_error(ctl, 1, _("profile exists")); + } if (ctl->append && ctl->newfile) { if (vah_add_file(&buf, ctl->newfile, "rw") != 0) @@ -1198,7 +1203,7 @@ main(int argc, char **argv) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); - vah_error(ctl, 1, "failed to allocate buffer"); + vah_error(ctl, 1, _("failed to allocate buffer")); } included_files = virBufferContentAndReset(&buf); @@ -1219,7 +1224,7 @@ main(int argc, char **argv) char *tmp = NULL; if (virAsprintf(&tmp, " #include <libvirt/%s.files>\n", ctl->uuid) == -1) { - vah_error(ctl, 0, "could not allocate memory"); + vah_error(ctl, 0, _("could not allocate memory")); goto clean; } @@ -1229,7 +1234,7 @@ main(int argc, char **argv) vah_info(tmp); rc = 0; } else if ((rc = create_profile(profile, ctl->uuid, tmp)) != 0) { - vah_error(ctl, 0, "could not create profile"); + vah_error(ctl, 0, _("could not create profile")); unlink(include_file); } VIR_FREE(tmp); -- 1.7.3.2

On Tue, Nov 16, 2010 at 03:35:18PM -0700, Eric Blake wrote:
These messages are visible to the user, so they should be consistently translated.
* cfg.mk (msg_gen_function): Add vah_error, vah_warning. * src/security/virt-aa-helper.c: Translate messages. (catchXMLError): Fix capitalization. --- cfg.mk | 2 + src/security/virt-aa-helper.c | 187 +++++++++++++++++++++-------------------- 2 files changed, 98 insertions(+), 91 deletions(-)
ACK Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On 11/17/2010 07:34 AM, Daniel P. Berrange wrote:
On Tue, Nov 16, 2010 at 03:35:18PM -0700, Eric Blake wrote:
These messages are visible to the user, so they should be consistently translated.
* cfg.mk (msg_gen_function): Add vah_error, vah_warning. * src/security/virt-aa-helper.c: Translate messages. (catchXMLError): Fix capitalization. --- cfg.mk | 2 + src/security/virt-aa-helper.c | 187 +++++++++++++++++++++-------------------- 2 files changed, 98 insertions(+), 91 deletions(-)
ACK
Thanks; series is pushed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org
participants (2)
-
Daniel P. Berrange
-
Eric Blake