Remove the configure-time QEMU definition. No longer initialize g->hv
= QEMU. g->hv may now be NULL if the user does not explicitly either
call guestfs_set_hv or set LIBGUESTFS_HV.
Remove any assumptions in the code that g->hv is always non-NULL.
Fix one test that relied on the QEMU definition.
Change the implementation of guestfs_get_hv so that if a custom
hypervisor was not set (eg. by an earlier call to guestfs_set_hv) then
we will return the default hypervisor reported by the backend.
This changes the API slightly because we can now return an error here
in the libvirt backend case if the appliance has not been launched
yet.
Run this command across the source:
perl -pi.bak -e 's/(20[012][0-9])-20[12][012]/$1-2023/g' `git ls-files`
and remove changes to po{,-docs}/*.po{,t} (these will be regenerated
later when we run 'make dist').
This gnulib feature abstracts away threads, locks and TLS, and also
allowed libguestfs to be linked with or without pthread. However
since pthread these days is part of glibc and so every program is
using pthread, and we want to get rid of gnulib as a dependency, just
use pthread directly.
The 'localmountpoint' variable in the handle is available only when
building with FUSE support, so guard it in a proper #ifdef block.
Fixes commit 296370fb86.
Thanks to: Corentin Labbe (both reporting, and testing)
"localmountpoint" parameter is allocated in JNI before calling
mount_local and freed afterward. But guestfs handle keeps reference
to passed "localmountpoint" parameter and will try to access it in
umount_local and free after mount_local_run caller thread ends
which leads to a crash (an attempt to access to already freed memory).
RWMJ: Remove ‘const’ from definition of localmountpoint, and
wrap a comment at 80 columns.
We permit the following constructs in libguestfs code:
if (guestfs_some_call (g) == -1) {
fprintf (stderr, "failed: error is %s\n", guestfs_last_error (g));
}
and:
guestfs_push_error_handler (g, NULL, NULL);
guestfs_some_call (g);
guestfs_pop_error_handler (g);
Neither of these would be safe if we allowed the handle to be used
from threads concurrently, since the error string or error handler
could be changed by another thread.
Solve this in approximately the same way that libvirt does: by making
the error, current error handler, and stack of error handlers use
thread-local storage (TLS).
The implementation is not entirely straightforward, mainly because
POSIX doesn't give us useful destructor behaviour, so effectively we
end up creating our own destructor using a linked list.
Note that you have to set the error handler in each thread separately,
which is an API change (eg: if you set the error handler in one
thread, then pass the handle 'g' to another thread, the error handler
in the second thread appears to have reset itself back to the default
error handler). I haven't yet worked out a better way to solve this.
Acquire the per-handle lock on entering each public API function.
The lock is released by a cleanup handler, so we only need to use the
ACQUIRE_LOCK_FOR_CURRENT_SCOPE macro at the top of each function.
Note this means we require __attribute__((cleanup)). On platforms
where this is not supported, the code will probably hang whenever a
libguestfs function is called.
The only definitive list of public APIs is found indirectly in the
generator (in generator/c.ml : globals).
Only in end-user messages and documentation. This change was done
mostly mechanically using the Perl script attached below.
I also changed don't -> don’t etc and made some other simple fixes.
See also: https://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html
----------
#!/usr/bin/perl -w
use strict;
use Locale::PO;
my $re = qr{'([-\w%.,=?*/]+)'};
my %files = ();
foreach my $filename ("po/libguestfs.pot", "po-docs/libguestfs-docs.pot") {
my $poref = Locale::PO->load_file_asarray($filename);
foreach my $po (@$poref) {
if ($po->msgid =~ $re) {
my @refs = split /\s+/, $po->reference;
foreach my $ref (@refs) {
my ($file, $lineno) = split /:/, $ref, 2;
$file =~ s{^\.\./}{};
if (exists $files{$file}) {
push @{$files{$file}}, $lineno;
} else {
$files{$file} = [$lineno];
}
}
}
}
}
foreach my $file (sort keys %files) {
unless (-w $file) {
warn "warning: $file is probably generated\n"; # have to edit generator
next;
}
my @lines = sort { $a <=> $b } @{$files{$file}};
#print "editing $file at lines ", join (", ", @lines), " ...\n";
open FILE, "<$file" or die "$file: $!";
my @all = ();
push @all, $_ while <FILE>;
close FILE;
my $ext = $file;
$ext =~ s/^.*\.//;
foreach (@lines) {
# Don't mess with verbatim sections in POD files.
next if $ext eq "pod" && $all[$_-1] =~ m/^ /;
unless ($all[$_-1] =~ $re) {
# this can happen for multi-line strings, have to edit it
# by hand
warn "warning: $file:$_ does not contain expected content\n";
next;
}
$all[$_-1] =~ s/$re/‘$1’/g;
}
rename "$file", "$file.bak";
open FILE, ">$file" or die "$file: $!";
print FILE $_ for @all;
close FILE;
my $mode = (stat ("$file.bak"))[2];
chmod ($mode & 0777, "$file");
}