mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 16:26:17 +00:00
Compare commits
182 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00100179e4 | ||
|
|
36e4541018 | ||
|
|
0e3962be90 | ||
|
|
949d98813d | ||
|
|
f09fa59193 | ||
|
|
c8002212c5 | ||
|
|
af081cd2c9 | ||
|
|
e494a59921 | ||
|
|
5d63cfc346 | ||
|
|
74cd1b4a70 | ||
|
|
33e3c51421 | ||
|
|
1541c3381a | ||
|
|
c039ce86da | ||
|
|
ae8172b8ff | ||
|
|
a37b8356f0 | ||
|
|
830a2d29d9 | ||
|
|
b466dba1ba | ||
|
|
677453aef1 | ||
|
|
7ad3300b40 | ||
|
|
60e2396365 | ||
|
|
9729402e75 | ||
|
|
705f1a74f5 | ||
|
|
3cd506f36e | ||
|
|
346837f99a | ||
|
|
e36f683bb0 | ||
|
|
21dc351f30 | ||
|
|
d5cc91cf18 | ||
|
|
880374c6df | ||
|
|
7b45f7d04f | ||
|
|
d222efeb15 | ||
|
|
a21dff8faa | ||
|
|
b2ad24867d | ||
|
|
3effae351d | ||
|
|
978dec6706 | ||
|
|
73f89a8174 | ||
|
|
95513e8b43 | ||
|
|
bd13469de8 | ||
|
|
913d5cd3a9 | ||
|
|
accc5488a6 | ||
|
|
92e741835b | ||
|
|
dfd1aa563d | ||
|
|
2fca903769 | ||
|
|
ddb10a9aaf | ||
|
|
ef9f07095f | ||
|
|
6cbff91612 | ||
|
|
00a412ac4f | ||
|
|
f0bea00cc5 | ||
|
|
4e8dda6ae5 | ||
|
|
7273f8f271 | ||
|
|
d614d63b76 | ||
|
|
c8a63e8e72 | ||
|
|
45dbb6f4a6 | ||
|
|
1a1be3e66f | ||
|
|
a583906233 | ||
|
|
6cdd349e69 | ||
|
|
210c4ccefb | ||
|
|
b83dc098ab | ||
|
|
20f8e7c6b5 | ||
|
|
e81916e42e | ||
|
|
d83c866ca3 | ||
|
|
82a9bfb8de | ||
|
|
f632b8cb7b | ||
|
|
96905d6a27 | ||
|
|
bd7ff2f332 | ||
|
|
4ff259db46 | ||
|
|
76014765dd | ||
|
|
faa0c22cce | ||
|
|
df4dce74a8 | ||
|
|
ec64a41858 | ||
|
|
36026b1448 | ||
|
|
76435db1ad | ||
|
|
5a9d47dae1 | ||
|
|
b6e2e1f8dd | ||
|
|
d50c5f4c7d | ||
|
|
7a2317156b | ||
|
|
c018c39cc9 | ||
|
|
57261c712d | ||
|
|
3bc613e925 | ||
|
|
b40f442f41 | ||
|
|
ee993d1a4d | ||
|
|
7ef60bb65d | ||
|
|
2e4669d6e7 | ||
|
|
f6c8665a72 | ||
|
|
2b0f806e5b | ||
|
|
e3dddaaddc | ||
|
|
8236fd4ffd | ||
|
|
b9c70b9ff5 | ||
|
|
21df39f204 | ||
|
|
22ec8330ac | ||
|
|
7095ab748b | ||
|
|
93e27c2154 | ||
|
|
739431339b | ||
|
|
49f08be012 | ||
|
|
a0a8b40efd | ||
|
|
5839078c60 | ||
|
|
a41b116767 | ||
|
|
97245561cf | ||
|
|
aff24a249a | ||
|
|
d31af99180 | ||
|
|
b61fddabaf | ||
|
|
79a91703d9 | ||
|
|
3e549d8668 | ||
|
|
e3bb27af94 | ||
|
|
7b367b4d92 | ||
|
|
5bae163aa7 | ||
|
|
f12fe37e0f | ||
|
|
aea6fabc7d | ||
|
|
56bbd76313 | ||
|
|
821083b1c4 | ||
|
|
1fba33e4ba | ||
|
|
1f94d8dcc7 | ||
|
|
5508573951 | ||
|
|
c9f47f5a6f | ||
|
|
7c2b0646d1 | ||
|
|
7ffaf84497 | ||
|
|
2f88a20d30 | ||
|
|
b4d99ebce5 | ||
|
|
066d14d138 | ||
|
|
55fe8a1d1b | ||
|
|
26679e94f5 | ||
|
|
2e495f3f50 | ||
|
|
f64011b6d7 | ||
|
|
1521c64102 | ||
|
|
f3240bc31e | ||
|
|
edffc79f70 | ||
|
|
93d9d50ac8 | ||
|
|
897f9d26bc | ||
|
|
e160acc6a2 | ||
|
|
1d32d70553 | ||
|
|
9cbbe5bda0 | ||
|
|
750a338725 | ||
|
|
6d403edd96 | ||
|
|
18477ae349 | ||
|
|
2b2651a690 | ||
|
|
8bd3f92e17 | ||
|
|
dd92597346 | ||
|
|
831dbc97f9 | ||
|
|
f72a3c4742 | ||
|
|
520552c12d | ||
|
|
10faedab12 | ||
|
|
9b488a0c9e | ||
|
|
bce26e15ee | ||
|
|
1d3900b126 | ||
|
|
99513f6256 | ||
|
|
7a4dec9994 | ||
|
|
658fb1759d | ||
|
|
1560fd52c9 | ||
|
|
5796576e8b | ||
|
|
e41776d042 | ||
|
|
97e66259f3 | ||
|
|
a6a6d761e1 | ||
|
|
bca76363eb | ||
|
|
3b4ff15f15 | ||
|
|
5b656fac03 | ||
|
|
03ac08e523 | ||
|
|
0309719307 | ||
|
|
7fdd632ec0 | ||
|
|
8fd6edf2e6 | ||
|
|
febf614d7e | ||
|
|
d544076459 | ||
|
|
2e9122d8ce | ||
|
|
bbd812bb06 | ||
|
|
c243d66c25 | ||
|
|
0fd1ab8e0f | ||
|
|
a38330ca19 | ||
|
|
ce3e858e84 | ||
|
|
10402b45d9 | ||
|
|
8162b612f6 | ||
|
|
e4f1a25116 | ||
|
|
8b665274e3 | ||
|
|
cde2df4006 | ||
|
|
e16eb8b673 | ||
|
|
d4eb238577 | ||
|
|
c7328142c9 | ||
|
|
0699e05354 | ||
|
|
5c02176d3e | ||
|
|
acdf84dc39 | ||
|
|
10a7a10de9 | ||
|
|
8e99fde5fc | ||
|
|
54ffbc2f3f | ||
|
|
36683d7ea1 | ||
|
|
e53f651868 |
18
.gitignore
vendored
18
.gitignore
vendored
@@ -74,7 +74,11 @@ fish/cmds.c
|
||||
fish/cmds_gperf.c
|
||||
fish/cmds_gperf.gperf
|
||||
fish/completion.c
|
||||
fish/fish-cmds.h
|
||||
fish/guestfish
|
||||
fish/guestfish.1
|
||||
fish/guestfish-actions.pod
|
||||
fish/guestfish-commands.pod
|
||||
fish/prepopts.c
|
||||
fish/prepopts.h
|
||||
fish/rc_protocol.c
|
||||
@@ -87,13 +91,6 @@ generator/.pod2text.data*
|
||||
generator/files-generated.txt
|
||||
generator/generator
|
||||
generator/stamp-generator
|
||||
guestfish.1
|
||||
guestfish-actions.pod
|
||||
guestfish-commands.pod
|
||||
guestfs.3
|
||||
guestfs-actions.pod
|
||||
guestfs-availability.pod
|
||||
guestfs-structs.pod
|
||||
guestfsd-in-wine.log
|
||||
haskell/Bindtests
|
||||
haskell/Bindtests.hs
|
||||
@@ -209,6 +206,7 @@ perl/lib/Sys/Guestfs.pm
|
||||
perl/Makefile-pl
|
||||
perl/Makefile-pl.old
|
||||
perl/Makefile.PL
|
||||
perl/MYMETA.yml
|
||||
perl/pm_to_blib
|
||||
php/extension/Makefile.fragments
|
||||
php/extension/Makefile.global
|
||||
@@ -223,6 +221,7 @@ php/extension/guestfs_php_*.exp
|
||||
php/extension/guestfs_php_*.log
|
||||
php/extension/guestfs_php_*.out
|
||||
php/extension/guestfs_php_*.php
|
||||
php/extension/guestfs_php_*.sh
|
||||
php/extension/mkinstalldirs
|
||||
php/extension/modules/
|
||||
php/extension/php_guestfs_php.h
|
||||
@@ -284,6 +283,10 @@ src/guestfs-internal-actions.h
|
||||
src/guestfs_protocol.c
|
||||
src/guestfs_protocol.h
|
||||
src/guestfs_protocol.x
|
||||
src/guestfs.3
|
||||
src/guestfs-actions.pod
|
||||
src/guestfs-availability.pod
|
||||
src/guestfs-structs.pod
|
||||
src/.libs/libguestfs.so
|
||||
src/libguestfs.syms
|
||||
src/stamp-guestfs.pod
|
||||
@@ -301,3 +304,4 @@ tools/virt-*.pl
|
||||
/build-aux
|
||||
/gnulib
|
||||
.git-module-status
|
||||
.guestfs-*
|
||||
|
||||
3
AUTHORS
3
AUTHORS
@@ -1,13 +1,16 @@
|
||||
Angus Salkeld
|
||||
Ani Peter
|
||||
Charles Duffy
|
||||
Daniel Berrange
|
||||
Daniel Cabrera
|
||||
Douglas Schilling Landgraf
|
||||
Geert Warrink
|
||||
Guido Günther
|
||||
Jim Meyering
|
||||
Karel Klíč
|
||||
Matthew Booth
|
||||
Maxim Koltsov
|
||||
Nikita A Menkovich
|
||||
Piotr Drąg
|
||||
Rajesh Ranjan
|
||||
Richard W.M. Jones
|
||||
|
||||
340
BUGS
340
BUGS
@@ -1,5 +1,5 @@
|
||||
NOTE: This file is automatically generated from "update-bugs.sh".
|
||||
Last updated: 2010-12-19 15:38:46
|
||||
Last updated: 2011-09-16
|
||||
|
||||
This contains a local list of the bugs that are open against
|
||||
libguestfs. Bugs are tracked in the Red Hat Bugzilla database
|
||||
@@ -20,44 +20,74 @@ When reporting a new bug, please check:
|
||||
--------------------------------------------------
|
||||
Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
|
||||
676020 NEW https://bugzilla.redhat.com/show_bug.cgi?id=676020
|
||||
After using virt-resize with an ntfs partition windows is not booting
|
||||
|
||||
684486 NEW https://bugzilla.redhat.com/show_bug.cgi?id=684486
|
||||
Guest fails to boot after virt-resize
|
||||
|
||||
691659 NEW https://bugzilla.redhat.com/show_bug.cgi?id=691659
|
||||
libguestfs fails to run under JRuby 1.6.0
|
||||
|
||||
693064 NEW https://bugzilla.redhat.com/show_bug.cgi?id=693064
|
||||
Symbolic links on ntfs-3g are not followed correctly by some commands
|
||||
|
||||
693359 NEW https://bugzilla.redhat.com/show_bug.cgi?id=693359
|
||||
virt-cat and virt-edit don't handle case sensitive NTFS paths properly
|
||||
|
||||
701814 NEW https://bugzilla.redhat.com/show_bug.cgi?id=701814
|
||||
virt-win-reg fails on a libvirt guest that has no defined disk format: "format parameter is empty or contains disallowed characters"
|
||||
|
||||
709326 NEW https://bugzilla.redhat.com/show_bug.cgi?id=709326
|
||||
virt-inspector cannot detect ReactOS
|
||||
|
||||
719879 NEW https://bugzilla.redhat.com/show_bug.cgi?id=719879
|
||||
Rebase libguestfs in RHEL 6.3
|
||||
|
||||
723474 NEW https://bugzilla.redhat.com/show_bug.cgi?id=723474
|
||||
If hivex and/or pcre not installed, libguestfs fails to compile
|
||||
|
||||
728224 NEW https://bugzilla.redhat.com/show_bug.cgi?id=728224
|
||||
configure can't find qemu on PPC
|
||||
|
||||
729075 NEW https://bugzilla.redhat.com/show_bug.cgi?id=729075
|
||||
libguestfs confuses Hp_recovery partition with Windows root filesystem
|
||||
|
||||
729076 NEW https://bugzilla.redhat.com/show_bug.cgi?id=729076
|
||||
libguestfs confuses Hp_recovery partition with Windows root filesystem
|
||||
|
||||
731742 NEW https://bugzilla.redhat.com/show_bug.cgi?id=731742
|
||||
libguestfs should escape special/non-printing characters in debug output
|
||||
|
||||
737261 NEW https://bugzilla.redhat.com/show_bug.cgi?id=737261
|
||||
F16 TC2 DVD grub/grub2 conflict
|
||||
|
||||
737944 NEW https://bugzilla.redhat.com/show_bug.cgi?id=737944
|
||||
virt-win-reg hyphen (delete key) syntax may be wrong, and is not documented
|
||||
|
||||
563450 NEW https://bugzilla.redhat.com/show_bug.cgi?id=563450
|
||||
list-devices returns devices of different types out of order
|
||||
|
||||
627835 NEW https://bugzilla.redhat.com/show_bug.cgi?id=627835
|
||||
libguestfs protocol loses synchronization if you 'upload' before mounting disks
|
||||
696445 NEW https://bugzilla.redhat.com/show_bug.cgi?id=696445
|
||||
Backport virt-inspector for virt-v2v
|
||||
|
||||
547488 NEW https://bugzilla.redhat.com/show_bug.cgi?id=547488
|
||||
guestfish cannot tab complete filenames that contain spaces
|
||||
|
||||
627833 NEW https://bugzilla.redhat.com/show_bug.cgi?id=627833
|
||||
get-e2uuid should use blkid instead of "tune2fs -l" to get filesystem UUID
|
||||
672485 NEW https://bugzilla.redhat.com/show_bug.cgi?id=672485
|
||||
[RFE] virt-edit/tar/inspector do not support encrypted system
|
||||
|
||||
633174 NEW https://bugzilla.redhat.com/show_bug.cgi?id=633174
|
||||
some guestfish sub commands can not handle special files properly
|
||||
|
||||
643991 NEW https://bugzilla.redhat.com/show_bug.cgi?id=643991
|
||||
CVE-2010-3851 libguestfs: missing disk format specifier when adding a disk [fedora-all]
|
||||
|
||||
657472 NEW https://bugzilla.redhat.com/show_bug.cgi?id=657472
|
||||
checksum: wrong check sum type causes umount to fail
|
||||
|
||||
501884 NEW https://bugzilla.redhat.com/show_bug.cgi?id=501884
|
||||
virt-inspector still configured, even if there are missing deps
|
||||
|
||||
501886 NEW https://bugzilla.redhat.com/show_bug.cgi?id=501886
|
||||
exec: chroot not found
|
||||
679737 NEW https://bugzilla.redhat.com/show_bug.cgi?id=679737
|
||||
zerofree is unavailable
|
||||
|
||||
507278 NEW https://bugzilla.redhat.com/show_bug.cgi?id=507278
|
||||
libguestfs fails to build on Fedora sparc64
|
||||
|
||||
547479 NEW https://bugzilla.redhat.com/show_bug.cgi?id=547479
|
||||
NTFS partitions sometimes fail to mount if mounted read/write
|
||||
|
||||
554829 NEW https://bugzilla.redhat.com/show_bug.cgi?id=554829
|
||||
SELinux handling could be done better.
|
||||
|
||||
555803 NEW https://bugzilla.redhat.com/show_bug.cgi?id=555803
|
||||
virt-tar error: tgz_out error in chunked encoding
|
||||
guestfs_tgz_out does not detect failure of tar command
|
||||
|
||||
572337 NEW https://bugzilla.redhat.com/show_bug.cgi?id=572337
|
||||
libguestfs should support gptsync
|
||||
@@ -77,54 +107,18 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
596761 NEW https://bugzilla.redhat.com/show_bug.cgi?id=596761
|
||||
Ctrl- causes guestfish to abort
|
||||
|
||||
598772 NEW https://bugzilla.redhat.com/show_bug.cgi?id=598772
|
||||
guestfish 'help' command should indicate error in exit status with an unknown command
|
||||
|
||||
600144 NEW https://bugzilla.redhat.com/show_bug.cgi?id=600144
|
||||
document that mkmountpoint and umount-all cannot be mixed
|
||||
|
||||
602997 NEW https://bugzilla.redhat.com/show_bug.cgi?id=602997
|
||||
part-get-bootable gives wrong result with an unordered part layout
|
||||
|
||||
603000 NEW https://bugzilla.redhat.com/show_bug.cgi?id=603000
|
||||
part-get-bootable gives wrong result with an unordered part layout
|
||||
|
||||
604041 NEW https://bugzilla.redhat.com/show_bug.cgi?id=604041
|
||||
guestmount absolute symlinks don't work
|
||||
|
||||
612308 NEW https://bugzilla.redhat.com/show_bug.cgi?id=612308
|
||||
qemu -net / vlan option deprecated. Use -netdev instead.
|
||||
|
||||
615223 NEW https://bugzilla.redhat.com/show_bug.cgi?id=615223
|
||||
vfs-type could not read just-created filesystem
|
||||
|
||||
617436 NEW https://bugzilla.redhat.com/show_bug.cgi?id=617436
|
||||
guestfish: fails to tilde expand '~' when the $HOME env is unset
|
||||
|
||||
617440 NEW https://bugzilla.redhat.com/show_bug.cgi?id=617440
|
||||
guestfish: fails to tilde expand '~' when the $HOME env is unset
|
||||
|
||||
619345 NEW https://bugzilla.redhat.com/show_bug.cgi?id=619345
|
||||
RFE: Enable coredump capture in the appliance
|
||||
|
||||
624035 NEW https://bugzilla.redhat.com/show_bug.cgi?id=624035
|
||||
guestfish "upload /file foo" command hangs or gives a protocol error
|
||||
|
||||
624334 NEW https://bugzilla.redhat.com/show_bug.cgi?id=624334
|
||||
blockdev-setbsz succeeds, but does not affect blockdev-getbsz
|
||||
|
||||
624335 NEW https://bugzilla.redhat.com/show_bug.cgi?id=624335
|
||||
blockdev-setbsz succeeds, but does not affect blockdev-getbsz
|
||||
|
||||
627468 NEW https://bugzilla.redhat.com/show_bug.cgi?id=627468
|
||||
[RFE]It's better to emphasize "libguestfs-winsupport" in V2V manpage or error output
|
||||
|
||||
627675 NEW https://bugzilla.redhat.com/show_bug.cgi?id=627675
|
||||
libguestfs inspector code cannot handle /dev/disk/by-id/* paths
|
||||
|
||||
627832 NEW https://bugzilla.redhat.com/show_bug.cgi?id=627832
|
||||
[RFE] guestfish should print outputs in a suitable base (eg. octal for modes)
|
||||
|
||||
634649 NEW https://bugzilla.redhat.com/show_bug.cgi?id=634649
|
||||
[RFE] Align a NTFS partition within qcow2 over LVM to start at offset which is a multiple of 8
|
||||
|
||||
@@ -134,9 +128,6 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
637251 NEW https://bugzilla.redhat.com/show_bug.cgi?id=637251
|
||||
virt-inspector fails to recognize data-only NTFS disk image
|
||||
|
||||
637252 NEW https://bugzilla.redhat.com/show_bug.cgi?id=637252
|
||||
virt-resize has no 32-bit support
|
||||
|
||||
642821 NEW https://bugzilla.redhat.com/show_bug.cgi?id=642821
|
||||
virt-resize falls over on a disk image with a logical swap partition
|
||||
|
||||
@@ -146,18 +137,27 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
660687 NEW https://bugzilla.redhat.com/show_bug.cgi?id=660687
|
||||
guestmount: "touch" command fails: touch: setting times of `timestamp': Invalid argument
|
||||
|
||||
576879 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=576879
|
||||
libguestfs protocol loses synchronization if you 'upload' before mounting disks
|
||||
677870 NEW https://bugzilla.redhat.com/show_bug.cgi?id=677870
|
||||
[RFE] virt-v2v show the warning info after convert rhel4u8 guest if comment a line of swap in the fstab
|
||||
|
||||
696451 NEW https://bugzilla.redhat.com/show_bug.cgi?id=696451
|
||||
libguestfs: unknown filesystem label SWAP-sda2
|
||||
|
||||
696484 NEW https://bugzilla.redhat.com/show_bug.cgi?id=696484
|
||||
[RFE] virt-v2v show the warning info after convert rhel4u8 guest if comment a line of swap in the fstab
|
||||
|
||||
700342 NEW https://bugzilla.redhat.com/show_bug.cgi?id=700342
|
||||
virt-inspector resports unknown filesystem UUID
|
||||
|
||||
713678 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=713678
|
||||
Not all febootstrap messages are redirected to log callbacks
|
||||
|
||||
721160 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=721160
|
||||
Missing btrfs support
|
||||
|
||||
583974 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=583974
|
||||
mount hangs there when you lack proper permission to guest image
|
||||
|
||||
584228 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=584228
|
||||
tgz-in/tar-in command hang when run with a vfat img
|
||||
|
||||
502074 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=502074
|
||||
running commands segfault randomly, with 32 bit host and guest, when host is a Xen or VMWare guest
|
||||
|
||||
539746 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=539746
|
||||
launch fails when run inside a Xen guest, when no non-PV kernels are installed
|
||||
|
||||
@@ -167,167 +167,71 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
541618 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=541618
|
||||
guestfish not able to mount freebsd ufs2 partitions automatically
|
||||
|
||||
639601 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=639601
|
||||
"virt-ls" command failed to parse domain name "#"
|
||||
|
||||
639602 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=639602
|
||||
""virt-list-filesystems" fails to parse the command line argument if the domain name is "#".
|
||||
619334 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=619334
|
||||
RFE: Enable coredump capture in the appliance
|
||||
|
||||
--------------------------------------------------
|
||||
Bugs in MODIFIED, POST or ON_QA state are fixed.
|
||||
You can help by testing the fixes.
|
||||
|
||||
501882 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=501882
|
||||
/tmp/libguestfs temporary directory is not cleaned up
|
||||
|
||||
507810 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=507810
|
||||
guestfish -i / virt-inspector cannot handle spaces in filenames
|
||||
|
||||
585221 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=585221
|
||||
resize2fs should support shrinking filesystems
|
||||
|
||||
585222 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=585222
|
||||
pvresize should support shrinking PVs
|
||||
|
||||
585223 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=585223
|
||||
ntfsresize should support shrinking filesystems
|
||||
|
||||
591142 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=591142
|
||||
virt-inspector should give an error for unrecognized disk images
|
||||
|
||||
591155 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=591155
|
||||
virt-tar prints "tar_in: tar subcommand failed on directory" if a disk image is not writable
|
||||
|
||||
591250 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=591250
|
||||
virt-tar prints "tar_in: tar subcommand failed on directory" if the archive is compressed or not in the right format
|
||||
|
||||
592883 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=592883
|
||||
can not edit files on images mounted with guestmount cmd
|
||||
|
||||
501889 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=501889
|
||||
write-file does not support strings containing ASCII NUL
|
||||
|
||||
582484 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=582484
|
||||
some guestfish sub commands can not handle special files properly
|
||||
|
||||
588651 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=588651
|
||||
guestfish 'strings-e' cmd does not give proper error message or hint
|
||||
691389 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=691389
|
||||
Extended attributes don't work over guestmount (FUSE)
|
||||
|
||||
657499 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=657499
|
||||
checksum: wrong check sum type causes umount to fail
|
||||
|
||||
657502 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=657502
|
||||
virt-inspector depends on EPEL package perl-String-ShellQuote but does not require it
|
||||
|
||||
501893 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=501893
|
||||
String parameters should be checked for != NULL
|
||||
|
||||
501894 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=501894
|
||||
Some String parameters should be OptString
|
||||
|
||||
521674 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=521674
|
||||
Perl modules are unversioned, but should carry version numbers
|
||||
|
||||
597118 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=597118
|
||||
A warning should be given in the help of mke2journal-L for the length of label
|
||||
|
||||
597135 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=597135
|
||||
guestfish write-file cmd does not check "size" parameter
|
||||
|
||||
597145 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=597145
|
||||
guestfish 'help' command should indicate error in exit status with an unknown command
|
||||
|
||||
599464 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=599464
|
||||
mkfs-b does not support vfat/ntfs
|
||||
|
||||
599503 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=599503
|
||||
document that mkmountpoint and umount-all cannot be mixed
|
||||
|
||||
602592 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=602592
|
||||
[RFE] expose guestfs_close in perl bindings
|
||||
|
||||
613593 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=613593
|
||||
Rebase libguestfs in RHEL 6.1
|
||||
|
||||
619334 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=619334
|
||||
RFE: Enable coredump capture in the appliance
|
||||
|
||||
633096 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=633096
|
||||
virt-resize calculates block device size incorrectly, doesn't work with qcow2 target
|
||||
|
||||
633766 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=633766
|
||||
virt-resize --shrink fails
|
||||
|
||||
634246 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=634246
|
||||
guestfs_part_get_parttype returns "loop" when run against a partition, LV or filesystem
|
||||
|
||||
635969 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=635969
|
||||
glob echo mkfs ext2 /dev/vd[b-t]1 prints garbage
|
||||
|
||||
638899 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=638899
|
||||
/dev/mapper paths should not be returned from C inspection APIs
|
||||
|
||||
638901 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=638901
|
||||
Appliance filename should not contain repository name
|
||||
|
||||
639405 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=639405
|
||||
Interrupted cached appliance creation leaves libguestfs unusable
|
||||
|
||||
639986 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=639986
|
||||
virt-df --csv does not properly quote " in libvirt domain names
|
||||
|
||||
640961 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=640961
|
||||
Document that grub-install might be needed for old Linux guests after virt-resize
|
||||
|
||||
642826 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=642826
|
||||
virt-resize converts any other image format to raw without notifying user, instructions do not account for this
|
||||
|
||||
642929 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=642929
|
||||
C inspection code should ignore /dev/fd* in /etc/fstab
|
||||
|
||||
642930 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=642930
|
||||
virt-inspector (Sys::Guestfs::Lib) should use C inspection APIs
|
||||
|
||||
642932 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=642932
|
||||
guestmount options should match guestfish options
|
||||
|
||||
642933 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=642933
|
||||
guestfs_list_filesystems should be used in all possible places
|
||||
|
||||
642934 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=642934
|
||||
No way to specify disk format when adding a disk to libguestfs
|
||||
|
||||
643624 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=643624
|
||||
libguestfs tools documentation should describe how to quote guest domain names from shell
|
||||
|
||||
646432 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=646432
|
||||
/dev/mapper paths should not be returned from guestfs_mountpoints
|
||||
|
||||
646821 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=646821
|
||||
virt-df should have --uuid option
|
||||
|
||||
646822 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=646822
|
||||
libguestfs trace mode should not print long binary strings
|
||||
|
||||
652796 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=652796
|
||||
ruby bindings not installed by 'make install', hence omitted from the binary distribution
|
||||
|
||||
655554 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=655554
|
||||
Whole disk paths are not made canonical by virt-inspector
|
||||
|
||||
661280 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=661280
|
||||
virt-rescue: panic when shutting down: "/sbin/reboot: No such file or directory"
|
||||
|
||||
663407 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=663407
|
||||
readlink and readlinklist returns /sysroot/ in some paths
|
||||
727247 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=727247
|
||||
should not depend on MAKEDEV
|
||||
|
||||
--------------------------------------------------
|
||||
These bugs are in the VERIFIED state.
|
||||
|
||||
579664 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=579664
|
||||
guestfish doesn't report error when there is not enough space for image allocation
|
||||
672491 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=672491
|
||||
RFE: guestfs_last_errno should be exposed in perl bindings
|
||||
|
||||
636454 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=636454
|
||||
[RFE] Need a way to determine if a particular block device is a logical volume
|
||||
684980 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=684980
|
||||
calling guestfs_kill_subprocess() then guestfs_close() causes a lockup in some applications
|
||||
|
||||
695881 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=695881
|
||||
virt-make-fs generates qemu-img command line containing decimal point: "qemu-img: Invalid image size specified!"
|
||||
|
||||
727178 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=727178
|
||||
error: luks_open: cryptsetup: error while loading shared libraries: libfipscheck.so.1: cannot open shared object file: No such file or directory
|
||||
|
||||
627835 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=627835
|
||||
libguestfs protocol loses synchronization if you 'upload' before mounting disks
|
||||
|
||||
729887 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=729887
|
||||
appliance crashes running aug_init with flags=4
|
||||
|
||||
678231 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=678231
|
||||
virt-inspector reports unknown filesystem UUID
|
||||
|
||||
685009 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=685009
|
||||
Got error when expanding ntfs filesystem
|
||||
|
||||
690358 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=690358
|
||||
Better to point out in manual page that fullvirt query doesn't support Windows guest
|
||||
|
||||
692394 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=692394
|
||||
inspect-list-applications fails to detect 32 bit apps installed under WOW64 emulator on 64 bit Windows
|
||||
|
||||
693306 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=693306
|
||||
sfdisk's python interface only accepts lists of type 'list' for the lines parameter
|
||||
|
||||
603000 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=603000
|
||||
part-get-bootable gives wrong result with an unordered part layout
|
||||
|
||||
666578 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=666578
|
||||
libguestfs: unknown filesystem label SWAP-sda2
|
||||
|
||||
682980 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=682980
|
||||
libguestfs incorrectly detects Red Hat desktop as 'redhat-based' instead of 'redhat'
|
||||
|
||||
688062 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=688062
|
||||
fish: add luks-open mapped device to tab completion list
|
||||
|
||||
730248 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=730248
|
||||
'guestfish --remote run' hangs in a shell command substitution context
|
||||
|
||||
End of BUGS file.
|
||||
|
||||
260
HACKING
260
HACKING
@@ -1,258 +1,2 @@
|
||||
PLEASE LOOK AT THE TOP OF EACH FILE BEFORE EDITING TO SEE WHETHER IT
|
||||
IS AUTOMATICALLY GENERATED OR NOT.
|
||||
|
||||
Adding a new action
|
||||
----------------------------------------------------------------------
|
||||
|
||||
All action functions are generated automatically, so there are only
|
||||
two files you need to edit:
|
||||
|
||||
(1) generator/generator_actions.ml: Add your new action, parameters,
|
||||
description, etc. to the big list at the top of this file.
|
||||
|
||||
(2) Edit/create a C file in daemon/ subdirectory which implements your
|
||||
'do_action' function. Take a look at one of the numerous examples
|
||||
there.
|
||||
|
||||
Formatting
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Try to use GNU / Emacs default formatting, following the convention
|
||||
used elsewhere in the source.
|
||||
|
||||
Please make sure that the code compiles without warnings.
|
||||
|
||||
Please test any changes.
|
||||
|
||||
Useful targets:
|
||||
make syntax-check Checks the syntax of the C code.
|
||||
make check Runs the test suite.
|
||||
|
||||
Enable warnings, and fix any you find:
|
||||
./configure --enable-gcc-warnings
|
||||
|
||||
Code indentation
|
||||
----------------------------------------------------------------------
|
||||
Our C source code generally adheres to some basic code-formatting
|
||||
conventions. The existing code base is not totally consistent on this
|
||||
front, but we do prefer that contributed code be formatted similarly.
|
||||
In short, use spaces-not-TABs for indentation, use 2 spaces for each
|
||||
indentation level, and other than that, follow the K&R style.
|
||||
|
||||
If you use Emacs, add the following to one of one of your start-up files
|
||||
(e.g., ~/.emacs), to help ensure that you get indentation right:
|
||||
|
||||
;;; In libguestfs, indent with spaces everywhere (not TABs).
|
||||
;;; Exceptions: Makefile and ChangeLog modes.
|
||||
(add-hook 'find-file-hook
|
||||
'(lambda () (if (and buffer-file-name
|
||||
(string-match "/libguestfs\\>" (buffer-file-name))
|
||||
(not (string-equal mode-name "Change Log"))
|
||||
(not (string-equal mode-name "Makefile")))
|
||||
(setq indent-tabs-mode nil))))
|
||||
|
||||
;;; When editing C sources in libguestfs, use this style.
|
||||
(defun libguestfs-c-mode ()
|
||||
"C mode with adjusted defaults for use with libguestfs."
|
||||
(interactive)
|
||||
(c-set-style "K&R")
|
||||
(setq c-indent-level 2)
|
||||
(setq c-basic-offset 2))
|
||||
(add-hook 'c-mode-hook
|
||||
'(lambda () (if (string-match "/libguestfs\\>" (buffer-file-name))
|
||||
(libguestfs-c-mode))))
|
||||
|
||||
Directories
|
||||
----------------------------------------------------------------------
|
||||
|
||||
appliance/
|
||||
The qemu appliance, build scripts and so on.
|
||||
|
||||
capitests/
|
||||
Automated tests of the C API. See "Tests" below.
|
||||
|
||||
cat/
|
||||
The 'virt-cat', 'virt-filesystems' and 'virt-ls' commands and
|
||||
documentation.
|
||||
|
||||
contrib/
|
||||
Outside contributions, experimental parts.
|
||||
|
||||
csharp/
|
||||
Experimental C# bindings.
|
||||
|
||||
daemon/
|
||||
The daemon that runs inside the guest and carries out actions.
|
||||
|
||||
df/
|
||||
'virt-df' command and documentation.
|
||||
|
||||
examples/
|
||||
The examples.
|
||||
|
||||
fish/
|
||||
Guestfish (the command-line program / shell)
|
||||
|
||||
fuse/
|
||||
FUSE (userspace filesystem) built on top of libguestfs.
|
||||
|
||||
generator/
|
||||
The crucially important generator, used to automatically
|
||||
generate large amounts of boilerplate C code for things like
|
||||
RPC and bindings.
|
||||
|
||||
haskell/
|
||||
Haskell bindings.
|
||||
|
||||
hivex/ [removed in 1.0.85]
|
||||
This used to contain the hivex library for reading and
|
||||
writing Windows Registry binary hive files. This is now
|
||||
available as a separate upstream project.
|
||||
|
||||
images/
|
||||
Some guest images to test against. These are gzipped to save
|
||||
space. You have to unzip them before use.
|
||||
|
||||
Also contains some files used by the test suite.
|
||||
|
||||
inspector/
|
||||
Virtual machine image inspector (virt-inspector).
|
||||
|
||||
java/
|
||||
Java bindings.
|
||||
|
||||
m4/
|
||||
M4 macros used by autoconf.
|
||||
|
||||
ocaml/
|
||||
OCaml bindings.
|
||||
|
||||
php/
|
||||
PHP bindings.
|
||||
|
||||
po/
|
||||
Translations of simple gettext strings. For translations of
|
||||
longer documents, see po-docs/.
|
||||
|
||||
po-docs/
|
||||
The build infrastructure and PO files for translations of
|
||||
manpages and POD files. Eventually this will be combined
|
||||
with the po/ directory, but that is rather complicated.
|
||||
|
||||
perl/
|
||||
Perl bindings.
|
||||
|
||||
python/
|
||||
Python bindings.
|
||||
|
||||
regressions/
|
||||
Regression tests.
|
||||
|
||||
rescue/
|
||||
'virt-rescue' command and documentation.
|
||||
|
||||
ruby/
|
||||
Ruby bindings.
|
||||
|
||||
tools/
|
||||
Command line tools written in Perl (virt-resize and more).
|
||||
|
||||
src/
|
||||
Source code to the C library.
|
||||
|
||||
test-tool/
|
||||
Interactive qemu/kernel test tool.
|
||||
|
||||
Tests
|
||||
----------------------------------------------------------------------
|
||||
|
||||
You can supply zero or as many tests as you want per API call.
|
||||
|
||||
The test environment has 4 block devices:
|
||||
/dev/sda 500MB General block device for testing.
|
||||
/dev/sdb 50MB /dev/sdb1 is an ext2 filesystem used for testing
|
||||
filesystem write operations.
|
||||
/dev/sdc 10MB Used in a few tests where 2 block devices are needed.
|
||||
/dev/sdd - ISO with fixed content (see images/test.iso).
|
||||
|
||||
To be able to run the tests in a reasonable amount of time, the
|
||||
virtual machine and block devices are reused between tests. So don't
|
||||
try testing kill_subprocess :-x Between each test we blockdev-setrw,
|
||||
umount-all, lvm-remove-all.
|
||||
|
||||
Each test starts with an initial scenario, selected using one of the
|
||||
'Init*' expressions, described in generator/generator_types.ml. These
|
||||
initialize the disks in a particular way as described. You should not
|
||||
assume anything about the previous contents of other disks that are
|
||||
not initialized.
|
||||
|
||||
You can add a prerequisite clause to any individual test. This is a
|
||||
run-time check, which, if it fails, causes the test to be skipped.
|
||||
Useful if testing a command which might not work on all variations of
|
||||
libguestfs builds. A test that has prerequisite of 'Always' is run
|
||||
unconditionally.
|
||||
|
||||
In addition, packagers can skip individual tests by setting the
|
||||
environment variables: eg:
|
||||
|
||||
SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
|
||||
SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
|
||||
|
||||
and packagers can run only certain tests by setting eg:
|
||||
|
||||
TEST_ONLY="vfs_type zerofree"
|
||||
|
||||
See capitests/tests.c for more details of how these environment
|
||||
variables work.
|
||||
|
||||
Debugging
|
||||
----------------------------------------------------------------------
|
||||
|
||||
It's a good idea to use guestfish to try out new commands.
|
||||
|
||||
Debugging the daemon is a problem because it runs inside a minimal
|
||||
qemu environment. However you can print messages from the daemon, and
|
||||
they will show up if you use 'guestfish -v'.
|
||||
|
||||
Patches
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Submit patches to the mailing list:
|
||||
http://www.redhat.com/mailman/listinfo/libguestfs
|
||||
and CC to rjones@redhat.com
|
||||
|
||||
I18N
|
||||
----------------------------------------------------------------------
|
||||
|
||||
We support i18n (gettext anyhow) in the library.
|
||||
|
||||
However many messages come from the daemon, and we don't translate
|
||||
those at the moment. One reason is that the appliance generally has
|
||||
all locale files removed from it, because they take up a lot of space.
|
||||
So we'd have to readd some of those, as well as copying our PO files
|
||||
into the appliance.
|
||||
|
||||
Debugging messages are never translated, since they are intended for
|
||||
the programmers.
|
||||
|
||||
Extended printf
|
||||
----------------------------------------------------------------------
|
||||
|
||||
In the daemon code we have created custom printf formatters %Q and %R,
|
||||
which are used to do shell quoting.
|
||||
|
||||
%Q => Simple shell quoted string. Any spaces or other shell characters
|
||||
are escaped for you.
|
||||
|
||||
%R => Same as %Q except the string is treated as a path which is prefixed
|
||||
by the sysroot.
|
||||
|
||||
eg.
|
||||
|
||||
asprintf (&cmd, "cat %R", path);
|
||||
==> "cat /sysroot/some\ path\ with\ spaces"
|
||||
|
||||
Note: Do NOT use these when you are passing parameters to the
|
||||
command{,r,v,rv}() functions. These parameters do NOT need to be
|
||||
quoted because they are not passed via the shell (instead, straight to
|
||||
exec). You probably want to use the sysroot_path() function however.
|
||||
The contents of this page have moved to the section "EXTENDING LIBGUESTFS"
|
||||
in the guestfs(3) man page.
|
||||
|
||||
10
Makefile.am
10
Makefile.am
@@ -1,5 +1,5 @@
|
||||
# libguestfs
|
||||
# Copyright (C) 2009-2010 Red Hat Inc.
|
||||
# Copyright (C) 2009-2011 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
|
||||
@@ -30,7 +30,7 @@ SUBDIRS += appliance
|
||||
endif
|
||||
|
||||
# Tests and the test-tool.
|
||||
SUBDIRS += gnulib/tests capitests regressions test-tool
|
||||
SUBDIRS += gnulib/tests capitests caution regressions test-tool
|
||||
|
||||
# Guestfish.
|
||||
SUBDIRS += fish
|
||||
@@ -74,7 +74,9 @@ SUBDIRS += fuse
|
||||
endif
|
||||
|
||||
# po-docs must come after tools, inspector.
|
||||
if HAVE_PO4A
|
||||
SUBDIRS += po-docs
|
||||
endif
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(generator_built) \
|
||||
@@ -128,7 +130,7 @@ HTMLFILES = \
|
||||
html/recipes.html \
|
||||
html/pod.css html/recipes.css
|
||||
|
||||
TEXTFILES = BUGS HACKING README RELEASE-NOTES ROADMAP TODO
|
||||
TEXTFILES = BUGS README RELEASE-NOTES ROADMAP TODO
|
||||
|
||||
WEBSITEDIR = $(HOME)/d/redhat/websites/libguestfs
|
||||
|
||||
@@ -190,7 +192,7 @@ CLEANFILES = \
|
||||
# is NOT a substitute for proper testing!
|
||||
|
||||
quickcheck:
|
||||
test-tool/run-test-tool-locally
|
||||
test-tool/run-test-tool-locally $(QUICKCHECK_TEST_TOOL_ARGS)
|
||||
|
||||
# Make binary distribution.
|
||||
|
||||
|
||||
56
README
56
README
@@ -1,43 +1,21 @@
|
||||
Libguestfs is a library for accessing and modifying guest disk images.
|
||||
Amongst the things this is good for: making batch configuration
|
||||
changes to guests, getting disk used/free statistics (see also:
|
||||
virt-df), migrating between virtualization systems (see also:
|
||||
virt-p2v), performing partial backups, performing partial guest
|
||||
clones, cloning guests and changing registry/UUID/hostname info, and
|
||||
much else besides.
|
||||
|
||||
Libguestfs uses Linux kernel and qemu code, and can access any type of
|
||||
guest filesystem that Linux and qemu can, including but not limited
|
||||
to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
|
||||
schemes, qcow, qcow2, vmdk.
|
||||
|
||||
Libguestfs provides ways to enumerate guest storage (eg. partitions,
|
||||
LVs, what filesystem is in each LV, etc.). It can also run commands
|
||||
in the context of the guest. Also you can access filesystems over
|
||||
FUSE.
|
||||
|
||||
Libguestfs is a library that can be linked with C and C++ management
|
||||
programs (or management programs written in OCaml, Perl, Python, Ruby,
|
||||
Java, PHP, Haskell or C#). You can also use it from shell scripts or the
|
||||
command line.
|
||||
|
||||
Libguestfs was written by Richard W.M. Jones (rjones@redhat.com) and
|
||||
hacked on by lots of other people. For discussion, development,
|
||||
patches, etc. please use the mailing list:
|
||||
|
||||
http://www.redhat.com/mailman/listinfo/libguestfs
|
||||
|
||||
|
||||
Home page
|
||||
----------------------------------------------------------------------
|
||||
Libguestfs is tools and a library for accessing and modifying guest
|
||||
disk images. For more information see the home page:
|
||||
|
||||
http://libguestfs.org/
|
||||
|
||||
For discussion, development, patches, etc. please use the mailing
|
||||
list:
|
||||
|
||||
http://www.redhat.com/mailman/listinfo/libguestfs
|
||||
|
||||
|
||||
Requirements
|
||||
----------------------------------------------------------------------
|
||||
|
||||
- recent QEMU >= 0.12 with virtio-serial support
|
||||
- recent QEMU >= 0.13 with virtio-serial support
|
||||
|
||||
- kernel >= 2.6.34 with virtio-serial support enabled. virtio-block
|
||||
and virtio-serial support are not required but highly recommended.
|
||||
|
||||
- febootstrap >= 3.0 (recommended >= 3.3)
|
||||
*NB*: febootstrap 2.x WILL NOT WORK
|
||||
@@ -79,8 +57,6 @@ Requirements
|
||||
- (Optional) OCaml if you want to rebuild the generated files, and
|
||||
also to build the OCaml bindings
|
||||
|
||||
- (Optional) local Fedora mirror
|
||||
|
||||
- (Optional) Perl if you want to build the perl bindings
|
||||
|
||||
- (Optional) Python if you want to build the python bindings
|
||||
@@ -108,6 +84,8 @@ bindings
|
||||
|
||||
- (Optional) PHP, phpize if you want to build the PHP bindings
|
||||
|
||||
- (Optional, but highly recommended) getfacl, getfattr
|
||||
|
||||
Running ./configure will check you have all the requirements installed
|
||||
on your machine.
|
||||
|
||||
@@ -117,13 +95,9 @@ Building
|
||||
|
||||
Then make the daemon, library and root filesystem:
|
||||
|
||||
./configure [--with-mirror=URI]
|
||||
./configure
|
||||
make
|
||||
|
||||
Use the optional --with-mirror parameter to specify the URI of a local
|
||||
Fedora mirror. See the discussion of the MIRROR parameter in the
|
||||
febootstrap(8) manpage.
|
||||
|
||||
Finally run the tests:
|
||||
|
||||
make check
|
||||
@@ -205,7 +179,7 @@ Mirroring tip
|
||||
----------------------------------------------------------------------
|
||||
|
||||
On my machines I can usually rebuild the appliance in around 3
|
||||
minutes. If it takes much longer for you, use a local Fedora mirror
|
||||
minutes. If it takes much longer for you, use a local distro mirror
|
||||
or squid.
|
||||
|
||||
To use squid to cache yum downloads, read this first:
|
||||
|
||||
@@ -514,3 +514,6 @@ https://www.redhat.com/archives/libguestfs/2009-July/msg00059.html
|
||||
|
||||
2009-07-14 : 1.0.59
|
||||
https://www.redhat.com/archives/libguestfs/2009-July/msg00023.html
|
||||
|
||||
2009-04-01 : Initial announcement
|
||||
http://rwmj.wordpress.com/2009/04/01/libguestfs-access-and-modify-virtual-machine-disk-images/
|
||||
|
||||
5
ROADMAP
5
ROADMAP
@@ -46,6 +46,11 @@ For next major stable release (1.10)
|
||||
* Better handling of partitions, including MBR extended partitions
|
||||
(RHBZ#593511, RHBZ#602997, RHBZ#642821).
|
||||
|
||||
* Hot plugging of disks using QMP. This would allow more efficient
|
||||
reuse of the appliance in some circumstances: multiple disks
|
||||
(ie. VMs) can be added in turn to the same appliance. In particular
|
||||
this would help virt-df.
|
||||
|
||||
Bugs assigned to 1.10 (put "1.10" in the Devel Whiteboard field in
|
||||
Bugzilla):
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ elif [ -x /sbin/udevd ]; then
|
||||
echo -e '\000\000\000\000' > /proc/sys/kernel/hotplug
|
||||
/sbin/udevd --daemon
|
||||
/sbin/udevadm trigger
|
||||
/sbin/udevadm settle --timeout=10
|
||||
/sbin/udevadm settle
|
||||
else
|
||||
echo No udev, creating /dev manually
|
||||
mount -t tmpfs none /dev
|
||||
|
||||
@@ -58,11 +58,12 @@
|
||||
iproute
|
||||
libaugeas0
|
||||
linux-image
|
||||
nilfs2-tools
|
||||
nilfs-tools
|
||||
ntfs-3g
|
||||
ntfsprogs
|
||||
reiserfsprogs
|
||||
udev
|
||||
ufsutils
|
||||
util-linux
|
||||
vim-tiny
|
||||
xz-utils
|
||||
@@ -89,6 +90,7 @@
|
||||
xz
|
||||
#endif /* ARCHLINUX */
|
||||
|
||||
acl
|
||||
attr
|
||||
bash
|
||||
binutils
|
||||
@@ -97,6 +99,7 @@ cpio
|
||||
dosfstools
|
||||
file
|
||||
findutils
|
||||
gawk
|
||||
grep
|
||||
gzip
|
||||
jfsutils
|
||||
|
||||
@@ -51,6 +51,7 @@ TESTS_ENVIRONMENT = \
|
||||
SKIP_TEST_COMMAND=$(shell ldd test-command | grep -sq 'not a dynamic executable' || echo 1) \
|
||||
SKIP_TEST_COMMAND_LINES=$(shell ldd test-command | grep -sq 'not a dynamic executable' || echo 1) \
|
||||
LIBGUESTFS_PATH=$(top_builddir)/appliance \
|
||||
TMPDIR=$(top_builddir) \
|
||||
$(VG)
|
||||
|
||||
#SKIP_TEST_CHECKSUM_8=$(shell if test `find ../initramfs -name squashfs.ko | wc -l` -eq 0; then echo 1; fi)
|
||||
|
||||
@@ -126,6 +126,7 @@ random_val := $(shell awk 'BEGIN{srand(); print 1+int(255*rand())}' < /dev/null)
|
||||
TESTS_ENVIRONMENT = \
|
||||
MALLOC_PERTURB_=$(random_val) \
|
||||
LD_LIBRARY_PATH=$(top_builddir)/src/.libs \
|
||||
LIBGUESTFS_PATH=$(top_builddir)/appliance
|
||||
LIBGUESTFS_PATH=$(top_builddir)/appliance \
|
||||
TMPDIR=$(top_builddir)
|
||||
|
||||
TESTS = test-virt-cat.sh test-virt-filesystems.sh test-virt-ls.sh
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <locale.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "progname.h"
|
||||
|
||||
@@ -27,7 +27,7 @@ directory (starting with '/').
|
||||
|
||||
C<virt-cat> can be used to quickly view a file. To edit a file, use
|
||||
C<virt-edit>. For more complex cases you should look at the
|
||||
L<guestfish(1)> tool.
|
||||
L<guestfish(1)> tool (see L</USING GUESTFISH> below).
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
@@ -164,6 +164,30 @@ name as a guest.
|
||||
|
||||
For compatibility the old style is still supported.
|
||||
|
||||
=head1 USING GUESTFISH
|
||||
|
||||
L<guestfish(1)> is a more powerful, lower level tool which you can use
|
||||
when C<virt-cat> doesn't work.
|
||||
|
||||
Using C<virt-cat> is approximately equivalent to doing:
|
||||
|
||||
guestfish --ro -i -d domname download file -
|
||||
|
||||
where C<domname> is the name of the libvirt guest, and C<file> is the
|
||||
full path to the file. Note the final C<-> (meaning "output to
|
||||
stdout").
|
||||
|
||||
The command above uses libguestfs's guest inspection feature and so
|
||||
does not work on guests that libguestfs cannot inspect, or on things
|
||||
like arbitrary disk images that don't contain guests. To display a
|
||||
file from a disk image directly, use:
|
||||
|
||||
guestfish --ro -a disk.img -m /dev/sda1 download file -
|
||||
|
||||
where C<disk.img> is the disk image, C</dev/sda1> is the filesystem
|
||||
within the disk image to edit, and C<file> is the full path to the
|
||||
file.
|
||||
|
||||
=head1 SHELL QUOTING
|
||||
|
||||
Libvirt guest names can contain arbitrary characters, some of which
|
||||
@@ -184,7 +208,7 @@ Richard W.M. Jones L<http://people.redhat.com/~rjones/>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (C) 2010 Red Hat Inc.
|
||||
Copyright (C) 2010-2011 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
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <locale.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "c-ctype.h"
|
||||
@@ -33,6 +34,15 @@
|
||||
#include "guestfs.h"
|
||||
#include "options.h"
|
||||
|
||||
#define DISABLE_GUESTFS_ERRORS_FOR(stmt) do { \
|
||||
guestfs_error_handler_cb old_error_cb; \
|
||||
void *old_error_data; \
|
||||
old_error_cb = guestfs_get_error_handler (g, &old_error_data); \
|
||||
guestfs_set_error_handler (g, NULL, NULL); \
|
||||
stmt; \
|
||||
guestfs_set_error_handler (g, old_error_cb, old_error_data); \
|
||||
} while (0)
|
||||
|
||||
/* These globals are shared with options.c. */
|
||||
guestfs_h *g;
|
||||
|
||||
@@ -438,14 +448,28 @@ do_output_filesystems (void)
|
||||
* otherwise pass them as NULL.
|
||||
*/
|
||||
if ((columns & COLUMN_VFS_LABEL)) {
|
||||
vfs_label = guestfs_vfs_label (g, fses[i]);
|
||||
if (vfs_label == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
DISABLE_GUESTFS_ERRORS_FOR (
|
||||
vfs_label = guestfs_vfs_label (g, fses[i]);
|
||||
);
|
||||
if (vfs_label == NULL) {
|
||||
vfs_label = strdup ("");
|
||||
if (!vfs_label) {
|
||||
perror ("strdup");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((columns & COLUMN_UUID)) {
|
||||
vfs_uuid = guestfs_vfs_uuid (g, fses[i]);
|
||||
if (vfs_uuid == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
DISABLE_GUESTFS_ERRORS_FOR (
|
||||
vfs_uuid = guestfs_vfs_uuid (g, fses[i]);
|
||||
);
|
||||
if (vfs_uuid == NULL) {
|
||||
vfs_uuid = strdup ("");
|
||||
if (!vfs_uuid) {
|
||||
perror ("strdup");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((columns & COLUMN_SIZE)) {
|
||||
size = guestfs_blockdev_getsize64 (g, fses[i]);
|
||||
|
||||
@@ -283,6 +283,60 @@ Enable tracing of libguestfs API calls.
|
||||
|
||||
=back
|
||||
|
||||
=head1 COLUMNS
|
||||
|
||||
Note that columns in the output are subject to reordering and change
|
||||
in future versions of this tool.
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<Name>
|
||||
|
||||
The filesystem, partition, block device or LVM name.
|
||||
|
||||
For device and partition names these are displayed as canonical
|
||||
libguestfs names, so that for example C</dev/sda2> is the second
|
||||
partition on the first device.
|
||||
|
||||
If the I<--long> option is B<not> specified, then only the name column
|
||||
is shown in the output.
|
||||
|
||||
=item B<Type>
|
||||
|
||||
The object type, for example C<filesystem>, C<lv>, C<device> etc.
|
||||
|
||||
=item B<VFS>
|
||||
|
||||
If there is a filesystem, then this column displays the filesystem
|
||||
type if one could be detected, eg. C<ext4>.
|
||||
|
||||
=item B<Label>
|
||||
|
||||
If the object has a label (used for identifying and mounting
|
||||
filesystems) then this column contains the label.
|
||||
|
||||
=item B<Size>
|
||||
|
||||
The size of the object in bytes. If the I<--human> option is used
|
||||
then the size is displayed in a human-readable form.
|
||||
|
||||
=item B<Parent>
|
||||
|
||||
The parent column records the parent relationship between objects.
|
||||
For example, if the object is a partition, then this column contains
|
||||
the name of the containing device. If the object is a logical volume,
|
||||
then this column is the name of the volume group.
|
||||
|
||||
=item B<UUID>
|
||||
|
||||
If the object has a UUID (used for identifying and mounting
|
||||
filesystems and block devices) then this column contains the UUID as a
|
||||
string.
|
||||
|
||||
The UUID is only displayed if the I<--uuid> option is given.
|
||||
|
||||
=back
|
||||
|
||||
=head1 NOTE ABOUT CSV FORMAT
|
||||
|
||||
Comma-separated values (CSV) is a deceptive format. It I<seems> like
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "progname.h"
|
||||
@@ -58,7 +59,7 @@ usage (int status)
|
||||
_("%s: list files in a virtual machine\n"
|
||||
"Copyright (C) 2010 Red Hat Inc.\n"
|
||||
"Usage:\n"
|
||||
" %s [--options] -d domname file [dir ...]\n"
|
||||
" %s [--options] -d domname dir [dir ...]\n"
|
||||
" %s [--options] -a disk.img [-a disk.img ...] dir [dir ...]\n"
|
||||
"Options:\n"
|
||||
" -a|--add image Add image\n"
|
||||
|
||||
37
caution/Makefile.am
Normal file
37
caution/Makefile.am
Normal file
@@ -0,0 +1,37 @@
|
||||
# libguestfs
|
||||
# Copyright (C) 2011 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
# Safety and liveness tests of components that libguestfs depends upon
|
||||
# (not of libguestfs itself). Mainly this is for qemu and the kernel.
|
||||
#
|
||||
# See also capitests and regressions directories.
|
||||
|
||||
include $(top_srcdir)/subdir-rules.mk
|
||||
|
||||
TESTS = \
|
||||
qemu-snapshot-isolation.sh
|
||||
|
||||
random_val := $(shell awk 'BEGIN{srand(); print 1+int(255*rand())}' < /dev/null)
|
||||
|
||||
TESTS_ENVIRONMENT = \
|
||||
MALLOC_PERTURB_=$(random_val) \
|
||||
LD_LIBRARY_PATH=$(top_builddir)/src/.libs \
|
||||
LIBGUESTFS_PATH=$(top_builddir)/appliance \
|
||||
TMPDIR=$(top_builddir)
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(TESTS)
|
||||
94
caution/qemu-snapshot-isolation.sh
Executable file
94
caution/qemu-snapshot-isolation.sh
Executable file
@@ -0,0 +1,94 @@
|
||||
#!/bin/bash -
|
||||
# libguestfs
|
||||
# Copyright (C) 2011 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
# Test that qemu snapshots are really isolating writes from the
|
||||
# underlying disk image. If this test were to fail, you could expect
|
||||
# libguestfs to cause massive disk corruption on live guests.
|
||||
|
||||
set -e
|
||||
|
||||
rm -f test1.img test2.img test3.img
|
||||
|
||||
truncate -s 100M test1.img
|
||||
test1_md5sum="$(md5sum test1.img | awk '{print $1}')"
|
||||
truncate -s 100M test2.img
|
||||
test2_md5sum="$(md5sum test2.img | awk '{print $1}')"
|
||||
qemu-img create -f qcow2 test3.img 100M
|
||||
test3_md5sum="$(md5sum test3.img | awk '{print $1}')"
|
||||
|
||||
# The vitally important calls are 'add-drive-ro' and
|
||||
# 'add-drive-opts ... readonly:true'.
|
||||
../fish/guestfish <<'EOF'
|
||||
add-drive-ro test1.img
|
||||
add-drive-opts test2.img format:raw readonly:true
|
||||
add-drive-opts test3.img format:qcow2 readonly:true
|
||||
run
|
||||
|
||||
part-disk /dev/sda mbr
|
||||
part-disk /dev/sdb mbr
|
||||
part-disk /dev/sdc mbr
|
||||
|
||||
mkfs ext2 /dev/sda1
|
||||
copy-size /dev/sda1 /dev/sdb1 5M
|
||||
pvcreate /dev/sdc1
|
||||
vgcreate VG /dev/sdc1
|
||||
lvcreate LV VG 80
|
||||
mkfs ext3 /dev/VG/LV
|
||||
|
||||
mkmountpoint /a
|
||||
mount-options "" /dev/sda1 /a
|
||||
mkmountpoint /b
|
||||
mount-options "" /dev/sdb1 /b
|
||||
mkmountpoint /c
|
||||
mount-options "" /dev/VG/LV /c
|
||||
|
||||
write /a/test "This is a test"
|
||||
write /b/test "This is a test"
|
||||
write /c/test "This is a test"
|
||||
|
||||
# Really try hard to force writes to the disk.
|
||||
umount-all
|
||||
sync
|
||||
|
||||
EOF
|
||||
|
||||
# Now verify that the original disks have not been touched.
|
||||
function serious_error
|
||||
{
|
||||
echo
|
||||
echo
|
||||
echo "***** SERIOUS ERROR *****"
|
||||
echo "qemu's snapshot isolation does not appear to be working."
|
||||
echo "Running libguestfs could cause disk corruption on live guests."
|
||||
echo
|
||||
echo "DO NOT USE libguestfs before you have resolved this problem."
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ "$(md5sum test1.img | awk '{print $1}')" != "$test1_md5sum" ]; then
|
||||
serious_error
|
||||
fi
|
||||
if [ "$(md5sum test2.img | awk '{print $1}')" != "$test2_md5sum" ]; then
|
||||
serious_error
|
||||
fi
|
||||
if [ "$(md5sum test3.img | awk '{print $1}')" != "$test3_md5sum" ]; then
|
||||
serious_error
|
||||
fi
|
||||
|
||||
rm test1.img test2.img test3.img
|
||||
52
configure.ac
52
configure.ac
@@ -1,5 +1,5 @@
|
||||
# libguestfs
|
||||
# Copyright (C) 2009-2010 Red Hat Inc.
|
||||
# Copyright (C) 2009-2011 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
|
||||
@@ -18,7 +18,7 @@
|
||||
# major/minor/release must be numbers
|
||||
m4_define([libguestfs_major], [1])
|
||||
m4_define([libguestfs_minor], [8])
|
||||
m4_define([libguestfs_release], [0])
|
||||
m4_define([libguestfs_release], [13])
|
||||
# extra can be any string
|
||||
m4_define([libguestfs_extra], [])
|
||||
|
||||
@@ -158,7 +158,7 @@ dnl Headers.
|
||||
AC_CHECK_HEADERS([errno.h sys/types.h sys/un.h sys/wait.h sys/socket.h endian.h byteswap.h])
|
||||
|
||||
dnl Functions.
|
||||
AC_CHECK_FUNCS([posix_fallocate])
|
||||
AC_CHECK_FUNCS([futimens posix_fallocate])
|
||||
|
||||
dnl Build the daemon?
|
||||
AC_MSG_CHECKING([if we should build the daemon])
|
||||
@@ -187,7 +187,7 @@ if test "x$enable_appliance" = "xyes"; then
|
||||
test "x$FEBOOTSTRAP" = "xno" &&
|
||||
AC_MSG_ERROR([febootstrap must be installed])
|
||||
dnl febootstrap 2.x did not support the --version parameter
|
||||
$FEBOOTSTRAP --version >/dev/null 2>&1 ||
|
||||
$FEBOOTSTRAP --version >&AS_MESSAGE_LOG_FD 2>&1 ||
|
||||
AC_MSG_ERROR([febootstrap >= 3.0 must be installed, your version is too old])
|
||||
|
||||
dnl Pass a febootstrap --yum-config option.
|
||||
@@ -210,7 +210,7 @@ if test "x$enable_appliance" = "xyes"; then
|
||||
DISTRO=REDHAT
|
||||
if test -f /etc/debian_version; then
|
||||
DISTRO=DEBIAN
|
||||
if grep -q 'DISTRIB_ID=Ubuntu' /etc/lsb-release 2>/dev/null; then
|
||||
if grep -q 'DISTRIB_ID=Ubuntu' /etc/lsb-release 2>&AS_MESSAGE_LOG_FD; then
|
||||
DISTRO=UBUNTU
|
||||
fi
|
||||
fi
|
||||
@@ -249,6 +249,27 @@ AC_CHECK_PROG([POD2HTML],[pod2html],[pod2html],[no])
|
||||
test "x$POD2HTML" = "xno" &&
|
||||
AC_MSG_ERROR([pod2html must be installed])
|
||||
|
||||
dnl Check if pod2man, pod2text take --stderr and -u options (not in RHEL 5).
|
||||
AC_MSG_CHECKING([if pod2man takes --stderr option])
|
||||
if "$POD2MAN" --stderr >&AS_MESSAGE_LOG_FD 2>&1; then
|
||||
AC_MSG_RESULT([yes])
|
||||
POD2_STDERR_OPTION="--stderr"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
POD2_STDERR_OPTION=""
|
||||
fi
|
||||
AC_SUBST([POD2_STDERR_OPTION])
|
||||
|
||||
AC_MSG_CHECKING([if pod2man takes -u option])
|
||||
if "$POD2MAN" -u >&AS_MESSAGE_LOG_FD 2>&1; then
|
||||
AC_MSG_RESULT([yes])
|
||||
POD2_UTF8_OPTION="-u"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
POD2_UTF8_OPTION=""
|
||||
fi
|
||||
AC_SUBST([POD2_UTF8_OPTION])
|
||||
|
||||
dnl Check for mkisofs.
|
||||
AC_PATH_PROGS([MKISOFS],[mkisofs],[no],
|
||||
[$PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin])
|
||||
@@ -289,10 +310,22 @@ AC_DEFINE_UNQUOTED([QEMU],["$QEMU"],[Location of qemu binary.])
|
||||
|
||||
dnl Check that the chosen qemu has virtio-serial support.
|
||||
if test "x$vmchannel_test" != "xno"; then
|
||||
AC_MSG_CHECKING([that $QEMU -help works])
|
||||
if $QEMU -help >&AS_MESSAGE_LOG_FD 2>&1; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_FAILURE(
|
||||
[$QEMU -help: command failed.
|
||||
|
||||
This could be a very old version of qemu, or qemu might not be
|
||||
working.
|
||||
])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for virtio-serial support in $QEMU])
|
||||
if $QEMU -nographic -device \? 2>&1 | grep -sq virtio-serial; then
|
||||
AC_MSG_RESULT([yes])
|
||||
vmchannel_guestfwd=guestfwd
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_FAILURE(
|
||||
@@ -466,7 +499,7 @@ AS_IF([test "x$enable_perl" != "xno"],
|
||||
missing_perl_modules=no
|
||||
for pm in Test::More ExtUtils::MakeMaker; do
|
||||
AC_MSG_CHECKING([for $pm])
|
||||
if ! perl -M$pm -e1 >/dev/null 2>&1; then
|
||||
if ! perl -M$pm -e1 >&AS_MESSAGE_LOG_FD 2>&1; then
|
||||
AC_MSG_RESULT([no])
|
||||
missing_perl_modules=yes
|
||||
else
|
||||
@@ -750,7 +783,7 @@ AS_IF([test "x$PERL" != "xno"],
|
||||
missing_perl_modules=no
|
||||
for pm in Pod::Usage Getopt::Long Sys::Virt Data::Dumper Locale::TextDomain Win::Hivex Win::Hivex::Regedit String::ShellQuote; do
|
||||
AC_MSG_CHECKING([for $pm])
|
||||
if ! $PERL -M$pm -e1 >/dev/null 2>&1; then
|
||||
if ! $PERL -M$pm -e1 >&AS_MESSAGE_LOG_FD 2>&1; then
|
||||
AC_MSG_RESULT([no])
|
||||
missing_perl_modules=yes
|
||||
else
|
||||
@@ -771,7 +804,7 @@ AC_SUBST(MAX_PROC_NR)
|
||||
|
||||
dnl Replace libtool with a wrapper that clobbers dependency_libs in *.la files
|
||||
dnl http://lists.fedoraproject.org/pipermail/devel/2010-November/146343.html
|
||||
LIBTOOL='$(SHELL) $(top_srcdir)/libtool-kill-dependency_libs.sh $(top_builddir)/libtool'
|
||||
LIBTOOL='bash $(top_srcdir)/libtool-kill-dependency_libs.sh $(top_builddir)/libtool'
|
||||
AC_SUBST([LIBTOOL])
|
||||
|
||||
dnl Run in subdirs.
|
||||
@@ -790,6 +823,7 @@ AC_CONFIG_FILES([Makefile
|
||||
appliance/Makefile
|
||||
images/Makefile
|
||||
capitests/Makefile
|
||||
caution/Makefile
|
||||
regressions/Makefile
|
||||
test-tool/Makefile
|
||||
ocaml/Makefile ocaml/examples/Makefile
|
||||
|
||||
@@ -5,7 +5,9 @@ centos5.3-libguestfs.spec
|
||||
[REMOVED]
|
||||
This used to be a centos5.3 specfile. Please use the specfile
|
||||
from EL-5 here:
|
||||
http://cvs.fedoraproject.org/viewvc/rpms/libguestfs/EL-5/
|
||||
http://pkgs.fedoraproject.org/gitweb/?p=libguestfs.git;a=shortlog;h=refs/heads/el5/master
|
||||
or the RHEL 5 source RPMs here:
|
||||
http://libguestfs.org/download/binaries/rhel5-packages/
|
||||
|
||||
dependency-diagram/
|
||||
A "dot" file (for graphviz) which describes the dependencies
|
||||
@@ -22,13 +24,13 @@ fedora-libguestfs.spec
|
||||
[REMOVED]
|
||||
This used to be a Fedora 10+ specfile. Please use the specfile
|
||||
from Fedora instead:
|
||||
http://cvs.fedoraproject.org/viewvc/rpms/libguestfs/devel/
|
||||
http://pkgs.fedoraproject.org/gitweb/?p=libguestfs.git
|
||||
|
||||
guestfsd-in-wine.sh
|
||||
Run a Windows-compiled guestfsd under Wine. Read the
|
||||
instructions at the top of this file carefully.
|
||||
|
||||
visualize-alignment
|
||||
visualize-alignment/
|
||||
Tests for visualizing block device reads and writes and
|
||||
alignment using a patched qemu. See the README file in that
|
||||
directory.
|
||||
|
||||
@@ -45,13 +45,12 @@ BUILT_SOURCES = \
|
||||
EXTRA_DIST = $(BUILT_SOURCES) \
|
||||
.gitignore
|
||||
|
||||
# This convenience library is solely to avoid compiler warnings
|
||||
# in its generated sources.
|
||||
noinst_LIBRARIES = libprotocol.a
|
||||
libprotocol_a_SOURCES = \
|
||||
guestfs_protocol.c \
|
||||
guestfs_protocol.h
|
||||
libprotocol_a_CFLAGS =
|
||||
|
||||
# This convenience library is solely to compile its generated sources with
|
||||
# custom flags.
|
||||
libprotocol_a_SOURCES = guestfs_protocol.c guestfs_protocol.h
|
||||
libprotocol_a_CFLAGS = -Wall -Wno-unused -fno-strict-aliasing
|
||||
|
||||
guestfs_protocol.c: $(libsrcdir)/guestfs_protocol.c
|
||||
rm -f $@
|
||||
|
||||
@@ -77,14 +77,15 @@ do_base64_in (const char *file)
|
||||
return -1;
|
||||
}
|
||||
if (r == -2) { /* cancellation from library */
|
||||
/* This error is ignored by the library since it initiated the
|
||||
* cancel. Nevertheless we must send an error reply here.
|
||||
*/
|
||||
reply_with_error ("file upload cancelled");
|
||||
pclose (fp);
|
||||
/* Do NOT send any error. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pclose (fp) != 0) {
|
||||
if (r == -1) /* if r == 0, file transfer ended already */
|
||||
cancel_receive ();
|
||||
reply_with_error ("base64 subcommand failed on file: %s", file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -33,18 +33,16 @@ get_blkid_tag (const char *device, const char *tag)
|
||||
char *out, *err;
|
||||
int r;
|
||||
|
||||
/* Kill the cache file, forcing blkid to reread values from the
|
||||
* original filesystems. In blkid there is a '-p' option which is
|
||||
* supposed to do this, but (a) it doesn't work and (b) that option
|
||||
* is not supported in RHEL 5.
|
||||
*/
|
||||
unlink ("/etc/blkid/blkid.tab"); /* Red Hat, Fedora */
|
||||
unlink ("/etc/blkid.tab"); /* Debian */
|
||||
|
||||
r = command (&out, &err,
|
||||
"blkid", "-o", "value", "-s", tag, device, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s", device, err);
|
||||
r = commandr (&out, &err,
|
||||
"blkid",
|
||||
/* Adding -c option kills all caching, even on RHEL 5. */
|
||||
"-c", "/dev/null",
|
||||
"-o", "value", "-s", tag, device, NULL);
|
||||
if (r != 0 && r != 2) {
|
||||
if (r >= 0)
|
||||
reply_with_error ("%s: %s (blkid returned %d)", device, err, r);
|
||||
else
|
||||
reply_with_error ("%s: %s", device, err);
|
||||
free (out);
|
||||
free (err);
|
||||
return NULL;
|
||||
@@ -52,6 +50,14 @@ get_blkid_tag (const char *device, const char *tag)
|
||||
|
||||
free (err);
|
||||
|
||||
if (r == 2) { /* means UUID etc not found */
|
||||
free (out);
|
||||
out = strdup ("");
|
||||
if (out == NULL)
|
||||
reply_with_perror ("strdup");
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Trim trailing \n if present. */
|
||||
size_t len = strlen (out);
|
||||
if (len > 0 && out[len-1] == '\n')
|
||||
|
||||
@@ -68,11 +68,13 @@ call_blockdev (const char *device, const char *switc, int extraarg, int prints)
|
||||
if (sscanf (out, "%" SCNi64, &rv) != 1) {
|
||||
reply_with_error ("%s: expected output, but got nothing", argv[0]);
|
||||
free (out);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
free (out);
|
||||
free (err);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,14 @@
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
|
||||
#include "ignore-value.h"
|
||||
|
||||
static inline void
|
||||
umount_ignore_fail (const char *path)
|
||||
{
|
||||
ignore_value (command (NULL, NULL, "umount", path, NULL));
|
||||
}
|
||||
|
||||
char *
|
||||
do_command (char *const *argv)
|
||||
{
|
||||
@@ -36,7 +44,7 @@ do_command (char *const *argv)
|
||||
int dev_ok, dev_pts_ok, proc_ok, selinux_ok, sys_ok;
|
||||
|
||||
/* We need a root filesystem mounted to do this. */
|
||||
NEED_ROOT (0, return NULL);
|
||||
NEED_ROOT (, return NULL);
|
||||
|
||||
/* Conveniently, argv is already a NULL-terminated argv-style array
|
||||
* of parameters, so we can pass it straight in to our internal
|
||||
@@ -88,11 +96,11 @@ do_command (char *const *argv)
|
||||
r = commandv (&out, &err, (const char * const *) argv);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (sys_ok) command (NULL, NULL, "umount", sysroot_sys, NULL);
|
||||
if (selinux_ok) command (NULL, NULL, "umount", sysroot_selinux, NULL);
|
||||
if (proc_ok) command (NULL, NULL, "umount", sysroot_proc, NULL);
|
||||
if (dev_pts_ok) command (NULL, NULL, "umount", sysroot_dev_pts, NULL);
|
||||
if (dev_ok) command (NULL, NULL, "umount", sysroot_dev, NULL);
|
||||
if (sys_ok) umount_ignore_fail (sysroot_sys);
|
||||
if (selinux_ok) umount_ignore_fail (sysroot_selinux);
|
||||
if (proc_ok) umount_ignore_fail (sysroot_proc);
|
||||
if (dev_pts_ok) umount_ignore_fail (sysroot_dev_pts);
|
||||
if (dev_ok) umount_ignore_fail (sysroot_dev);
|
||||
|
||||
free (sysroot_dev);
|
||||
free (sysroot_dev_pts);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
* Copyright (C) 2009-2011 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
|
||||
@@ -81,8 +81,8 @@ extern int prog_exists (const char *prog);
|
||||
|
||||
extern void udev_settle (void);
|
||||
|
||||
/* This just stops gcc from giving a warning about our custom
|
||||
* printf formatters %Q and %R. See HACKING file for more
|
||||
/* This just stops gcc from giving a warning about our custom printf
|
||||
* formatters %Q and %R. See guestfs(3)/EXTENDING LIBGUESTFS for more
|
||||
* info about these.
|
||||
*/
|
||||
static inline int
|
||||
@@ -126,6 +126,9 @@ extern struct optgroup optgroups[];
|
||||
/* Use this as a replacement for sync(2). */
|
||||
extern int sync_disks (void);
|
||||
|
||||
/*-- in ext2.c --*/
|
||||
extern int e2prog (char *name); /* Massive hack for RHEL 5. */
|
||||
|
||||
/*-- in lvm.c --*/
|
||||
extern int lv_canonical (const char *device, char **ret);
|
||||
|
||||
@@ -150,10 +153,6 @@ extern int receive_file (receive_cb cb, void *opaque);
|
||||
|
||||
/* daemon functions that receive files (FileIn) can call this
|
||||
* to cancel incoming transfers (eg. if there is a local error).
|
||||
*
|
||||
* If and only if this function does NOT return -2, they MUST then
|
||||
* call reply_with_*
|
||||
* (see https://bugzilla.redhat.com/show_bug.cgi?id=576879#c5).
|
||||
*/
|
||||
extern int cancel_receive (void);
|
||||
|
||||
@@ -179,8 +178,8 @@ extern void notify_progress (uint64_t position, uint64_t total);
|
||||
#define NEED_ROOT(cancel_stmt,fail_stmt) \
|
||||
do { \
|
||||
if (!root_mounted) { \
|
||||
if ((cancel_stmt) != -2) \
|
||||
reply_with_error ("%s: you must call 'mount' first to mount the root filesystem", __func__); \
|
||||
cancel_stmt; \
|
||||
reply_with_error ("%s: you must call 'mount' first to mount the root filesystem", __func__); \
|
||||
fail_stmt; \
|
||||
} \
|
||||
} \
|
||||
@@ -192,8 +191,8 @@ extern void notify_progress (uint64_t position, uint64_t total);
|
||||
#define ABS_PATH(path,cancel_stmt,fail_stmt) \
|
||||
do { \
|
||||
if ((path)[0] != '/') { \
|
||||
if ((cancel_stmt) != -2) \
|
||||
reply_with_error ("%s: path must start with a / character", __func__); \
|
||||
cancel_stmt; \
|
||||
reply_with_error ("%s: path must start with a / character", __func__); \
|
||||
fail_stmt; \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -208,18 +207,17 @@ extern void notify_progress (uint64_t position, uint64_t total);
|
||||
#define RESOLVE_DEVICE(path,cancel_stmt,fail_stmt) \
|
||||
do { \
|
||||
if (STRNEQLEN ((path), "/dev/", 5)) { \
|
||||
if ((cancel_stmt) != -2) \
|
||||
reply_with_error ("%s: %s: expecting a device name", __func__, (path)); \
|
||||
cancel_stmt; \
|
||||
reply_with_error ("%s: %s: expecting a device name", __func__, (path)); \
|
||||
fail_stmt; \
|
||||
} \
|
||||
if (is_root_device (path)) \
|
||||
reply_with_error ("%s: %s: device not found", __func__, path); \
|
||||
if (device_name_translation ((path)) == -1) { \
|
||||
int err = errno; \
|
||||
int r = cancel_stmt; \
|
||||
cancel_stmt; \
|
||||
errno = err; \
|
||||
if (r != -2) \
|
||||
reply_with_perror ("%s: %s", __func__, path); \
|
||||
reply_with_perror ("%s: %s", __func__, path); \
|
||||
fail_stmt; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@@ -540,16 +540,15 @@ do_debug_upload (const char *filename, int mode)
|
||||
return -1;
|
||||
}
|
||||
if (r == -2) { /* cancellation from library */
|
||||
/* This error is ignored by the library since it initiated the
|
||||
* cancel. Nevertheless we must send an error reply here.
|
||||
*/
|
||||
reply_with_error ("file upload cancelled");
|
||||
close (fd);
|
||||
/* Do NOT send any error. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (close (fd) == -1) {
|
||||
int err = errno;
|
||||
if (r == -1) /* if r == 0, file transfer ended already */
|
||||
cancel_receive ();
|
||||
errno = err;
|
||||
reply_with_perror ("close: %s", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ foreach_block_device (block_dev_func_t func)
|
||||
if(0 != errno) {
|
||||
reply_with_perror ("readdir: /sys/block");
|
||||
free_stringslen(r, size);
|
||||
closedir (dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -105,8 +106,9 @@ foreach_block_device (block_dev_func_t func)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Sort the devices */
|
||||
sort_strings (r, size);
|
||||
/* Sort the devices. Note that r might be NULL if there are no devices. */
|
||||
if (r != NULL)
|
||||
sort_strings (r, size);
|
||||
|
||||
/* NULL terminate the list */
|
||||
if (add_string (&r, &size, &alloc, NULL) == -1) {
|
||||
@@ -174,6 +176,7 @@ add_partitions(const char *device,
|
||||
if(0 != errno) {
|
||||
reply_with_perror ("readdir: %s", devdir);
|
||||
free_stringslen(*r, *size);
|
||||
closedir (dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ do_df (void)
|
||||
int r;
|
||||
char *out, *err;
|
||||
|
||||
NEED_ROOT (0, return NULL);
|
||||
NEED_ROOT (, return NULL);
|
||||
|
||||
r = command (&out, &err, "df", NULL);
|
||||
if (r == -1) {
|
||||
@@ -54,7 +54,7 @@ do_df_h (void)
|
||||
int r;
|
||||
char *out, *err;
|
||||
|
||||
NEED_ROOT (0, return NULL);
|
||||
NEED_ROOT (, return NULL);
|
||||
|
||||
r = command (&out, &err, "df", "-h", NULL);
|
||||
if (r == -1) {
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
* We specify e4fsprogs in the package list to ensure it is loaded
|
||||
* if it exists.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
e2prog (char *name)
|
||||
{
|
||||
char *p = strstr (name, "e2");
|
||||
|
||||
@@ -39,5 +39,6 @@ do_fsck (const char *fstype, const char *device)
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@ do_glob_expand (const char *pattern)
|
||||
char **rv;
|
||||
|
||||
rv = malloc (sizeof (char *) * 1);
|
||||
if (rv == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
return NULL;
|
||||
}
|
||||
rv[0] = NULL;
|
||||
return rv; /* Caller frees. */
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
* Copyright (C) 2009-2011 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
|
||||
@@ -24,6 +24,13 @@
|
||||
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
#include "optgroups.h"
|
||||
|
||||
int
|
||||
optgroup_grub_available (void)
|
||||
{
|
||||
return prog_exists ("grub-install");
|
||||
}
|
||||
|
||||
int
|
||||
do_grub_install (const char *root, const char *device)
|
||||
|
||||
@@ -142,6 +142,8 @@ main (int argc, char *argv[])
|
||||
int dont_fork = 0;
|
||||
char *cmdline;
|
||||
|
||||
ignore_value (chdir ("/"));
|
||||
|
||||
if (winsock_init () == -1)
|
||||
error (EXIT_FAILURE, 0, "winsock initialization failed");
|
||||
|
||||
@@ -258,6 +260,7 @@ main (int argc, char *argv[])
|
||||
"output to the libguestfs developers, either in a bug report\n"
|
||||
"or on the libguestfs redhat com mailing list.\n"
|
||||
"\n");
|
||||
perror ("/dev/virtio-ports/org.libguestfs.channel.0");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@@ -270,8 +273,10 @@ main (int argc, char *argv[])
|
||||
xdrmem_create (&xdr, lenbuf, sizeof lenbuf, XDR_ENCODE);
|
||||
xdr_u_int (&xdr, &len);
|
||||
|
||||
if (xwrite (sock, lenbuf, sizeof lenbuf) == -1)
|
||||
if (xwrite (sock, lenbuf, sizeof lenbuf) == -1) {
|
||||
perror ("xwrite");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
xdr_destroy (&xdr);
|
||||
|
||||
@@ -439,6 +444,7 @@ add_string (char ***argv, int *size, int *alloc, const char *str)
|
||||
if (new_str == NULL) {
|
||||
reply_with_perror ("strdup");
|
||||
free_strings (*argv);
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
new_str = NULL;
|
||||
@@ -689,6 +695,7 @@ commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
}
|
||||
|
||||
if (pid == 0) { /* Child process running the command. */
|
||||
signal (SIGPIPE, SIG_DFL);
|
||||
close (0);
|
||||
if (flag_copy_stdin) {
|
||||
dup2 (stdin_fd[0], 0);
|
||||
@@ -696,7 +703,7 @@ commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
close (stdin_fd[1]);
|
||||
} else {
|
||||
/* Set stdin to /dev/null (ignore failure) */
|
||||
open ("/dev/null", O_RDONLY);
|
||||
ignore_value (open ("/dev/null", O_RDONLY));
|
||||
}
|
||||
close (so_fd[0]);
|
||||
close (se_fd[0]);
|
||||
@@ -777,13 +784,29 @@ commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
|
||||
quit = 0;
|
||||
while (quit < 2) {
|
||||
again:
|
||||
rset2 = rset;
|
||||
r = select (MAX (so_fd[0], se_fd[0]) + 1, &rset2, NULL, NULL, NULL);
|
||||
if (r == -1) {
|
||||
if (errno == EINTR)
|
||||
goto again;
|
||||
|
||||
perror ("select");
|
||||
quit:
|
||||
if (stdoutput) free (*stdoutput);
|
||||
if (stderror) free (*stderror);
|
||||
if (stdoutput) {
|
||||
free (*stdoutput);
|
||||
*stdoutput = NULL;
|
||||
}
|
||||
if (stderror) {
|
||||
free (*stderror);
|
||||
/* Need to return non-NULL *stderror here since most callers
|
||||
* will try to print and then free the err string.
|
||||
* Unfortunately recovery from strdup failure here is not
|
||||
* possible.
|
||||
*/
|
||||
*stderror = strdup ("error running external command, "
|
||||
"see debug output for details");
|
||||
}
|
||||
close (so_fd[0]);
|
||||
close (se_fd[0]);
|
||||
waitpid (pid, NULL, 0);
|
||||
@@ -974,7 +997,8 @@ trim (char *str)
|
||||
}
|
||||
|
||||
/* printf helper function so we can use %Q ("quoted") and %R to print
|
||||
* shell-quoted strings. See HACKING file for more details.
|
||||
* shell-quoted strings. See guestfs(3)/EXTENDING LIBGUESTFS for more
|
||||
* details.
|
||||
*/
|
||||
static int
|
||||
print_shell_quote (FILE *stream,
|
||||
|
||||
@@ -70,7 +70,7 @@ do_inotify_init (int max_events)
|
||||
#ifdef HAVE_SYS_INOTIFY_H
|
||||
FILE *fp;
|
||||
|
||||
NEED_ROOT (0, return -1);
|
||||
NEED_ROOT (, return -1);
|
||||
|
||||
if (max_events < 0) {
|
||||
reply_with_error ("max_events < 0");
|
||||
@@ -314,7 +314,7 @@ do_inotify_files (void)
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
unsigned int i;
|
||||
FILE *fp;
|
||||
FILE *fp = NULL;
|
||||
guestfs_int_inotify_event_list *events;
|
||||
char buf[PATH_MAX];
|
||||
|
||||
@@ -361,13 +361,12 @@ do_inotify_files (void)
|
||||
if (len > 0 && buf[len-1] == '\n')
|
||||
buf[len-1] = '\0';
|
||||
|
||||
if (add_string (&ret, &size, &alloc, buf) == -1) {
|
||||
fclose (fp);
|
||||
if (add_string (&ret, &size, &alloc, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
fp = NULL;
|
||||
|
||||
if (add_string (&ret, &size, &alloc, NULL) == -1)
|
||||
goto error;
|
||||
@@ -376,6 +375,9 @@ do_inotify_files (void)
|
||||
return ret;
|
||||
|
||||
error:
|
||||
if (fp != NULL)
|
||||
fclose (fp);
|
||||
|
||||
unlink ("/tmp/inotify");
|
||||
return NULL;
|
||||
#else
|
||||
|
||||
@@ -76,7 +76,6 @@ do_readlinklist (const char *path, char *const *names)
|
||||
r = readlinkat (fd_cwd, names[i], link, sizeof link);
|
||||
if (r >= PATH_MAX) {
|
||||
reply_with_perror ("readlinkat: returned link is too long");
|
||||
free_strings (ret);
|
||||
close (fd_cwd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ vgchange (const char *vgchange_flag)
|
||||
char *err;
|
||||
int r = command (NULL, &err, "lvm", "vgchange", vgchange_flag, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("vgscan: %s", err);
|
||||
reply_with_error ("vgchange: %s", err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -223,10 +223,12 @@ do_vgcreate (const char *volgroup, char *const *physvols)
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s", err);
|
||||
free (err);
|
||||
free (argv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
free (argv);
|
||||
|
||||
udev_settle ();
|
||||
|
||||
@@ -512,10 +514,12 @@ do_vg_activate (int activate, char *const *volgroups)
|
||||
if (r == -1) {
|
||||
reply_with_error ("vgchange: %s", err);
|
||||
free (err);
|
||||
free (argv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
free (argv);
|
||||
|
||||
udev_settle ();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
* Copyright (C) 2009-2011 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
|
||||
@@ -40,11 +40,31 @@ do_mkfs_opts (const char *fstype, const char *device, int blocksize)
|
||||
char blocksize_str[32];
|
||||
int r;
|
||||
char *err;
|
||||
char mke2fs[] = "mke2fs";
|
||||
|
||||
/* For ext2/3/4 run the mke2fs program directly. This is because
|
||||
* the mkfs program "eats" some options, in particular the -F
|
||||
* option.
|
||||
*/
|
||||
if (STREQ (fstype, "ext2") || STREQ (fstype, "ext3") ||
|
||||
STREQ (fstype, "ext4")) {
|
||||
if (e2prog (mke2fs) == -1)
|
||||
return -1;
|
||||
argv[i++] = mke2fs;
|
||||
}
|
||||
else
|
||||
argv[i++] = "mkfs";
|
||||
|
||||
argv[i++] = "mkfs";
|
||||
argv[i++] = "-t";
|
||||
argv[i++] = fstype;
|
||||
|
||||
/* Force mke2fs to create a filesystem, even if it thinks it
|
||||
* shouldn't (RHBZ#690819).
|
||||
*/
|
||||
if (STREQ (fstype, "ext2") || STREQ (fstype, "ext3") ||
|
||||
STREQ (fstype, "ext4"))
|
||||
argv[i++] = "-F";
|
||||
|
||||
/* mkfs.ntfs requires the -Q argument otherwise it writes zeroes
|
||||
* to every block and does bad block detection, neither of which
|
||||
* are useful behaviour for virtual devices.
|
||||
|
||||
@@ -48,7 +48,7 @@ do_mount_vfs (const char *options, const char *vfstype,
|
||||
char *mp;
|
||||
char *error;
|
||||
|
||||
ABS_PATH (mountpoint, 0, return -1);
|
||||
ABS_PATH (mountpoint, , return -1);
|
||||
|
||||
is_root = STREQ (mountpoint, "/");
|
||||
|
||||
@@ -79,6 +79,7 @@ do_mount_vfs (const char *options, const char *vfstype,
|
||||
if (is_root)
|
||||
root_mounted = 1;
|
||||
|
||||
free (error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -121,7 +122,7 @@ do_umount (const char *pathordevice)
|
||||
}
|
||||
|
||||
if (is_dev)
|
||||
RESOLVE_DEVICE (buf, 0, { free (buf); return -1; });
|
||||
RESOLVE_DEVICE (buf, , { free (buf); return -1; });
|
||||
|
||||
r = command (NULL, &err, "umount", buf, NULL);
|
||||
free (buf);
|
||||
@@ -349,7 +350,7 @@ do_mount_loop (const char *file, const char *mountpoint)
|
||||
}
|
||||
|
||||
buf = sysroot_path (file);
|
||||
if (!file) {
|
||||
if (!buf) {
|
||||
reply_with_perror ("malloc");
|
||||
free (mp);
|
||||
return -1;
|
||||
@@ -364,6 +365,7 @@ do_mount_loop (const char *file, const char *mountpoint)
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -377,7 +379,7 @@ do_mkmountpoint (const char *path)
|
||||
int r;
|
||||
|
||||
/* NEED_ROOT (return -1); - we don't want this test for this call. */
|
||||
ABS_PATH (path, 0, return -1);
|
||||
ABS_PATH (path, , return -1);
|
||||
|
||||
CHROOT_IN;
|
||||
r = mkdir (path, 0777);
|
||||
@@ -402,7 +404,7 @@ do_rmmountpoint (const char *path)
|
||||
int r;
|
||||
|
||||
/* NEED_ROOT (return -1); - we don't want this test for this call. */
|
||||
ABS_PATH (path, 0, return -1);
|
||||
ABS_PATH (path, , return -1);
|
||||
|
||||
CHROOT_IN;
|
||||
r = rmdir (path);
|
||||
|
||||
@@ -56,6 +56,7 @@ do_ntfs_3g_probe (int rw, const char *device)
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -72,6 +73,7 @@ do_ntfsresize (const char *device)
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -92,5 +94,6 @@ do_ntfsresize_size (const char *device, int64_t size)
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -295,13 +295,16 @@ test_parted_m_opt (void)
|
||||
if (r == -1) {
|
||||
/* Test failed, eg. missing or completely unusable parted binary. */
|
||||
reply_with_error ("could not run 'parted' command");
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (err && strstr (err, "invalid option -- m"))
|
||||
return result = 0;
|
||||
|
||||
return result = 1;
|
||||
result = 0;
|
||||
else
|
||||
result = 1;
|
||||
free (err);
|
||||
return result;
|
||||
}
|
||||
|
||||
static char *
|
||||
@@ -576,15 +579,41 @@ do_part_get_bootable (const char *device, int partnum)
|
||||
/* New-style parsing using the "machine-readable" format from
|
||||
* 'parted -m'.
|
||||
*
|
||||
* We want lines[1+partnum].
|
||||
* Partitions may not be in any order, so we have to look for
|
||||
* the matching partition number (RHBZ#602997).
|
||||
*/
|
||||
if (count_strings (lines) < (size_t) 1+partnum) {
|
||||
reply_with_error ("partition number out of range: %d", partnum);
|
||||
if (lines[0] == NULL || STRNEQ (lines[0], "BYT;")) {
|
||||
reply_with_error ("unknown signature, expected \"BYT;\" as first line of the output: %s",
|
||||
lines[0] ? lines[0] : "(signature was null)");
|
||||
free_strings (lines);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *boot = get_table_field (lines[1+partnum], 6);
|
||||
if (lines[1] == NULL) {
|
||||
reply_with_error ("parted didn't return a line describing the device");
|
||||
free_strings (lines);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t row;
|
||||
int pnum;
|
||||
for (row = 2; lines[row] != NULL; ++row) {
|
||||
if (sscanf (lines[row], "%d:", &pnum) != 1) {
|
||||
reply_with_error ("could not parse row from output of parted print command: %s", lines[row]);
|
||||
free_strings (lines);
|
||||
return -1;
|
||||
}
|
||||
if (pnum == partnum)
|
||||
break;
|
||||
}
|
||||
|
||||
if (lines[row] == NULL) {
|
||||
reply_with_error ("partition number %d not found", partnum);
|
||||
free_strings (lines);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *boot = get_table_field (lines[row], 6);
|
||||
if (boot == NULL) {
|
||||
free_strings (lines);
|
||||
return -1;
|
||||
|
||||
@@ -183,7 +183,8 @@ do_case_sensitive_path (const char *path)
|
||||
}
|
||||
}
|
||||
|
||||
close (fd_cwd);
|
||||
if (fd_cwd >= 0)
|
||||
close (fd_cwd);
|
||||
|
||||
ret[next] = '\0';
|
||||
char *retp = strdup (ret);
|
||||
@@ -194,6 +195,8 @@ do_case_sensitive_path (const char *path)
|
||||
return retp; /* caller frees */
|
||||
|
||||
error:
|
||||
close (fd_cwd);
|
||||
if (fd_cwd >= 0)
|
||||
close (fd_cwd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "actions.h"
|
||||
#include "optgroups.h"
|
||||
|
||||
#include "ignore-value.h"
|
||||
|
||||
/* Confirmed this is true for Linux swap partitions from the Linux sources. */
|
||||
#define SWAP_LABEL_MAX 16
|
||||
|
||||
@@ -42,7 +44,7 @@ optgroup_linuxfsuuid_available (void)
|
||||
int av;
|
||||
|
||||
/* Ignore return code - mkswap --help *will* fail. */
|
||||
command (NULL, &err, "mkswap", "--help", NULL);
|
||||
ignore_value (command (NULL, &err, "mkswap", "--help", NULL));
|
||||
|
||||
av = strstr (err, "-U") != NULL;
|
||||
free (err);
|
||||
|
||||
30
daemon/tar.c
30
daemon/tar.c
@@ -85,7 +85,7 @@ do_tXz_in (const char *dir, const char *filter)
|
||||
err = errno;
|
||||
r = cancel_receive ();
|
||||
errno = err;
|
||||
if (r != -2) reply_with_perror ("asprintf");
|
||||
reply_with_perror ("asprintf");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ do_tXz_in (const char *dir, const char *filter)
|
||||
err = errno;
|
||||
r = cancel_receive ();
|
||||
errno = err;
|
||||
if (r != -2) reply_with_perror ("%s", cmd);
|
||||
reply_with_perror ("%s", cmd);
|
||||
free (cmd);
|
||||
return -1;
|
||||
}
|
||||
@@ -110,29 +110,27 @@ do_tXz_in (const char *dir, const char *filter)
|
||||
|
||||
r = receive_file (write_cb, &fd);
|
||||
if (r == -1) { /* write error */
|
||||
if (cancel_receive () != -2) {
|
||||
char *errstr = read_error_file ();
|
||||
reply_with_error ("write error on directory: %s: %s", dir, errstr);
|
||||
free (errstr);
|
||||
}
|
||||
cancel_receive ();
|
||||
char *errstr = read_error_file ();
|
||||
reply_with_error ("write error on directory: %s: %s", dir, errstr);
|
||||
free (errstr);
|
||||
pclose (fp);
|
||||
return -1;
|
||||
}
|
||||
if (r == -2) { /* cancellation from library */
|
||||
/* This error is ignored by the library since it initiated the
|
||||
* cancel. Nevertheless we must send an error reply here.
|
||||
*/
|
||||
reply_with_error ("file upload cancelled");
|
||||
pclose (fp);
|
||||
/* Do NOT send any error. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pclose (fp) != 0) {
|
||||
if (r == -1) /* if r == 0, file transfer ended already */
|
||||
r = cancel_receive ();
|
||||
if (r != -2) {
|
||||
char *errstr = read_error_file ();
|
||||
reply_with_error ("tar subcommand failed on directory: %s: %s",
|
||||
dir, errstr);
|
||||
free (errstr);
|
||||
}
|
||||
char *errstr = read_error_file ();
|
||||
reply_with_error ("tar subcommand failed on directory: %s: %s",
|
||||
dir, errstr);
|
||||
free (errstr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ upload (const char *filename, int flags, int64_t offset)
|
||||
err = errno;
|
||||
r = cancel_receive ();
|
||||
errno = err;
|
||||
if (r != -2) reply_with_perror ("%s", filename);
|
||||
reply_with_perror ("%s", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ upload (const char *filename, int flags, int64_t offset)
|
||||
err = errno;
|
||||
r = cancel_receive ();
|
||||
errno = err;
|
||||
if (r != -2) reply_with_perror ("lseek: %s", filename);
|
||||
reply_with_perror ("lseek: %s", filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -89,23 +89,21 @@ upload (const char *filename, int flags, int64_t offset)
|
||||
err = errno;
|
||||
r = cancel_receive ();
|
||||
errno = err;
|
||||
if (r != -2) reply_with_error ("write error: %s", filename);
|
||||
reply_with_error ("write error: %s", filename);
|
||||
close (data.fd);
|
||||
return -1;
|
||||
}
|
||||
if (r == -2) { /* cancellation from library */
|
||||
/* This error is ignored by the library since it initiated the
|
||||
* cancel. Nevertheless we must send an error reply here.
|
||||
*/
|
||||
reply_with_error ("file upload cancelled");
|
||||
close (data.fd);
|
||||
/* Do NOT send any error. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (close (data.fd) == -1) {
|
||||
err = errno;
|
||||
if (r == -1) /* if r == 0, file transfer ended already */
|
||||
r = cancel_receive ();
|
||||
errno = err;
|
||||
if (r != -2)
|
||||
reply_with_perror ("close: %s", filename);
|
||||
reply_with_perror ("close: %s", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
2
debian/python-guestfs.install
vendored
2
debian/python-guestfs.install
vendored
@@ -1,2 +1,2 @@
|
||||
usr/share/pyshared/*.py
|
||||
usr/share/pyshared/*.so
|
||||
usr/share/pyshared/*.so*
|
||||
|
||||
@@ -76,6 +76,7 @@ random_val := $(shell awk 'BEGIN{srand(); print 1+int(255*rand())}' < /dev/null)
|
||||
TESTS_ENVIRONMENT = \
|
||||
MALLOC_PERTURB_=$(random_val) \
|
||||
LD_LIBRARY_PATH=$(top_builddir)/src/.libs \
|
||||
LIBGUESTFS_PATH=$(top_builddir)/appliance
|
||||
LIBGUESTFS_PATH=$(top_builddir)/appliance \
|
||||
TMPDIR=$(top_builddir)
|
||||
|
||||
TESTS = test-virt-df.sh
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <locale.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef HAVE_LIBVIRT
|
||||
@@ -281,6 +282,8 @@ main (int argc, char *argv[])
|
||||
name = strrchr (drvs->a.filename, '/');
|
||||
if (name == NULL)
|
||||
name = drvs->a.filename;
|
||||
else
|
||||
name++; /* skip '/' character */
|
||||
break;
|
||||
case drv_d:
|
||||
name = drvs->d.guest;
|
||||
|
||||
@@ -72,6 +72,12 @@ connect to the default libvirt hypervisor.
|
||||
If you specify guest block devices directly (I<-a>), then libvirt is
|
||||
not used at all.
|
||||
|
||||
=item B<--csv>
|
||||
|
||||
Write out the results in CSV format (comma-separated values). This
|
||||
format can be imported easily into databases and spreadsheets, but
|
||||
read L</NOTE ABOUT CSV FORMAT> below.
|
||||
|
||||
=item B<-d> guest
|
||||
|
||||
=item B<--domain> guest
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# libguestfs C examples
|
||||
# Copyright (C) 2010 Red Hat Inc.
|
||||
# Copyright (C) 2010-2011 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
|
||||
@@ -24,12 +24,18 @@ CLEANFILES = stamp-guestfs-examples.pod
|
||||
noinst_PROGRAMS = create_disk inspect_vm
|
||||
|
||||
create_disk_SOURCES = create_disk.c
|
||||
create_disk_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src -Wall
|
||||
create_disk_LDADD = $(top_builddir)/src/libguestfs.la
|
||||
create_disk_CFLAGS = \
|
||||
-I$(top_srcdir)/src -I$(top_builddir)/src \
|
||||
$(WARN_CFLAGS) $(WERROR_CFLAGS)
|
||||
create_disk_LDADD = \
|
||||
$(top_builddir)/src/libguestfs.la
|
||||
|
||||
inspect_vm_SOURCES = inspect_vm.c
|
||||
inspect_vm_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src -Wall
|
||||
inspect_vm_LDADD = $(top_builddir)/src/libguestfs.la
|
||||
inspect_vm_CFLAGS = \
|
||||
-I$(top_srcdir)/src -I$(top_builddir)/src \
|
||||
$(WARN_CFLAGS) $(WERROR_CFLAGS)
|
||||
inspect_vm_LDADD = \
|
||||
$(top_builddir)/src/libguestfs.la
|
||||
|
||||
man_MANS = guestfs-examples.3
|
||||
noinst_DATA = $(top_builddir)/html/guestfs-examples.3.html
|
||||
|
||||
@@ -36,8 +36,7 @@ L<guestfs(3)>,
|
||||
L<guestfs-ocaml(3)>,
|
||||
L<guestfs-python(3)>,
|
||||
L<guestfs-ruby(3)>,
|
||||
L<http://libguestfs.org/>,
|
||||
L<http://caml.inria.fr/>.
|
||||
L<http://libguestfs.org/>.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ compare_keys_len (const void *p1, const void *p2)
|
||||
return strlen (key1) - strlen (key2);
|
||||
}
|
||||
|
||||
static int
|
||||
static size_t
|
||||
count_strings (char *const *argv)
|
||||
{
|
||||
int c;
|
||||
size_t c;
|
||||
|
||||
for (c = 0; argv[c]; ++c)
|
||||
;
|
||||
@@ -98,8 +98,10 @@ main (int argc, char *argv[])
|
||||
qsort (mountpoints, count_strings (mountpoints) / 2, 2 * sizeof (char *),
|
||||
compare_keys_len);
|
||||
for (i = 0; mountpoints[i] != NULL; i += 2) {
|
||||
if (guestfs_mount_ro (g, mountpoints[i+1], mountpoints[i]) == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
/* Ignore failures from this call, since bogus entries can
|
||||
* appear in the guest's /etc/fstab.
|
||||
*/
|
||||
guestfs_mount_ro (g, mountpoints[i+1], mountpoints[i]);
|
||||
free (mountpoints[i]);
|
||||
free (mountpoints[i+1]);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,12 @@
|
||||
|
||||
include $(top_srcdir)/subdir-rules.mk
|
||||
|
||||
CLEANFILES = stamp-guestfish.pod
|
||||
CLEANFILES = \
|
||||
stamp-guestfish.pod \
|
||||
stamp-virt-copy-in.pod \
|
||||
stamp-virt-copy-out.pod \
|
||||
stamp-virt-tar-in.pod \
|
||||
stamp-virt-tar-out.pod
|
||||
|
||||
bin_PROGRAMS = guestfish
|
||||
|
||||
@@ -25,6 +30,7 @@ generator_built = \
|
||||
cmds.c \
|
||||
cmds_gperf.gperf \
|
||||
completion.c \
|
||||
fish-cmds.h \
|
||||
guestfish-actions.pod \
|
||||
guestfish-commands.pod \
|
||||
prepopts.h \
|
||||
@@ -84,10 +90,10 @@ guestfish_SOURCES = \
|
||||
tilde.c \
|
||||
time.c
|
||||
|
||||
# This convenience library is solely to avoid compiler warnings
|
||||
# in its generated sources.
|
||||
librc_protocol_la_SOURCES = rc_protocol.c
|
||||
librc_protocol_la_CFLAGS = -Wall -Wno-unused
|
||||
# This convenience library is solely to compile its generated sources with
|
||||
# custom flags.
|
||||
librc_protocol_la_SOURCES = rc_protocol.c rc_protocol.h
|
||||
librc_protocol_la_CFLAGS = -Wall -Wno-unused -fno-strict-aliasing
|
||||
|
||||
# Build the command lookup perfect hash code. The generated code has
|
||||
# lots of warnings so we must compile it in a separate mini-library.
|
||||
|
||||
@@ -192,7 +192,7 @@ run_copy_out (const char *cmd, size_t argc, char *argv[])
|
||||
struct stat statbuf;
|
||||
if (stat (local, &statbuf) == -1 ||
|
||||
! (S_ISDIR (statbuf.st_mode))) {
|
||||
fprintf (stderr, _("copy-in: target '%s' is not a directory\n"), local);
|
||||
fprintf (stderr, _("copy-out: target '%s' is not a directory\n"), local);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
394
fish/fish.c
394
fish/fish.c
@@ -45,6 +45,14 @@
|
||||
#include "closeout.h"
|
||||
#include "progname.h"
|
||||
|
||||
/* Return from parse_command_line. See description below. */
|
||||
struct parsed_command {
|
||||
int status;
|
||||
char *pipe;
|
||||
char *cmd;
|
||||
char *argv[64];
|
||||
};
|
||||
|
||||
static void set_up_terminal (void);
|
||||
static void prepare_drives (struct drv *drv);
|
||||
static int launch (void);
|
||||
@@ -52,6 +60,7 @@ static void interactive (void);
|
||||
static void shell_script (void);
|
||||
static void script (int prompt);
|
||||
static void cmdline (char *argv[], int optind, int argc);
|
||||
static struct parsed_command parse_command_line (char *buf, int *exit_on_error_rtn);
|
||||
static void initialize_readline (void);
|
||||
static void cleanup_readline (void);
|
||||
#ifdef HAVE_LIBREADLINE
|
||||
@@ -69,7 +78,6 @@ int verbose = 0;
|
||||
int remote_control_listen = 0;
|
||||
int remote_control_csh = 0;
|
||||
int remote_control = 0;
|
||||
int exit_on_error = 1;
|
||||
int command_num = 0;
|
||||
int keys_from_stdin = 0;
|
||||
int echo_keys = 0;
|
||||
@@ -89,18 +97,9 @@ usage (int status)
|
||||
fprintf (stdout,
|
||||
_("%s: guest filesystem shell\n"
|
||||
"%s lets you edit virtual machine filesystems\n"
|
||||
"Copyright (C) 2009-2010 Red Hat Inc.\n"
|
||||
"Copyright (C) 2009-2011 Red Hat Inc.\n"
|
||||
"Usage:\n"
|
||||
" %s [--options] cmd [: cmd : cmd ...]\n"
|
||||
" %s [--ro] -i -a disk-image\n"
|
||||
" %s [--ro] -i -d libvirt-domain\n"
|
||||
"or for interactive use:\n"
|
||||
" %s\n"
|
||||
"or from a shell script:\n"
|
||||
" %s <<EOF\n"
|
||||
" cmd\n"
|
||||
" ...\n"
|
||||
" EOF\n"
|
||||
"Options:\n"
|
||||
" -h|--cmd-help List available commands\n"
|
||||
" -h|--cmd-help cmd Display detailed help on 'cmd'\n"
|
||||
@@ -125,11 +124,21 @@ usage (int status)
|
||||
" --selinux Enable SELinux support\n"
|
||||
" -v|--verbose Verbose messages\n"
|
||||
" -V|--version Display version and exit\n"
|
||||
" -w|--rw Mount read-write\n"
|
||||
" -x Echo each command before executing it\n"
|
||||
"\n"
|
||||
"To examine a disk image, ISO, hard disk, filesystem etc:\n"
|
||||
" %s [--ro|--rw] -i -a /path/to/disk.img\n"
|
||||
"or\n"
|
||||
" %s [--ro|--rw] -i -d name-of-libvirt-domain\n"
|
||||
"\n"
|
||||
"--ro recommended to avoid any writes to the disk image. If -i option fails\n"
|
||||
"run again without -i and use 'run' + 'list-filesystems' + 'mount' cmds.\n"
|
||||
"\n"
|
||||
"For more information, see the manpage %s(1).\n"),
|
||||
program_name, program_name, program_name,
|
||||
program_name, program_name, program_name,
|
||||
program_name, program_name, program_name);
|
||||
program_name);
|
||||
}
|
||||
exit (status);
|
||||
}
|
||||
@@ -606,12 +615,9 @@ static void
|
||||
script (int prompt)
|
||||
{
|
||||
char *buf;
|
||||
char *cmd;
|
||||
char *p, *pend;
|
||||
char *argv[64];
|
||||
int len;
|
||||
int global_exit_on_error = !prompt;
|
||||
int tilde_candidate;
|
||||
int exit_on_error;
|
||||
struct parsed_command pcmd;
|
||||
|
||||
if (prompt) {
|
||||
printf (_("\n"
|
||||
@@ -630,8 +636,6 @@ script (int prompt)
|
||||
}
|
||||
|
||||
while (!quit) {
|
||||
char *pipe = NULL;
|
||||
|
||||
exit_on_error = global_exit_on_error;
|
||||
|
||||
buf = rl_gets (prompt);
|
||||
@@ -640,178 +644,195 @@ script (int prompt)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip any initial whitespace before the command. */
|
||||
again:
|
||||
while (*buf && c_isspace (*buf))
|
||||
buf++;
|
||||
|
||||
if (!*buf) continue;
|
||||
|
||||
/* If the next character is '#' then this is a comment. */
|
||||
if (*buf == '#') continue;
|
||||
|
||||
/* If the next character is '!' then pass the whole lot to system(3). */
|
||||
if (*buf == '!') {
|
||||
int r;
|
||||
|
||||
r = system (buf+1);
|
||||
if (exit_on_error) {
|
||||
if (r == -1 ||
|
||||
(WIFSIGNALED (r) &&
|
||||
(WTERMSIG (r) == SIGINT || WTERMSIG (r) == SIGQUIT)) ||
|
||||
WEXITSTATUS (r) != 0)
|
||||
exit (EXIT_FAILURE);
|
||||
pcmd = parse_command_line (buf, &exit_on_error);
|
||||
if (pcmd.status == -1 && exit_on_error)
|
||||
exit (EXIT_FAILURE);
|
||||
if (pcmd.status == 1) {
|
||||
if (issue_command (pcmd.cmd, pcmd.argv, pcmd.pipe, exit_on_error) == -1) {
|
||||
if (exit_on_error) exit (EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the next character is '-' allow the command to fail without
|
||||
* exiting on error (just for this one command though).
|
||||
*/
|
||||
if (*buf == '-') {
|
||||
exit_on_error = 0;
|
||||
buf++;
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* Get the command (cannot be quoted). */
|
||||
len = strcspn (buf, " \t");
|
||||
|
||||
if (len == 0) continue;
|
||||
|
||||
cmd = buf;
|
||||
unsigned int i = 0;
|
||||
if (buf[len] == '\0') {
|
||||
argv[0] = NULL;
|
||||
goto got_command;
|
||||
}
|
||||
|
||||
buf[len] = '\0';
|
||||
p = &buf[len+1];
|
||||
p += strspn (p, " \t");
|
||||
|
||||
/* Get the parameters. */
|
||||
while (*p && i < sizeof argv / sizeof argv[0]) {
|
||||
tilde_candidate = 0;
|
||||
|
||||
/* Parameters which start with quotes or pipes are treated
|
||||
* specially. Bare parameters are delimited by whitespace.
|
||||
*/
|
||||
if (*p == '"') {
|
||||
p++;
|
||||
len = strcspn (p, "\"");
|
||||
if (p[len] == '\0') {
|
||||
fprintf (stderr, _("%s: unterminated double quote\n"), program_name);
|
||||
if (exit_on_error) exit (EXIT_FAILURE);
|
||||
goto next_command;
|
||||
}
|
||||
if (p[len+1] && (p[len+1] != ' ' && p[len+1] != '\t')) {
|
||||
fprintf (stderr,
|
||||
_("%s: command arguments not separated by whitespace\n"),
|
||||
program_name);
|
||||
if (exit_on_error) exit (EXIT_FAILURE);
|
||||
goto next_command;
|
||||
}
|
||||
p[len] = '\0';
|
||||
pend = p[len+1] ? &p[len+2] : &p[len+1];
|
||||
} else if (*p == '\'') {
|
||||
p++;
|
||||
len = strcspn (p, "'");
|
||||
if (p[len] == '\0') {
|
||||
fprintf (stderr, _("%s: unterminated single quote\n"), program_name);
|
||||
if (exit_on_error) exit (EXIT_FAILURE);
|
||||
goto next_command;
|
||||
}
|
||||
if (p[len+1] && (p[len+1] != ' ' && p[len+1] != '\t')) {
|
||||
fprintf (stderr,
|
||||
_("%s: command arguments not separated by whitespace\n"),
|
||||
program_name);
|
||||
if (exit_on_error) exit (EXIT_FAILURE);
|
||||
goto next_command;
|
||||
}
|
||||
p[len] = '\0';
|
||||
pend = p[len+1] ? &p[len+2] : &p[len+1];
|
||||
} else if (*p == '|') {
|
||||
*p = '\0';
|
||||
pipe = p+1;
|
||||
continue;
|
||||
/*
|
||||
} else if (*p == '[') {
|
||||
int c = 1;
|
||||
p++;
|
||||
pend = p;
|
||||
while (*pend && c != 0) {
|
||||
if (*pend == '[') c++;
|
||||
else if (*pend == ']') c--;
|
||||
pend++;
|
||||
}
|
||||
if (c != 0) {
|
||||
fprintf (stderr,
|
||||
_("%s: unterminated \"[...]\" sequence\n"), program_name);
|
||||
if (exit_on_error) exit (EXIT_FAILURE);
|
||||
goto next_command;
|
||||
}
|
||||
if (*pend && (*pend != ' ' && *pend != '\t')) {
|
||||
fprintf (stderr,
|
||||
_("%s: command arguments not separated by whitespace\n"),
|
||||
program_name);
|
||||
if (exit_on_error) exit (EXIT_FAILURE);
|
||||
goto next_command;
|
||||
}
|
||||
*(pend-1) = '\0';
|
||||
*/
|
||||
} else if (*p != ' ' && *p != '\t') {
|
||||
/* If the first character is a ~ then note that this parameter
|
||||
* is a candidate for ~username expansion. NB this does not
|
||||
* apply to quoted parameters.
|
||||
*/
|
||||
tilde_candidate = *p == '~';
|
||||
len = strcspn (p, " \t");
|
||||
if (p[len]) {
|
||||
p[len] = '\0';
|
||||
pend = &p[len+1];
|
||||
} else
|
||||
pend = &p[len];
|
||||
} else {
|
||||
fprintf (stderr, _("%s: internal error parsing string at '%s'\n"),
|
||||
program_name, p);
|
||||
abort ();
|
||||
}
|
||||
|
||||
if (!tilde_candidate)
|
||||
argv[i] = p;
|
||||
else
|
||||
argv[i] = try_tilde_expansion (p);
|
||||
i++;
|
||||
p = pend;
|
||||
|
||||
if (*p)
|
||||
p += strspn (p, " \t");
|
||||
}
|
||||
|
||||
if (i == sizeof argv / sizeof argv[0]) {
|
||||
fprintf (stderr, _("%s: too many arguments\n"), program_name);
|
||||
if (exit_on_error) exit (EXIT_FAILURE);
|
||||
goto next_command;
|
||||
}
|
||||
|
||||
argv[i] = NULL;
|
||||
|
||||
got_command:
|
||||
if (issue_command (cmd, argv, pipe) == -1) {
|
||||
if (exit_on_error) exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
next_command:;
|
||||
}
|
||||
if (prompt) printf ("\n");
|
||||
}
|
||||
|
||||
/* Parse a command string, splitting at whitespace, handling '!', '#' etc.
|
||||
* This destructively updates 'buf'.
|
||||
*
|
||||
* 'exit_on_error_rtn' is used to pass in the global exit_on_error
|
||||
* setting and to return the local setting (eg. if the command begins
|
||||
* with '-').
|
||||
*
|
||||
* Returns in parsed_command.status:
|
||||
* 1 = got a guestfish command (returned in cmd_rtn/argv_rtn/pipe_rtn)
|
||||
* 0 = no guestfish command, but otherwise OK
|
||||
* -1 = an error
|
||||
*/
|
||||
static struct parsed_command
|
||||
parse_command_line (char *buf, int *exit_on_error_rtn)
|
||||
{
|
||||
struct parsed_command pcmd;
|
||||
char *p, *pend;
|
||||
int len;
|
||||
int tilde_candidate;
|
||||
int r;
|
||||
const size_t argv_len = sizeof pcmd.argv / sizeof pcmd.argv[0];
|
||||
|
||||
/* Note that pcmd.pipe must be set to NULL for correct usage. Other
|
||||
* fields do not need to be, but this silences a gcc warning.
|
||||
*/
|
||||
memset (&pcmd, 0, sizeof pcmd);
|
||||
|
||||
again:
|
||||
/* Skip any initial whitespace before the command. */
|
||||
while (*buf && c_isspace (*buf))
|
||||
buf++;
|
||||
|
||||
if (!*buf) {
|
||||
pcmd.status = 0;
|
||||
return pcmd;
|
||||
}
|
||||
|
||||
/* If the next character is '#' then this is a comment. */
|
||||
if (*buf == '#') {
|
||||
pcmd.status = 0;
|
||||
return pcmd;
|
||||
}
|
||||
|
||||
/* If the next character is '!' then pass the whole lot to system(3). */
|
||||
if (*buf == '!') {
|
||||
r = system (buf+1);
|
||||
if (r == -1 ||
|
||||
(WIFSIGNALED (r) &&
|
||||
(WTERMSIG (r) == SIGINT || WTERMSIG (r) == SIGQUIT)) ||
|
||||
WEXITSTATUS (r) != 0)
|
||||
pcmd.status = -1;
|
||||
else
|
||||
pcmd.status = 0;
|
||||
return pcmd;
|
||||
}
|
||||
|
||||
/* If the next character is '-' allow the command to fail without
|
||||
* exiting on error (just for this one command though).
|
||||
*/
|
||||
if (*buf == '-') {
|
||||
*exit_on_error_rtn = 0;
|
||||
buf++;
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* Get the command (cannot be quoted). */
|
||||
len = strcspn (buf, " \t");
|
||||
|
||||
if (len == 0) {
|
||||
pcmd.status = 0;
|
||||
return pcmd;
|
||||
}
|
||||
|
||||
pcmd.cmd = buf;
|
||||
unsigned int i = 0;
|
||||
if (buf[len] == '\0') {
|
||||
pcmd.argv[0] = NULL;
|
||||
pcmd.status = 1;
|
||||
return pcmd;
|
||||
}
|
||||
|
||||
buf[len] = '\0';
|
||||
p = &buf[len+1];
|
||||
p += strspn (p, " \t");
|
||||
|
||||
/* Get the parameters. */
|
||||
while (*p && i < argv_len) {
|
||||
tilde_candidate = 0;
|
||||
|
||||
/* Parameters which start with quotes or pipes are treated
|
||||
* specially. Bare parameters are delimited by whitespace.
|
||||
*/
|
||||
if (*p == '"') {
|
||||
p++;
|
||||
len = strcspn (p, "\"");
|
||||
if (p[len] == '\0') {
|
||||
fprintf (stderr, _("%s: unterminated double quote\n"), program_name);
|
||||
pcmd.status = -1;
|
||||
return pcmd;
|
||||
}
|
||||
if (p[len+1] && (p[len+1] != ' ' && p[len+1] != '\t')) {
|
||||
fprintf (stderr,
|
||||
_("%s: command arguments not separated by whitespace\n"),
|
||||
program_name);
|
||||
pcmd.status = -1;
|
||||
return pcmd;
|
||||
}
|
||||
p[len] = '\0';
|
||||
pend = p[len+1] ? &p[len+2] : &p[len+1];
|
||||
} else if (*p == '\'') {
|
||||
p++;
|
||||
len = strcspn (p, "'");
|
||||
if (p[len] == '\0') {
|
||||
fprintf (stderr, _("%s: unterminated single quote\n"), program_name);
|
||||
pcmd.status = -1;
|
||||
return pcmd;
|
||||
}
|
||||
if (p[len+1] && (p[len+1] != ' ' && p[len+1] != '\t')) {
|
||||
fprintf (stderr,
|
||||
_("%s: command arguments not separated by whitespace\n"),
|
||||
program_name);
|
||||
pcmd.status = -1;
|
||||
return pcmd;
|
||||
}
|
||||
p[len] = '\0';
|
||||
pend = p[len+1] ? &p[len+2] : &p[len+1];
|
||||
} else if (*p == '|') {
|
||||
*p = '\0';
|
||||
pcmd.pipe = p+1;
|
||||
continue;
|
||||
} else if (*p != ' ' && *p != '\t') {
|
||||
/* If the first character is a ~ then note that this parameter
|
||||
* is a candidate for ~username expansion. NB this does not
|
||||
* apply to quoted parameters.
|
||||
*/
|
||||
tilde_candidate = *p == '~';
|
||||
len = strcspn (p, " \t");
|
||||
if (p[len]) {
|
||||
p[len] = '\0';
|
||||
pend = &p[len+1];
|
||||
} else
|
||||
pend = &p[len];
|
||||
} else {
|
||||
fprintf (stderr, _("%s: internal error parsing string at '%s'\n"),
|
||||
program_name, p);
|
||||
abort ();
|
||||
}
|
||||
|
||||
if (!tilde_candidate)
|
||||
pcmd.argv[i] = p;
|
||||
else
|
||||
pcmd.argv[i] = try_tilde_expansion (p);
|
||||
i++;
|
||||
p = pend;
|
||||
|
||||
if (*p)
|
||||
p += strspn (p, " \t");
|
||||
}
|
||||
|
||||
if (i == argv_len) {
|
||||
fprintf (stderr, _("%s: too many arguments\n"), program_name);
|
||||
pcmd.status = -1;
|
||||
return pcmd;
|
||||
}
|
||||
|
||||
pcmd.argv[i] = NULL;
|
||||
|
||||
pcmd.status = 1;
|
||||
return pcmd;
|
||||
}
|
||||
|
||||
static void
|
||||
cmdline (char *argv[], int optind, int argc)
|
||||
{
|
||||
const char *cmd;
|
||||
char **params;
|
||||
int exit_on_error;
|
||||
|
||||
exit_on_error = 1;
|
||||
|
||||
@@ -838,18 +859,23 @@ cmdline (char *argv[], int optind, int argc)
|
||||
optind++;
|
||||
|
||||
if (optind == argc) {
|
||||
if (issue_command (cmd, params, NULL) == -1 && exit_on_error)
|
||||
if (issue_command (cmd, params, NULL, exit_on_error) == -1 && exit_on_error)
|
||||
exit (EXIT_FAILURE);
|
||||
} else {
|
||||
argv[optind] = NULL;
|
||||
if (issue_command (cmd, params, NULL) == -1 && exit_on_error)
|
||||
if (issue_command (cmd, params, NULL, exit_on_error) == -1 && exit_on_error)
|
||||
exit (EXIT_FAILURE);
|
||||
cmdline (argv, optind+1, argc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: 'rc_exit_on_error_flag' is the exit_on_error flag that we
|
||||
* pass to the remote server (when issuing --remote commands). It
|
||||
* does not cause issue_command itself to exit on error.
|
||||
*/
|
||||
int
|
||||
issue_command (const char *cmd, char *argv[], const char *pipecmd)
|
||||
issue_command (const char *cmd, char *argv[], const char *pipecmd,
|
||||
int rc_exit_on_error_flag)
|
||||
{
|
||||
int argc;
|
||||
int stdout_saved_fd = -1;
|
||||
@@ -912,7 +938,7 @@ issue_command (const char *cmd, char *argv[], const char *pipecmd)
|
||||
|
||||
/* If --remote was set, then send this command to a remote process. */
|
||||
if (remote_control)
|
||||
r = rc_remote (remote_control, cmd, argc, argv, exit_on_error);
|
||||
r = rc_remote (remote_control, cmd, argc, argv, rc_exit_on_error_flag);
|
||||
|
||||
/* Otherwise execute it locally. */
|
||||
else if (STRCASEEQ (cmd, "help")) {
|
||||
|
||||
40
fish/fish.h
40
fish/fish.h
@@ -21,6 +21,8 @@
|
||||
|
||||
#include <guestfs.h>
|
||||
|
||||
#include "fish-cmds.h"
|
||||
|
||||
#ifdef HAVE_GETTEXT
|
||||
#include "gettext.h"
|
||||
#define _(str) dgettext(PACKAGE, (str))
|
||||
@@ -63,7 +65,7 @@ extern int have_terminfo;
|
||||
extern int progress_bars;
|
||||
extern int remote_control_csh;
|
||||
extern const char *libvirt_uri;
|
||||
extern int issue_command (const char *cmd, char *argv[], const char *pipe);
|
||||
extern int issue_command (const char *cmd, char *argv[], const char *pipe, int rc_exit_on_error_flag);
|
||||
extern void list_builtin_commands (void);
|
||||
extern int display_builtin_command (const char *cmd);
|
||||
extern void free_strings (char **argv);
|
||||
@@ -92,40 +94,13 @@ extern int complete_dest_paths;
|
||||
extern char *complete_dest_paths_generator (const char *text, int state);
|
||||
|
||||
/* in alloc.c */
|
||||
extern int run_alloc (const char *cmd, size_t argc, char *argv[]);
|
||||
extern int run_sparse (const char *cmd, size_t argc, char *argv[]);
|
||||
extern int alloc_disk (const char *filename, const char *size,
|
||||
int add, int sparse);
|
||||
extern int parse_size (const char *str, off_t *size_rtn);
|
||||
|
||||
/* in copy.c */
|
||||
extern int run_copy_in (const char *cmd, size_t argc, char *argv[]);
|
||||
extern int run_copy_out (const char *cmd, size_t argc, char *argv[]);
|
||||
|
||||
/* in echo.c */
|
||||
extern int run_echo (const char *cmd, size_t argc, char *argv[]);
|
||||
|
||||
/* in edit.c */
|
||||
extern int run_edit (const char *cmd, size_t argc, char *argv[]);
|
||||
|
||||
/* in help.c */
|
||||
extern void display_help (void);
|
||||
|
||||
/* in hexedit.c */
|
||||
extern int run_hexedit (const char *cmd, size_t argc, char *argv[]);
|
||||
|
||||
/* in lcd.c */
|
||||
extern int run_lcd (const char *cmd, size_t argc, char *argv[]);
|
||||
|
||||
/* in glob.c */
|
||||
extern int run_glob (const char *cmd, size_t argc, char *argv[]);
|
||||
|
||||
/* in man.c */
|
||||
extern int run_man (const char *cmd, size_t argc, char *argv[]);
|
||||
|
||||
/* in more.c */
|
||||
extern int run_more (const char *cmd, size_t argc, char *argv[]);
|
||||
|
||||
/* in prep.c */
|
||||
struct prep_data {
|
||||
const struct prep *prep;
|
||||
@@ -153,15 +128,6 @@ extern void rc_listen (void) __attribute__((noreturn));
|
||||
extern int rc_remote (int pid, const char *cmd, size_t argc, char *argv[],
|
||||
int exit_on_error);
|
||||
|
||||
/* in reopen.c */
|
||||
extern int run_reopen (const char *cmd, size_t argc, char *argv[]);
|
||||
|
||||
/* in supported.c */
|
||||
extern int run_supported (const char *cmd, size_t argc, char *argv[]);
|
||||
|
||||
/* in time.c */
|
||||
extern int run_time (const char *cmd, size_t argc, char *argv[]);
|
||||
|
||||
/* in tilde.c */
|
||||
extern char *try_tilde_expansion (char *path);
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ glob_issue (char *cmd, size_t argc,
|
||||
for (i = 1; i < argc; ++i)
|
||||
argv[i] = globs[i][posn[i]];
|
||||
|
||||
if (issue_command (argv[0], &argv[1], NULL) == -1)
|
||||
if (issue_command (argv[0], &argv[1], NULL, 0) == -1)
|
||||
*r = -1; /* ... but don't exit */
|
||||
|
||||
for (i = argc-1; i >= 1; --i) {
|
||||
|
||||
@@ -176,7 +176,7 @@ force a particular format use the I<--format=..> option.
|
||||
|
||||
Using this flag is mostly equivalent to using the C<add> command,
|
||||
with C<readonly:true> if the I<--ro> flag was given, and
|
||||
with C<format:...> if the I<--format:...> flag was given.
|
||||
with C<format:...> if the I<--format=...> flag was given.
|
||||
|
||||
=item B<-c URI>
|
||||
|
||||
@@ -463,7 +463,7 @@ disk image read-only you have to do I<-a image --ro>.
|
||||
This matters: If you accidentally open a live VM disk image writable
|
||||
then you will cause irreversible disk corruption.
|
||||
|
||||
By libguestfs 1.8 we intend to change the default the other way. Disk
|
||||
By libguestfs 1.10 we intend to change the default the other way. Disk
|
||||
images will be opened read-only. You will have to either specify
|
||||
I<guestfish --rw> or change a configuration file in order to get write
|
||||
access for disk images specified by those other command line options.
|
||||
@@ -863,6 +863,17 @@ user ID of the process, and C<$PID> is the process ID of the server.
|
||||
|
||||
Guestfish client and server versions must match exactly.
|
||||
|
||||
=head2 REMOTE CONTROL RUN COMMAND HANGING
|
||||
|
||||
Using the C<run> (or C<launch>) command remotely in a command
|
||||
substitution context hangs, ie. don't do (note the backquotes):
|
||||
|
||||
a=`guestfish --remote run`
|
||||
|
||||
Since the C<run> command produces no output on stdout, this is not
|
||||
useful anyway. For further information see
|
||||
L<https://bugzilla.redhat.com/show_bug.cgi?id=592910>.
|
||||
|
||||
=head1 PREPARED DISK IMAGES
|
||||
|
||||
Use the I<-N type> or I<--new type> parameter to select one of a set
|
||||
|
||||
@@ -111,6 +111,7 @@ inspect_mount_root (const char *root)
|
||||
compare_keys_len);
|
||||
|
||||
size_t i;
|
||||
size_t mount_errors = 0;
|
||||
for (i = 0; mountpoints[i] != NULL; i += 2) {
|
||||
int r;
|
||||
if (!read_only)
|
||||
@@ -118,10 +119,14 @@ inspect_mount_root (const char *root)
|
||||
else
|
||||
r = guestfs_mount_ro (g, mountpoints[i+1], mountpoints[i]);
|
||||
if (r == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
mount_errors++;
|
||||
}
|
||||
|
||||
free_strings (mountpoints);
|
||||
|
||||
if (mount_errors)
|
||||
fprintf (stderr, _("%s: some filesystems could not be mounted (ignored)\n"),
|
||||
program_name);
|
||||
}
|
||||
|
||||
/* This function is called only if the above function was called,
|
||||
|
||||
@@ -284,7 +284,7 @@ rc_listen (void)
|
||||
}
|
||||
|
||||
/* Run the command. */
|
||||
reply.r = issue_command (call.cmd, argv, NULL);
|
||||
reply.r = issue_command (call.cmd, argv, NULL, 0);
|
||||
|
||||
xdr_free ((xdrproc_t) xdr_guestfish_call, (char *) &call);
|
||||
|
||||
|
||||
39
fish/tilde.c
39
fish/tilde.c
@@ -28,8 +28,9 @@
|
||||
|
||||
#include "fish.h"
|
||||
|
||||
static char *expand_home (const char *);
|
||||
static char *expand_home (char *orig, const char *append);
|
||||
static const char *find_home_for_username (const char *, size_t);
|
||||
static const char *find_home_for_current_user (void);
|
||||
|
||||
/* This is called from the script loop if we find a candidate for
|
||||
* ~username (tilde-expansion).
|
||||
@@ -39,13 +40,11 @@ try_tilde_expansion (char *str)
|
||||
{
|
||||
assert (str[0] == '~');
|
||||
|
||||
/* Expand current user's home directory. By simple experimentation
|
||||
* I found out that bash always uses $HOME.
|
||||
*/
|
||||
/* Expand "~" to current user's home directory. */
|
||||
if (str[1] == '\0') /* ~ */
|
||||
return expand_home (NULL);
|
||||
return expand_home (str, NULL);
|
||||
else if (str[1] == '/') /* ~/... */
|
||||
return expand_home (&str[1]);
|
||||
return expand_home (str, &str[1]);
|
||||
|
||||
/* Try expanding the part up to the following '\0' or '/' as a
|
||||
* username from the password file.
|
||||
@@ -58,7 +57,7 @@ try_tilde_expansion (char *str)
|
||||
home = find_home_for_username (&str[1], len);
|
||||
|
||||
if (home) {
|
||||
len = strlen (home) + strlen (rest);
|
||||
len = strlen (home) + strlen (rest) + 1;
|
||||
str = malloc (len);
|
||||
if (str == NULL) {
|
||||
perror ("malloc");
|
||||
@@ -76,14 +75,21 @@ try_tilde_expansion (char *str)
|
||||
|
||||
/* Return $HOME + append string. */
|
||||
static char *
|
||||
expand_home (const char *append)
|
||||
expand_home (char *orig, const char *append)
|
||||
{
|
||||
const char *home;
|
||||
int len;
|
||||
char *str;
|
||||
|
||||
home = getenv ("HOME");
|
||||
if (!home) home = "~";
|
||||
if (!home) {
|
||||
/* $HOME not set, bash can look up the current user in the
|
||||
* password file and find their home that way. (RHBZ#617440).
|
||||
*/
|
||||
home = find_home_for_current_user ();
|
||||
if (!home)
|
||||
return orig;
|
||||
}
|
||||
|
||||
len = strlen (home) + (append ? strlen (append) : 0) + 1;
|
||||
str = malloc (len);
|
||||
@@ -116,3 +122,18 @@ find_home_for_username (const char *username, size_t ulen)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
find_home_for_current_user (void)
|
||||
{
|
||||
struct passwd *pw;
|
||||
uid_t euid = geteuid ();
|
||||
|
||||
setpwent ();
|
||||
while ((pw = getpwent ()) != NULL) {
|
||||
if (pw->pw_uid == euid)
|
||||
return pw->pw_dir;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ run_time (const char *cmd, size_t argc, char *argv[])
|
||||
|
||||
gettimeofday (&start_t, NULL);
|
||||
|
||||
if (issue_command (argv[0], &argv[1], NULL) == -1)
|
||||
if (issue_command (argv[0], &argv[1], NULL, 0) == -1)
|
||||
return -1;
|
||||
|
||||
gettimeofday (&end_t, NULL);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# libguestfs
|
||||
# Copyright (C) 2009 Red Hat Inc.
|
||||
# Copyright (C) 2009-2011 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* guestmount - mount guests using libguestfs and FUSE
|
||||
* Copyright (C) 2009-2010 Red Hat Inc.
|
||||
* Copyright (C) 2009-2011 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
|
||||
@@ -744,19 +744,41 @@ fg_getxattr (const char *path, const char *name, char *value,
|
||||
free_attrs = 1;
|
||||
}
|
||||
|
||||
/* Find the matching attribute (index in 'i'). */
|
||||
ssize_t r;
|
||||
size_t i;
|
||||
int r = -ENOATTR;
|
||||
for (i = 0; i < xattrs->len; ++i) {
|
||||
if (STREQ (xattrs->val[i].attrname, name)) {
|
||||
size_t sz = xattrs->val[i].attrval_len;
|
||||
if (sz > size)
|
||||
sz = size;
|
||||
memcpy (value, xattrs->val[i].attrval, sz);
|
||||
r = 0;
|
||||
if (STREQ (xattrs->val[i].attrname, name))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == xattrs->len) { /* not found */
|
||||
r = -ENOATTR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The getxattr man page is unclear, but if value == NULL then we
|
||||
* return the space required (the caller then makes a second syscall
|
||||
* after allocating the required amount of space). If value != NULL
|
||||
* then it's not clear what we should do, but it appears we should
|
||||
* copy as much as possible and return -ERANGE if there's not enough
|
||||
* space in the buffer.
|
||||
*/
|
||||
size_t sz = xattrs->val[i].attrval_len;
|
||||
if (value == NULL) {
|
||||
r = sz;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sz <= size)
|
||||
r = sz;
|
||||
else {
|
||||
r = -ERANGE;
|
||||
sz = size;
|
||||
}
|
||||
memcpy (value, xattrs->val[i].attrval, sz);
|
||||
|
||||
out:
|
||||
if (free_attrs)
|
||||
guestfs_free_xattr_list ((struct guestfs_xattr_list *) xattrs);
|
||||
|
||||
@@ -780,25 +802,47 @@ fg_listxattr (const char *path, char *list, size_t size)
|
||||
free_attrs = 1;
|
||||
}
|
||||
|
||||
/* Calculate how much space is required to hold the result. */
|
||||
size_t space = 0;
|
||||
size_t len;
|
||||
size_t i;
|
||||
ssize_t copied = 0;
|
||||
for (i = 0; i < xattrs->len; ++i) {
|
||||
size_t len = strlen (xattrs->val[i].attrname) + 1;
|
||||
len = strlen (xattrs->val[i].attrname) + 1;
|
||||
space += len;
|
||||
}
|
||||
|
||||
/* The listxattr man page is unclear, but if list == NULL then we
|
||||
* return the space required (the caller then makes a second syscall
|
||||
* after allocating the required amount of space). If list != NULL
|
||||
* then it's not clear what we should do, but it appears we should
|
||||
* copy as much as possible and return -ERANGE if there's not enough
|
||||
* space in the buffer.
|
||||
*/
|
||||
ssize_t r;
|
||||
if (list == NULL) {
|
||||
r = space;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
for (i = 0; i < xattrs->len; ++i) {
|
||||
len = strlen (xattrs->val[i].attrname) + 1;
|
||||
if (size >= len) {
|
||||
memcpy (list, xattrs->val[i].attrname, len);
|
||||
size -= len;
|
||||
list += len;
|
||||
copied += len;
|
||||
r += len;
|
||||
} else {
|
||||
copied = -ERANGE;
|
||||
r = -ERANGE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (free_attrs)
|
||||
guestfs_free_xattr_list ((struct guestfs_xattr_list *) xattrs);
|
||||
|
||||
return copied;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -886,6 +930,7 @@ usage (int status)
|
||||
" --selinux Enable SELinux support\n"
|
||||
" -v|--verbose Verbose messages\n"
|
||||
" -V|--version Display version and exit\n"
|
||||
" -w|--rw Mount read-write\n"
|
||||
" -x|--trace Trace guestfs API calls\n"
|
||||
),
|
||||
program_name, program_name, program_name);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash -
|
||||
# libguestfs
|
||||
# Copyright (C) 2009 Red Hat Inc.
|
||||
# Copyright (C) 2009-2011 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
|
||||
@@ -31,6 +31,10 @@ nr_stages=$(grep "^stage " $0 | wc -l)
|
||||
# and move to that directory for the initial phase of the script.
|
||||
top_builddir=$(cd "$top_builddir" > /dev/null; pwd)
|
||||
|
||||
# Set TMPDIR so the appliance doesn't conflict with globally
|
||||
# installed libguestfs.
|
||||
export TMPDIR=$top_builddir
|
||||
|
||||
# Set libguestfs up for running locally.
|
||||
export LIBGUESTFS_PATH="$top_builddir/appliance"
|
||||
|
||||
@@ -92,10 +96,15 @@ $guestfish <<EOF
|
||||
run
|
||||
part-disk /dev/sda mbr
|
||||
mkfs ext2 /dev/sda1
|
||||
mount /dev/sda1 /
|
||||
mount_options acl,user_xattr /dev/sda1 /
|
||||
write /hello.txt hello
|
||||
write /world.txt "hello world"
|
||||
touch /empty
|
||||
touch /user_xattr
|
||||
setxattr user.test hello123 8 /user_xattr
|
||||
touch /acl
|
||||
# XXX hack until libguestfs gets ACL support
|
||||
debug sh "setfacl -m u:500:r /sysroot/acl" | cat > /dev/null
|
||||
EOF
|
||||
|
||||
stage Mounting the filesystem
|
||||
|
||||
@@ -907,6 +907,10 @@ This returns a hash of where we think the filesystems
|
||||
associated with this operating system should be mounted.
|
||||
Callers should note that this is at best an educated guess
|
||||
made by reading configuration files such as C</etc/fstab>.
|
||||
I<In particular note> that this may return filesystems
|
||||
which are non-existent or not mountable and callers should
|
||||
be prepared to handle or ignore failures if they try to
|
||||
mount them.
|
||||
|
||||
Each element in the returned hashtable has a key which
|
||||
is the path of the mountpoint (eg. C</boot>) and a value
|
||||
@@ -1095,9 +1099,7 @@ The optional C<libvirturi> parameter sets the libvirt URI
|
||||
(see L<http://libvirt.org/uri.html>). If this is not set then
|
||||
we connect to the default libvirt URI (or one set through an
|
||||
environment variable, see the libvirt documentation for full
|
||||
details). If you are using the C API directly then it is more
|
||||
flexible to create the libvirt connection object yourself, get
|
||||
the domain object, and call C<guestfs_add_libvirt_dom>.
|
||||
details).
|
||||
|
||||
The other optional parameters are passed directly through to
|
||||
C<guestfs_add_drive_opts>.");
|
||||
@@ -1567,7 +1569,12 @@ do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
|
||||
|
||||
=item C<AUG_TYPE_CHECK> = 4
|
||||
|
||||
Typecheck lenses (can be expensive).
|
||||
Typecheck lenses.
|
||||
|
||||
This option is only useful when debugging Augeas lenses. Use
|
||||
of this option may require additional memory for the libguestfs
|
||||
appliance. You may need to set the C<LIBGUESTFS_MEMSIZE>
|
||||
environment variable or call C<guestfs_set_memsize>.
|
||||
|
||||
=item C<AUG_NO_STDINC> = 8
|
||||
|
||||
@@ -2037,15 +2044,12 @@ The exact command which runs is C<file -zb path>. Note in
|
||||
particular that the filename is not prepended to the output
|
||||
(the C<-b> option).
|
||||
|
||||
This command can also be used on C</dev/> devices
|
||||
(and partitions, LV names). You can for example use this
|
||||
to determine if a device contains a filesystem, although
|
||||
it's usually better to use C<guestfs_vfs_type>.
|
||||
The output depends on the output of the underlying L<file(1)>
|
||||
command and it can change in future in ways beyond our control.
|
||||
In other words, the output is not guaranteed by the ABI.
|
||||
|
||||
If the C<path> does not begin with C</dev/> then
|
||||
this command only works for the content of regular files.
|
||||
For other file types (directory, symbolic link etc) it
|
||||
will just return the string C<directory> etc.");
|
||||
See also: L<file(1)>, C<guestfs_vfs_type>, C<guestfs_lstat>,
|
||||
C<guestfs_is_file>, C<guestfs_is_blockdev> (etc).");
|
||||
|
||||
("command", (RString "output", [StringList "arguments"], []), 50, [ProtocolLimitWarning],
|
||||
[InitScratchFS, Always, TestOutput (
|
||||
@@ -2739,10 +2743,9 @@ Checking or repairing NTFS volumes is not supported
|
||||
This command is entirely equivalent to running C<fsck -a -t fstype device>.");
|
||||
|
||||
("zero", (RErr, [Device "device"], []), 85, [Progress],
|
||||
[InitBasicFS, Always, TestOutput (
|
||||
[InitBasicFS, Always, TestRun (
|
||||
[["umount"; "/dev/sda1"];
|
||||
["zero"; "/dev/sda1"];
|
||||
["file"; "/dev/sda1"]], "data")],
|
||||
["zero"; "/dev/sda1"]])],
|
||||
"write zeroes to the device",
|
||||
"\
|
||||
This command writes zeroes over the first few blocks of C<device>.
|
||||
@@ -2753,7 +2756,7 @@ any partition tables, filesystem superblocks and so on.
|
||||
|
||||
See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
|
||||
|
||||
("grub_install", (RErr, [Pathname "root"; Device "device"], []), 86, [],
|
||||
("grub_install", (RErr, [Pathname "root"; Device "device"], []), 86, [Optional "grub"],
|
||||
(* See:
|
||||
* https://bugzilla.redhat.com/show_bug.cgi?id=484986
|
||||
* https://bugzilla.redhat.com/show_bug.cgi?id=479760
|
||||
@@ -2763,12 +2766,32 @@ See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
|
||||
["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
|
||||
["grub_install"; "/"; "/dev/vda"];
|
||||
["is_dir"; "/boot"]])],
|
||||
"install GRUB",
|
||||
"install GRUB 1",
|
||||
"\
|
||||
This command installs GRUB (the Grand Unified Bootloader) on
|
||||
This command installs GRUB 1 (the Grand Unified Bootloader) on
|
||||
C<device>, with the root directory being C<root>.
|
||||
|
||||
Note: If grub-install reports the error
|
||||
Notes:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
There is currently no way in the API to install grub2, which
|
||||
is used by most modern Linux guests. It is possible to run
|
||||
the grub2 command from the guest, although see the
|
||||
caveats in L<guestfs(3)/RUNNING COMMANDS>.
|
||||
|
||||
=item *
|
||||
|
||||
This uses C<grub-install> from the host. Unfortunately grub is
|
||||
not always compatible with itself, so this only works in rather
|
||||
narrow circumstances. Careful testing with each guest version
|
||||
is advisable.
|
||||
|
||||
=item *
|
||||
|
||||
If grub-install reports the error
|
||||
\"No suitable drive was found in the generated device map.\"
|
||||
it may be that you need to create a C</boot/grub/device.map>
|
||||
file first that contains the mapping between grub device names
|
||||
@@ -2777,7 +2800,9 @@ a file containing:
|
||||
|
||||
(hd0) /dev/vda
|
||||
|
||||
replacing C</dev/vda> with the name of the installation device.");
|
||||
replacing C</dev/vda> with the name of the installation device.
|
||||
|
||||
=back");
|
||||
|
||||
("cp", (RErr, [Pathname "src"; Pathname "dest"], []), 87, [],
|
||||
[InitScratchFS, Always, TestOutput (
|
||||
@@ -4998,6 +5023,15 @@ it to local file C<tarball> (as an xz compressed tar archive).");
|
||||
"\
|
||||
This command resizes an NTFS filesystem, expanding or
|
||||
shrinking it to the size of the underlying device.
|
||||
|
||||
I<Note:> After the resize operation, the filesystem is marked
|
||||
as requiring a consistency check (for safety). You have to boot
|
||||
into Windows to perform this check and clear this condition.
|
||||
Furthermore, ntfsresize refuses to resize filesystems
|
||||
which have been marked in this way. So in effect it is
|
||||
not possible to call ntfsresize multiple times on a single
|
||||
filesystem without booting into Windows between each resize.
|
||||
|
||||
See also L<ntfsresize(8)>.");
|
||||
|
||||
("vgscan", (RErr, [], []), 232, [],
|
||||
@@ -5631,6 +5665,8 @@ for Linux ext2/3 filesystems.
|
||||
For VFAT and NTFS the C<blocksize> parameter is treated as
|
||||
the requested cluster size.
|
||||
|
||||
For UFS block sizes, please see L<mkfs.ufs(8)>.
|
||||
|
||||
=back");
|
||||
|
||||
("getxattr", (RBufferOut "xattr", [Pathname "path"; String "name"], []), 279, [Optional "linuxxattrs"],
|
||||
|
||||
@@ -253,7 +253,7 @@ I<The caller must free the returned buffer after use>.\n\n"
|
||||
pr "This function takes a key or passphrase parameter which
|
||||
could contain sensitive material. Read the section
|
||||
L</KEYS AND PASSPHRASES> for more information.\n\n";
|
||||
(match deprecation_notice flags with
|
||||
(match deprecation_notice ~prefix:"guestfs_" flags with
|
||||
| None -> ()
|
||||
| Some txt -> pr "%s\n\n" txt
|
||||
);
|
||||
@@ -637,14 +637,6 @@ check_state (guestfs_h *g, const char *caller)
|
||||
|
||||
";
|
||||
|
||||
let error_code_of = function
|
||||
| RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
|
||||
| RConstString _ | RConstOptString _
|
||||
| RString _ | RStringList _
|
||||
| RStruct _ | RStructList _
|
||||
| RHashtable _ | RBufferOut _ -> "NULL"
|
||||
in
|
||||
|
||||
(* Generate code to check String-like parameters are not passed in
|
||||
* as NULL (returning an error if they are).
|
||||
*)
|
||||
@@ -667,7 +659,17 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " if (%s == NULL) {\n" n;
|
||||
pr " error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
|
||||
pr " \"%s\", \"%s\");\n" shortname n;
|
||||
pr " return %s;\n" (error_code_of ret);
|
||||
let errcode =
|
||||
match errcode_of_ret ret with
|
||||
| `CannotReturnError ->
|
||||
if shortname = "test0rconstoptstring" then (* XXX hack *)
|
||||
`ErrorIsNULL
|
||||
else
|
||||
failwithf
|
||||
"%s: RConstOptString function has invalid parameter '%s'"
|
||||
shortname n
|
||||
| (`ErrorIsMinusOne |`ErrorIsNULL) as e -> e in
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr_newline := true
|
||||
|
||||
@@ -689,7 +691,11 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " optargs->%s == NULL) {\n" n;
|
||||
pr " error (g, \"%%s: %%s: optional parameter cannot be NULL\",\n";
|
||||
pr " \"%s\", \"%s\");\n" shortname n;
|
||||
pr " return %s;\n" (error_code_of ret);
|
||||
let errcode =
|
||||
match errcode_of_ret ret with
|
||||
| `CannotReturnError -> assert false
|
||||
| (`ErrorIsMinusOne |`ErrorIsNULL) as e -> e in
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr_newline := true
|
||||
|
||||
@@ -711,7 +717,11 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " if (optargs->bitmask & UINT64_C(0x%Lx)) {\n" mask;
|
||||
pr " error (g, \"%%s: unknown option in guestfs_%%s_argv->bitmask (this can happen if a program is compiled against a newer version of libguestfs, then dynamically linked to an older version)\",\n";
|
||||
pr " \"%s\", \"%s\");\n" shortname shortname;
|
||||
pr " return %s;\n" (error_code_of ret);
|
||||
let errcode =
|
||||
match errcode_of_ret ret with
|
||||
| `CannotReturnError -> assert false
|
||||
| (`ErrorIsMinusOne |`ErrorIsNULL) as e -> e in
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr "\n";
|
||||
in
|
||||
@@ -823,12 +833,14 @@ check_state (guestfs_h *g, const char *caller)
|
||||
| RBufferOut _ ->
|
||||
pr "%s guestfs___print_BufferOut (stderr, %s, *size_r);\n" indent rv
|
||||
| RStringList _ | RHashtable _ ->
|
||||
pr "%s fputs (\"[\\\"\", stderr);\n" indent;
|
||||
pr "%s fputs (\"[\", stderr);\n" indent;
|
||||
pr "%s for (i = 0; %s[i]; ++i) {\n" indent rv;
|
||||
pr "%s if (i > 0) fputs (\"\\\", \\\"\", stderr);\n" indent;
|
||||
pr "%s if (i > 0) fputs (\", \", stderr);\n" indent;
|
||||
pr "%s fputs (\"\\\"\", stderr);\n" indent;
|
||||
pr "%s fputs (%s[i], stderr);\n" indent rv;
|
||||
pr "%s fputs (\"\\\"\", stderr);\n" indent;
|
||||
pr "%s }\n" indent;
|
||||
pr "%s fputs (\"\\\"]\", stderr);\n" indent;
|
||||
pr "%s fputs (\"]\", stderr);\n" indent;
|
||||
| RStruct (_, typ) ->
|
||||
(* XXX There is code generated for guestfish for printing
|
||||
* these structures. We need to make it generally available
|
||||
@@ -882,7 +894,9 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " int r;\n"
|
||||
| RInt64 _ ->
|
||||
pr " int64_t r;\n"
|
||||
| RConstString _ | RConstOptString _ ->
|
||||
| RConstString _ ->
|
||||
pr " const char *r;\n"
|
||||
| RConstOptString _ ->
|
||||
pr " const char *r;\n"
|
||||
| RString _ | RBufferOut _ ->
|
||||
pr " char *r;\n"
|
||||
@@ -900,7 +914,18 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " r = guestfs__%s " shortname;
|
||||
generate_c_call_args ~handle:"g" style;
|
||||
pr ";\n";
|
||||
trace_return style "r";
|
||||
pr "\n";
|
||||
(match errcode_of_ret ret with
|
||||
| (`ErrorIsMinusOne | `ErrorIsNULL) as errcode ->
|
||||
pr " if (r != %s) {\n" (string_of_errcode errcode);
|
||||
trace_return ~indent:4 style "r";
|
||||
pr " } else {\n";
|
||||
trace_return_error ~indent:4 style;
|
||||
pr " }\n";
|
||||
| `CannotReturnError ->
|
||||
trace_return style "r";
|
||||
);
|
||||
pr "\n";
|
||||
pr " return r;\n";
|
||||
pr "}\n";
|
||||
pr "\n"
|
||||
@@ -910,7 +935,10 @@ check_state (guestfs_h *g, const char *caller)
|
||||
List.iter (
|
||||
fun (shortname, (ret, args, optargs as style), _, _, _, _, _) ->
|
||||
let name = "guestfs_" ^ shortname in
|
||||
let error_code = error_code_of ret in
|
||||
let errcode =
|
||||
match errcode_of_ret ret with
|
||||
| `CannotReturnError -> assert false
|
||||
| (`ErrorIsMinusOne | `ErrorIsNULL) as e -> e in
|
||||
|
||||
(* Generate the action stub. *)
|
||||
if optargs = [] then
|
||||
@@ -991,7 +1019,7 @@ check_state (guestfs_h *g, const char *caller)
|
||||
(* Check we are in the right state for sending a request. *)
|
||||
pr " if (check_state (g, \"%s\") == -1) {\n" shortname;
|
||||
trace_return_error ~indent:4 style;
|
||||
pr " return %s;\n" error_code;
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr " guestfs___set_busy (g);\n";
|
||||
pr "\n";
|
||||
@@ -1025,7 +1053,7 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
|
||||
shortname;
|
||||
pr " guestfs___end_busy (g);\n";
|
||||
pr " return %s;\n" error_code;
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr " args.%s.%s_val = (char *) %s;\n" n n n;
|
||||
pr " args.%s.%s_len = %s_size;\n" n n n
|
||||
@@ -1047,7 +1075,7 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " else\n";
|
||||
pr " args.%s = 0;\n" n
|
||||
| String n ->
|
||||
pr " args.%s = (char *) %s;\n" n n;
|
||||
pr " args.%s = (char *) optargs->%s;\n" n n;
|
||||
pr " else\n";
|
||||
pr " args.%s = (char *) \"\";\n" n
|
||||
| _ -> assert false
|
||||
@@ -1064,7 +1092,7 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " if (serial == -1) {\n";
|
||||
pr " guestfs___end_busy (g);\n";
|
||||
trace_return_error ~indent:4 style;
|
||||
pr " return %s;\n" error_code;
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr "\n";
|
||||
|
||||
@@ -1077,7 +1105,9 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " if (r == -1) {\n";
|
||||
pr " guestfs___end_busy (g);\n";
|
||||
trace_return_error ~indent:4 style;
|
||||
pr " return %s;\n" error_code;
|
||||
pr " /* daemon will send an error reply which we discard */\n";
|
||||
pr " guestfs___recv_discard (g, \"%s\");\n" shortname;
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr " if (r == -2) /* daemon cancelled */\n";
|
||||
pr " goto read_reply;\n";
|
||||
@@ -1102,7 +1132,7 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " if (r == -1) {\n";
|
||||
pr " guestfs___end_busy (g);\n";
|
||||
trace_return_error ~indent:4 style;
|
||||
pr " return %s;\n" error_code;
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr "\n";
|
||||
|
||||
@@ -1110,7 +1140,7 @@ check_state (guestfs_h *g, const char *caller)
|
||||
(String.uppercase shortname);
|
||||
pr " guestfs___end_busy (g);\n";
|
||||
trace_return_error ~indent:4 style;
|
||||
pr " return %s;\n" error_code;
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr "\n";
|
||||
|
||||
@@ -1129,7 +1159,7 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " free (err.error_message);\n";
|
||||
pr " free (err.errno_string);\n";
|
||||
pr " guestfs___end_busy (g);\n";
|
||||
pr " return %s;\n" error_code;
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr "\n";
|
||||
|
||||
@@ -1140,7 +1170,7 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
|
||||
pr " guestfs___end_busy (g);\n";
|
||||
trace_return_error ~indent:4 style;
|
||||
pr " return %s;\n" error_code;
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr "\n";
|
||||
| _ -> ()
|
||||
@@ -1231,16 +1261,16 @@ check_state (guestfs_h *g, const char *caller)
|
||||
| [] -> "g"
|
||||
| args -> name_of_argt (List.hd (List.rev args)) in
|
||||
|
||||
let rerrcode, rtype =
|
||||
let rtype =
|
||||
match ret with
|
||||
| RErr | RInt _ | RBool _ -> "-1", "int "
|
||||
| RInt64 _ -> "-1", "int64_t "
|
||||
| RConstString _ | RConstOptString _ -> "NULL", "const char *"
|
||||
| RString _ | RBufferOut _ -> "NULL", "char *"
|
||||
| RStringList _ | RHashtable _ -> "NULL", "char **"
|
||||
| RStruct (_, typ) -> "NULL", sprintf "struct guestfs_%s *" typ
|
||||
| RErr | RInt _ | RBool _ -> "int "
|
||||
| RInt64 _ -> "int64_t "
|
||||
| RConstString _ | RConstOptString _ -> "const char *"
|
||||
| RString _ | RBufferOut _ -> "char *"
|
||||
| RStringList _ | RHashtable _ -> "char **"
|
||||
| RStruct (_, typ) -> sprintf "struct guestfs_%s *" typ
|
||||
| RStructList (_, typ) ->
|
||||
"NULL", sprintf "struct guestfs_%s_list *" typ in
|
||||
sprintf "struct guestfs_%s_list *" typ in
|
||||
|
||||
(* The regular variable args function, just calls the _va variant. *)
|
||||
generate_prototype ~extern:false ~semicolon:false ~newline:true
|
||||
@@ -1286,17 +1316,22 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " break;\n";
|
||||
) optargs;
|
||||
|
||||
let errcode =
|
||||
match errcode_of_ret ret with
|
||||
| `CannotReturnError -> assert false
|
||||
| (`ErrorIsMinusOne | `ErrorIsNULL) as e -> e in
|
||||
|
||||
pr " default:\n";
|
||||
pr " error (g, \"%%s: unknown option %%d (this can happen if a program is compiled against a newer version of libguestfs, then dynamically linked to an older version)\",\n";
|
||||
pr " \"%s\", i);\n" shortname;
|
||||
pr " return %s;\n" rerrcode;
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr "\n";
|
||||
pr " uint64_t i_mask = UINT64_C(1) << i;\n";
|
||||
pr " if (optargs_s.bitmask & i_mask) {\n";
|
||||
pr " error (g, \"%%s: same optional argument specified more than once\",\n";
|
||||
pr " \"%s\");\n" shortname;
|
||||
pr " return %s;\n" rerrcode;
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr " optargs_s.bitmask |= i_mask;\n";
|
||||
pr " }\n";
|
||||
|
||||
@@ -792,25 +792,23 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
|
||||
) optargs;
|
||||
);
|
||||
|
||||
let error_code =
|
||||
match style_ret with
|
||||
| RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
|
||||
| RInt64 _ -> pr " int64_t r;\n"; "-1"
|
||||
| RConstString _ | RConstOptString _ ->
|
||||
pr " const char *r;\n"; "NULL"
|
||||
| RString _ -> pr " char *r;\n"; "NULL"
|
||||
| RStringList _ | RHashtable _ ->
|
||||
pr " char **r;\n";
|
||||
pr " size_t i;\n";
|
||||
"NULL"
|
||||
| RStruct (_, typ) ->
|
||||
pr " struct guestfs_%s *r;\n" typ; "NULL"
|
||||
| RStructList (_, typ) ->
|
||||
pr " struct guestfs_%s_list *r;\n" typ; "NULL"
|
||||
| RBufferOut _ ->
|
||||
pr " char *r;\n";
|
||||
pr " size_t size;\n";
|
||||
"NULL" in
|
||||
(match style_ret with
|
||||
| RErr | RInt _ | RBool _ -> pr " int r;\n"
|
||||
| RInt64 _ -> pr " int64_t r;\n"
|
||||
| RConstString _ | RConstOptString _ ->
|
||||
pr " const char *r;\n"
|
||||
| RString _ -> pr " char *r;\n"
|
||||
| RStringList _ | RHashtable _ ->
|
||||
pr " char **r;\n";
|
||||
pr " size_t i;\n"
|
||||
| RStruct (_, typ) ->
|
||||
pr " struct guestfs_%s *r;\n" typ
|
||||
| RStructList (_, typ) ->
|
||||
pr " struct guestfs_%s_list *r;\n" typ
|
||||
| RBufferOut _ ->
|
||||
pr " char *r;\n";
|
||||
pr " size_t size;\n"
|
||||
);
|
||||
|
||||
pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
|
||||
if optargs = [] then
|
||||
@@ -861,11 +859,21 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
|
||||
|
||||
pr ");\n";
|
||||
|
||||
if not expect_error then
|
||||
pr " if (r == %s)\n" error_code
|
||||
else
|
||||
pr " if (r != %s)\n" error_code;
|
||||
pr " return -1;\n";
|
||||
(match errcode_of_ret style_ret, expect_error with
|
||||
| `CannotReturnError, _ -> ()
|
||||
| `ErrorIsMinusOne, false ->
|
||||
pr " if (r == -1)\n";
|
||||
pr " return -1;\n";
|
||||
| `ErrorIsMinusOne, true ->
|
||||
pr " if (r != -1)\n";
|
||||
pr " return -1;\n";
|
||||
| `ErrorIsNULL, false ->
|
||||
pr " if (r == NULL)\n";
|
||||
pr " return -1;\n";
|
||||
| `ErrorIsNULL, true ->
|
||||
pr " if (r != NULL)\n";
|
||||
pr " return -1;\n";
|
||||
);
|
||||
|
||||
(* Insert the test code. *)
|
||||
(match test with
|
||||
|
||||
@@ -82,21 +82,20 @@ and generate_daemon_actions () =
|
||||
(* Generate server-side stubs. *)
|
||||
pr "static void %s_stub (XDR *xdr_in)\n" name;
|
||||
pr "{\n";
|
||||
let error_code =
|
||||
match ret with
|
||||
| RErr | RInt _ -> pr " int r;\n"; "-1"
|
||||
| RInt64 _ -> pr " int64_t r;\n"; "-1"
|
||||
| RBool _ -> pr " int r;\n"; "-1"
|
||||
| RConstString _ | RConstOptString _ ->
|
||||
failwithf "RConstString|RConstOptString cannot be used by daemon functions"
|
||||
| RString _ -> pr " char *r;\n"; "NULL"
|
||||
| RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
|
||||
| RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
|
||||
| RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
|
||||
| RBufferOut _ ->
|
||||
pr " size_t size = 1;\n";
|
||||
pr " char *r;\n";
|
||||
"NULL" in
|
||||
(match ret with
|
||||
| RErr | RInt _ -> pr " int r;\n"
|
||||
| RInt64 _ -> pr " int64_t r;\n"
|
||||
| RBool _ -> pr " int r;\n"
|
||||
| RConstString _ | RConstOptString _ ->
|
||||
failwithf "RConstString|RConstOptString cannot be used by daemon functions"
|
||||
| RString _ -> pr " char *r;\n"
|
||||
| RStringList _ | RHashtable _ -> pr " char **r;\n"
|
||||
| RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ
|
||||
| RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ
|
||||
| RBufferOut _ ->
|
||||
pr " size_t size = 1;\n";
|
||||
pr " char *r;\n"
|
||||
);
|
||||
|
||||
if args <> [] || optargs <> [] then (
|
||||
pr " struct guestfs_%s_args args;\n" name;
|
||||
@@ -123,18 +122,29 @@ and generate_daemon_actions () =
|
||||
let is_filein =
|
||||
List.exists (function FileIn _ -> true | _ -> false) args in
|
||||
|
||||
(* Reject unknown optional arguments. *)
|
||||
(* Reject unknown optional arguments.
|
||||
* Note this code is included even for calls with no optional
|
||||
* args because the caller must not pass optargs_bitmask != 0
|
||||
* in that case.
|
||||
*)
|
||||
if optargs <> [] then (
|
||||
let len = List.length optargs in
|
||||
let mask = Int64.lognot (Int64.pred (Int64.shift_left 1L len)) in
|
||||
pr " if (optargs_bitmask & UINT64_C(0x%Lx)) {\n" mask;
|
||||
if is_filein then
|
||||
pr " if (cancel_receive () != -2)\n";
|
||||
pr " cancel_receive ();\n";
|
||||
pr " reply_with_error (\"unknown option in optional arguments bitmask (this can happen if a program is compiled against a newer version of libguestfs, then run against an older version of the daemon)\");\n";
|
||||
pr " goto done;\n";
|
||||
pr " }\n";
|
||||
pr "\n"
|
||||
) else (
|
||||
pr " if (optargs_bitmask != 0) {\n";
|
||||
if is_filein then
|
||||
pr " cancel_receive ();\n";
|
||||
pr " reply_with_error (\"header optargs_bitmask field must be passed as 0 for calls that don't take optional arguments\");\n";
|
||||
pr " goto done;\n";
|
||||
pr " }\n";
|
||||
);
|
||||
pr "\n";
|
||||
|
||||
(* Decode arguments. *)
|
||||
if args <> [] || optargs <> [] then (
|
||||
@@ -142,8 +152,8 @@ and generate_daemon_actions () =
|
||||
pr "\n";
|
||||
pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
|
||||
if is_filein then
|
||||
pr " if (cancel_receive () != -2)\n";
|
||||
pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
|
||||
pr " cancel_receive ();\n";
|
||||
pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
|
||||
pr " goto done;\n";
|
||||
pr " }\n";
|
||||
let pr_args n =
|
||||
@@ -154,8 +164,8 @@ and generate_daemon_actions () =
|
||||
pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
|
||||
pr " if (%s == NULL) {\n" n;
|
||||
if is_filein then
|
||||
pr " if (cancel_receive () != -2)\n";
|
||||
pr " reply_with_perror (\"realloc\");\n";
|
||||
pr " cancel_receive ();\n";
|
||||
pr " reply_with_perror (\"realloc\");\n";
|
||||
pr " goto done;\n";
|
||||
pr " }\n";
|
||||
pr " %s[args.%s.%s_len] = NULL;\n" n n n;
|
||||
@@ -166,15 +176,15 @@ and generate_daemon_actions () =
|
||||
| Pathname n ->
|
||||
pr_args n;
|
||||
pr " ABS_PATH (%s, %s, goto done);\n"
|
||||
n (if is_filein then "cancel_receive ()" else "0");
|
||||
n (if is_filein then "cancel_receive ()" else "");
|
||||
| Device n ->
|
||||
pr_args n;
|
||||
pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
|
||||
n (if is_filein then "cancel_receive ()" else "0");
|
||||
n (if is_filein then "cancel_receive ()" else "");
|
||||
| Dev_or_Path n ->
|
||||
pr_args n;
|
||||
pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
|
||||
n (if is_filein then "cancel_receive ()" else "0");
|
||||
n (if is_filein then "cancel_receive ()" else "");
|
||||
| String n | Key n -> pr_args n
|
||||
| OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
|
||||
| StringList n ->
|
||||
@@ -188,7 +198,7 @@ and generate_daemon_actions () =
|
||||
pr " size_t i;\n";
|
||||
pr " for (i = 0; %s[i] != NULL; ++i)\n" n;
|
||||
pr " RESOLVE_DEVICE (%s[i], %s, goto done);\n" n
|
||||
(if is_filein then "cancel_receive ()" else "0");
|
||||
(if is_filein then "cancel_receive ()" else "");
|
||||
pr " }\n";
|
||||
| Bool n -> pr " %s = args.%s;\n" n n
|
||||
| Int n -> pr " %s = args.%s;\n" n n
|
||||
@@ -207,7 +217,7 @@ and generate_daemon_actions () =
|
||||
(* Emit NEED_ROOT just once, even when there are two or
|
||||
more Pathname args *)
|
||||
pr " NEED_ROOT (%s, goto done);\n"
|
||||
(if is_filein then "cancel_receive ()" else "0");
|
||||
(if is_filein then "cancel_receive ()" else "");
|
||||
);
|
||||
|
||||
(* Don't want to call the impl with any FileIn or FileOut
|
||||
@@ -223,11 +233,16 @@ and generate_daemon_actions () =
|
||||
pr ";\n" in
|
||||
|
||||
(match ret with
|
||||
| RConstOptString _ -> assert false
|
||||
| RErr | RInt _ | RInt64 _ | RBool _
|
||||
| RConstString _ | RConstOptString _
|
||||
| RConstString _
|
||||
| RString _ | RStringList _ | RHashtable _
|
||||
| RStruct (_, _) | RStructList (_, _) ->
|
||||
pr " if (r == %s)\n" error_code;
|
||||
let errcode =
|
||||
match errcode_of_ret ret with
|
||||
| `CannotReturnError -> assert false
|
||||
| (`ErrorIsMinusOne | `ErrorIsNULL) as e -> e in
|
||||
pr " if (r == %s)\n" (string_of_errcode errcode);
|
||||
pr " /* do_%s has already called reply_with_error */\n" name;
|
||||
pr " goto done;\n";
|
||||
pr "\n"
|
||||
@@ -235,7 +250,7 @@ and generate_daemon_actions () =
|
||||
pr " /* size == 0 && r == NULL could be a non-error case (just\n";
|
||||
pr " * an ordinary zero-length buffer), so be careful ...\n";
|
||||
pr " */\n";
|
||||
pr " if (size == 1 && r == %s)\n" error_code;
|
||||
pr " if (size == 1 && r == NULL)\n";
|
||||
pr " /* do_%s has already called reply_with_error */\n" name;
|
||||
pr " goto done;\n";
|
||||
pr "\n"
|
||||
|
||||
@@ -40,17 +40,17 @@ let danger_will_robinson =
|
||||
"B<This command is dangerous. Without careful use you
|
||||
can easily destroy all your data>."
|
||||
|
||||
let deprecation_notice flags =
|
||||
let deprecation_notice ?(prefix = "") flags =
|
||||
try
|
||||
let alt =
|
||||
find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
|
||||
let txt =
|
||||
sprintf "This function is deprecated.
|
||||
In new code, use the C<%s> call instead.
|
||||
In new code, use the L</%s%s> call instead.
|
||||
|
||||
Deprecated functions will not be removed from the API, but the
|
||||
fact that they are deprecated indicates that there are problems
|
||||
with correct use of these functions." alt in
|
||||
with correct use of these functions." prefix alt in
|
||||
Some txt
|
||||
with
|
||||
Not_found -> None
|
||||
|
||||
@@ -53,11 +53,13 @@ let generate_fish_cmds () =
|
||||
pr "#include <string.h>\n";
|
||||
pr "#include <inttypes.h>\n";
|
||||
pr "\n";
|
||||
pr "#include <guestfs.h>\n";
|
||||
pr "#include \"c-ctype.h\"\n";
|
||||
pr "#include \"full-write.h\"\n";
|
||||
pr "#include \"xstrtol.h\"\n";
|
||||
pr "\n";
|
||||
pr "#include <guestfs.h>\n";
|
||||
pr "#include \"fish.h\"\n";
|
||||
pr "#include \"fish-cmds.h\"\n";
|
||||
pr "#include \"options.h\"\n";
|
||||
pr "#include \"cmds_gperf.h\"\n";
|
||||
pr "\n";
|
||||
@@ -616,6 +618,22 @@ Guestfish will prompt for these separately."
|
||||
pr " }\n";
|
||||
pr "}\n"
|
||||
|
||||
and generate_fish_cmds_h () =
|
||||
generate_header CStyle GPLv2plus;
|
||||
|
||||
pr "#ifndef FISH_CMDS_H\n";
|
||||
pr "#define FISH_CMDS_H\n";
|
||||
pr "\n";
|
||||
|
||||
List.iter (
|
||||
fun (shortname, _, _, _, _, _, _) ->
|
||||
pr "extern int run_%s (const char *cmd, size_t argc, char *argv[]);\n"
|
||||
shortname
|
||||
) fish_commands;
|
||||
|
||||
pr "\n";
|
||||
pr "#endif /* FISH_CMDS_H */\n"
|
||||
|
||||
(* gperf code to do fast lookups of commands. *)
|
||||
and generate_fish_cmds_gperf () =
|
||||
generate_header CStyle GPLv2plus;
|
||||
|
||||
@@ -74,7 +74,7 @@ import Prelude hiding (truncate)
|
||||
import Foreign
|
||||
import Foreign.C
|
||||
import Foreign.C.Types
|
||||
import IO
|
||||
import System.IO
|
||||
import Control.Exception
|
||||
import Data.Typeable
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(* libguestfs
|
||||
* Copyright (C) 2009-2010 Red Hat Inc.
|
||||
* Copyright (C) 2009-2011 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
|
||||
@@ -37,6 +37,7 @@ let rec generate_java_java () =
|
||||
package com.redhat.et.libguestfs;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import com.redhat.et.libguestfs.LibGuestFSException;
|
||||
import com.redhat.et.libguestfs.PV;
|
||||
import com.redhat.et.libguestfs.VG;
|
||||
@@ -133,19 +134,33 @@ public class GuestFS {
|
||||
pr " * %s\n" doc;
|
||||
pr " * @throws LibGuestFSException\n";
|
||||
pr " */\n";
|
||||
pr " ";
|
||||
);
|
||||
pr " ";
|
||||
generate_java_prototype ~public:true ~semicolon:false name style;
|
||||
pr "\n";
|
||||
pr " {\n";
|
||||
pr " if (g == 0)\n";
|
||||
pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
|
||||
name;
|
||||
pr " ";
|
||||
if ret <> RErr then pr "return ";
|
||||
pr "_%s " name;
|
||||
generate_java_call_args ~handle:"g" style;
|
||||
pr ";\n";
|
||||
(match ret with
|
||||
| RErr ->
|
||||
pr " _%s " name;
|
||||
generate_java_call_args ~handle:"g" style;
|
||||
pr ";\n"
|
||||
| RHashtable _ ->
|
||||
pr " String[] r = _%s " name;
|
||||
generate_java_call_args ~handle:"g" style;
|
||||
pr ";\n";
|
||||
pr "\n";
|
||||
pr " HashMap rhash = new HashMap ();\n";
|
||||
pr " for (int i = 0; i < r.length; i += 2)\n";
|
||||
pr " rhash.put (r[i], r[i+1]);\n";
|
||||
pr " return rhash;\n"
|
||||
| _ ->
|
||||
pr " return _%s " name;
|
||||
generate_java_call_args ~handle:"g" style;
|
||||
pr ";\n"
|
||||
);
|
||||
pr " }\n";
|
||||
pr " ";
|
||||
generate_java_prototype ~privat:true ~native:true name style;
|
||||
@@ -183,7 +198,11 @@ and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
|
||||
| RStructList (_, typ) ->
|
||||
let name = java_name_of_struct typ in
|
||||
pr "%s[] " name;
|
||||
| RHashtable _ -> pr "HashMap<String,String> ";
|
||||
| RHashtable _ ->
|
||||
if not native then
|
||||
pr "Map<String,String> "
|
||||
else
|
||||
pr "String[] ";
|
||||
);
|
||||
|
||||
if native then pr "_%s " name else pr "%s " name;
|
||||
@@ -355,40 +374,40 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
|
||||
pr ")\n";
|
||||
pr "{\n";
|
||||
pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
|
||||
let error_code, no_ret =
|
||||
match ret with
|
||||
| RErr -> pr " int r;\n"; "-1", ""
|
||||
| RBool _
|
||||
| RInt _ -> pr " int r;\n"; "-1", "0"
|
||||
| RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
|
||||
| RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
|
||||
| RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
|
||||
| RString _ ->
|
||||
pr " jstring jr;\n";
|
||||
pr " char *r;\n"; "NULL", "NULL"
|
||||
| RStringList _ ->
|
||||
pr " jobjectArray jr;\n";
|
||||
pr " int r_len;\n";
|
||||
pr " jclass cl;\n";
|
||||
pr " jstring jstr;\n";
|
||||
pr " char **r;\n"; "NULL", "NULL"
|
||||
| RStruct (_, typ) ->
|
||||
pr " jobject jr;\n";
|
||||
pr " jclass cl;\n";
|
||||
pr " jfieldID fl;\n";
|
||||
pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
|
||||
| RStructList (_, typ) ->
|
||||
pr " jobjectArray jr;\n";
|
||||
pr " jclass cl;\n";
|
||||
pr " jfieldID fl;\n";
|
||||
pr " jobject jfl;\n";
|
||||
pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
|
||||
| RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
|
||||
| RBufferOut _ ->
|
||||
pr " jstring jr;\n";
|
||||
pr " char *r;\n";
|
||||
pr " size_t size;\n";
|
||||
"NULL", "NULL" in
|
||||
(match ret with
|
||||
| RErr -> pr " int r;\n"
|
||||
| RBool _
|
||||
| RInt _ -> pr " int r;\n"
|
||||
| RInt64 _ -> pr " int64_t r;\n"
|
||||
| RConstString _ -> pr " const char *r;\n"
|
||||
| RConstOptString _ -> pr " const char *r;\n"
|
||||
| RString _ ->
|
||||
pr " jstring jr;\n";
|
||||
pr " char *r;\n"
|
||||
| RStringList _
|
||||
| RHashtable _ ->
|
||||
pr " jobjectArray jr;\n";
|
||||
pr " int r_len;\n";
|
||||
pr " jclass cl;\n";
|
||||
pr " jstring jstr;\n";
|
||||
pr " char **r;\n"
|
||||
| RStruct (_, typ) ->
|
||||
pr " jobject jr;\n";
|
||||
pr " jclass cl;\n";
|
||||
pr " jfieldID fl;\n";
|
||||
pr " struct guestfs_%s *r;\n" typ
|
||||
| RStructList (_, typ) ->
|
||||
pr " jobjectArray jr;\n";
|
||||
pr " jclass cl;\n";
|
||||
pr " jfieldID fl;\n";
|
||||
pr " jobject jfl;\n";
|
||||
pr " struct guestfs_%s_list *r;\n" typ
|
||||
| RBufferOut _ ->
|
||||
pr " jstring jr;\n";
|
||||
pr " char *r;\n";
|
||||
pr " size_t size;\n"
|
||||
);
|
||||
|
||||
List.iter (
|
||||
function
|
||||
| Pathname n
|
||||
@@ -416,10 +435,10 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
|
||||
|
||||
let needs_i =
|
||||
(match ret with
|
||||
| RStringList _ | RStructList _ -> true
|
||||
| RStringList _ | RStructList _ | RHashtable _ -> true
|
||||
| RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
|
||||
| RConstOptString _
|
||||
| RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
|
||||
| RString _ | RBufferOut _ | RStruct _ -> false) ||
|
||||
List.exists (function
|
||||
| StringList _ -> true
|
||||
| DeviceList _ -> true
|
||||
@@ -508,10 +527,19 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
|
||||
) args;
|
||||
|
||||
(* Check for errors. *)
|
||||
pr " if (r == %s) {\n" error_code;
|
||||
pr " throw_exception (env, guestfs_last_error (g));\n";
|
||||
pr " return %s;\n" no_ret;
|
||||
pr " }\n";
|
||||
(match errcode_of_ret ret with
|
||||
| `CannotReturnError -> ()
|
||||
| `ErrorIsMinusOne ->
|
||||
pr " if (r == -1) {\n";
|
||||
pr " throw_exception (env, guestfs_last_error (g));\n";
|
||||
pr " return -1;\n";
|
||||
pr " }\n"
|
||||
| `ErrorIsNULL ->
|
||||
pr " if (r == NULL) {\n";
|
||||
pr " throw_exception (env, guestfs_last_error (g));\n";
|
||||
pr " return NULL;\n";
|
||||
pr " }\n"
|
||||
);
|
||||
|
||||
(* Return value. *)
|
||||
(match ret with
|
||||
@@ -526,7 +554,8 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
|
||||
pr " jr = (*env)->NewStringUTF (env, r);\n";
|
||||
pr " free (r);\n";
|
||||
pr " return jr;\n"
|
||||
| RStringList _ ->
|
||||
| RStringList _
|
||||
| RHashtable _ ->
|
||||
pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
|
||||
pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
|
||||
pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
|
||||
@@ -546,10 +575,6 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
|
||||
let jtyp = java_name_of_struct typ in
|
||||
let cols = cols_of_struct typ in
|
||||
generate_java_struct_list_return typ jtyp cols
|
||||
| RHashtable _ ->
|
||||
(* XXX *)
|
||||
pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
|
||||
pr " return NULL;\n"
|
||||
| RBufferOut _ ->
|
||||
pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
|
||||
pr " free (r);\n";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(* libguestfs
|
||||
* Copyright (C) 2009-2010 Red Hat Inc.
|
||||
* Copyright (C) 2009-2011 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
|
||||
@@ -50,7 +50,7 @@ let perror msg = function
|
||||
(* Main program. *)
|
||||
let () =
|
||||
let lock_fd =
|
||||
try openfile "HACKING" [O_RDWR] 0
|
||||
try openfile "BUGS" [O_RDWR] 0
|
||||
with
|
||||
| Unix_error (ENOENT, _, _) ->
|
||||
eprintf "\
|
||||
@@ -60,7 +60,7 @@ Run it from the top source directory using the command
|
||||
";
|
||||
exit 1
|
||||
| exn ->
|
||||
perror "open: HACKING" exn;
|
||||
perror "open: BUGS" exn;
|
||||
exit 1 in
|
||||
|
||||
(* Acquire a lock so parallel builds won't try to run the generator
|
||||
@@ -70,7 +70,7 @@ Run it from the top source directory using the command
|
||||
*)
|
||||
(try lockf lock_fd F_LOCK 1
|
||||
with exn ->
|
||||
perror "lock: HACKING" exn;
|
||||
perror "lock: BUGS" exn;
|
||||
exit 1);
|
||||
|
||||
(* Read the API versions file. *)
|
||||
@@ -98,6 +98,7 @@ Run it from the top source directory using the command
|
||||
output_to "fish/cmds_gperf.gperf" generate_fish_cmds_gperf;
|
||||
output_to "fish/cmds.c" generate_fish_cmds;
|
||||
output_to "fish/completion.c" generate_fish_completion;
|
||||
output_to "fish/fish-cmds.h" generate_fish_cmds_h;
|
||||
output_to "fish/guestfish-commands.pod" generate_fish_commands_pod;
|
||||
output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
|
||||
output_to "fish/prepopts.c" generate_fish_prep_options_c;
|
||||
|
||||
@@ -430,31 +430,28 @@ copy_table (char * const * argv)
|
||||
) optargs
|
||||
);
|
||||
|
||||
let error_code =
|
||||
match ret with
|
||||
| RErr -> pr " int r;\n"; "-1"
|
||||
| RInt _ -> pr " int r;\n"; "-1"
|
||||
| RInt64 _ -> pr " int64_t r;\n"; "-1"
|
||||
| RBool _ -> pr " int r;\n"; "-1"
|
||||
| RConstString _ | RConstOptString _ ->
|
||||
pr " const char *r;\n"; "NULL"
|
||||
| RString _ -> pr " char *r;\n"; "NULL"
|
||||
| RStringList _ ->
|
||||
pr " size_t i;\n";
|
||||
pr " char **r;\n";
|
||||
"NULL"
|
||||
| RStruct (_, typ) ->
|
||||
pr " struct guestfs_%s *r;\n" typ; "NULL"
|
||||
| RStructList (_, typ) ->
|
||||
pr " struct guestfs_%s_list *r;\n" typ; "NULL"
|
||||
| RHashtable _ ->
|
||||
pr " size_t i;\n";
|
||||
pr " char **r;\n";
|
||||
"NULL"
|
||||
| RBufferOut _ ->
|
||||
pr " char *r;\n";
|
||||
pr " size_t size;\n";
|
||||
"NULL" in
|
||||
(match ret with
|
||||
| RErr -> pr " int r;\n"
|
||||
| RInt _ -> pr " int r;\n"
|
||||
| RInt64 _ -> pr " int64_t r;\n"
|
||||
| RBool _ -> pr " int r;\n"
|
||||
| RConstString _ | RConstOptString _ ->
|
||||
pr " const char *r;\n"
|
||||
| RString _ -> pr " char *r;\n"
|
||||
| RStringList _ ->
|
||||
pr " size_t i;\n";
|
||||
pr " char **r;\n"
|
||||
| RStruct (_, typ) ->
|
||||
pr " struct guestfs_%s *r;\n" typ
|
||||
| RStructList (_, typ) ->
|
||||
pr " struct guestfs_%s_list *r;\n" typ
|
||||
| RHashtable _ ->
|
||||
pr " size_t i;\n";
|
||||
pr " char **r;\n"
|
||||
| RBufferOut _ ->
|
||||
pr " char *r;\n";
|
||||
pr " size_t size;\n"
|
||||
);
|
||||
pr "\n";
|
||||
|
||||
pr " caml_enter_blocking_section ();\n";
|
||||
@@ -487,8 +484,15 @@ copy_table (char * const * argv)
|
||||
| StringList _ | DeviceList _ | Pointer _ -> ()
|
||||
) optargs;
|
||||
|
||||
pr " if (r == %s)\n" error_code;
|
||||
pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
|
||||
(match errcode_of_ret ret with
|
||||
| `CannotReturnError -> ()
|
||||
| `ErrorIsMinusOne ->
|
||||
pr " if (r == -1)\n";
|
||||
pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
|
||||
| `ErrorIsNULL ->
|
||||
pr " if (r == NULL)\n";
|
||||
pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
|
||||
);
|
||||
pr "\n";
|
||||
|
||||
(match ret with
|
||||
|
||||
@@ -357,28 +357,27 @@ PHP_FUNCTION (guestfs_last_error)
|
||||
);
|
||||
|
||||
(* Return value. *)
|
||||
let error_code =
|
||||
match ret with
|
||||
| RErr -> pr " int r;\n"; "-1"
|
||||
| RBool _
|
||||
| RInt _ -> pr " int r;\n"; "-1"
|
||||
| RInt64 _ -> pr " int64_t r;\n"; "-1"
|
||||
| RConstString _ -> pr " const char *r;\n"; "NULL"
|
||||
| RConstOptString _ -> pr " const char *r;\n"; "NULL"
|
||||
| RString _ ->
|
||||
pr " char *r;\n"; "NULL"
|
||||
| RStringList _ ->
|
||||
pr " char **r;\n"; "NULL"
|
||||
| RStruct (_, typ) ->
|
||||
pr " struct guestfs_%s *r;\n" typ; "NULL"
|
||||
| RStructList (_, typ) ->
|
||||
pr " struct guestfs_%s_list *r;\n" typ; "NULL"
|
||||
| RHashtable _ ->
|
||||
pr " char **r;\n"; "NULL"
|
||||
| RBufferOut _ ->
|
||||
pr " char *r;\n";
|
||||
pr " size_t size;\n";
|
||||
"NULL" in
|
||||
(match ret with
|
||||
| RErr -> pr " int r;\n"
|
||||
| RBool _
|
||||
| RInt _ -> pr " int r;\n"
|
||||
| RInt64 _ -> pr " int64_t r;\n"
|
||||
| RConstString _ -> pr " const char *r;\n"
|
||||
| RConstOptString _ -> pr " const char *r;\n"
|
||||
| RString _ ->
|
||||
pr " char *r;\n"
|
||||
| RStringList _ ->
|
||||
pr " char **r;\n"
|
||||
| RStruct (_, typ) ->
|
||||
pr " struct guestfs_%s *r;\n" typ
|
||||
| RStructList (_, typ) ->
|
||||
pr " struct guestfs_%s_list *r;\n" typ
|
||||
| RHashtable _ ->
|
||||
pr " char **r;\n"
|
||||
| RBufferOut _ ->
|
||||
pr " char *r;\n";
|
||||
pr " size_t size;\n"
|
||||
);
|
||||
|
||||
(* Call the function. *)
|
||||
if optargs = [] then
|
||||
@@ -410,9 +409,17 @@ PHP_FUNCTION (guestfs_last_error)
|
||||
) args;
|
||||
|
||||
(* Check for errors. *)
|
||||
pr " if (r == %s) {\n" error_code;
|
||||
pr " RETURN_FALSE;\n";
|
||||
pr " }\n";
|
||||
(match errcode_of_ret ret with
|
||||
| `CannotReturnError -> ()
|
||||
| `ErrorIsMinusOne ->
|
||||
pr " if (r == -1) {\n";
|
||||
pr " RETURN_FALSE;\n";
|
||||
pr " }\n"
|
||||
| `ErrorIsNULL ->
|
||||
pr " if (r == NULL) {\n";
|
||||
pr " RETURN_FALSE;\n";
|
||||
pr " }\n"
|
||||
);
|
||||
pr "\n";
|
||||
|
||||
(* Convert the return value. *)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(* libguestfs
|
||||
* Copyright (C) 2009-2010 Red Hat Inc.
|
||||
* Copyright (C) 2009-2011 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
|
||||
@@ -180,6 +180,7 @@ py_guestfs_create (PyObject *self, PyObject *args)
|
||||
static PyObject *
|
||||
py_guestfs_close (PyObject *self, PyObject *args)
|
||||
{
|
||||
PyThreadState *py_save = NULL;
|
||||
PyObject *py_g;
|
||||
guestfs_h *g;
|
||||
|
||||
@@ -187,7 +188,11 @@ py_guestfs_close (PyObject *self, PyObject *args)
|
||||
return NULL;
|
||||
g = get_handle (py_g);
|
||||
|
||||
if (PyEval_ThreadsInitialized ())
|
||||
py_save = PyEval_SaveThread ();
|
||||
guestfs_close (g);
|
||||
if (PyEval_ThreadsInitialized ())
|
||||
PyEval_RestoreThread (py_save);
|
||||
|
||||
Py_INCREF (Py_None);
|
||||
return Py_None;
|
||||
@@ -284,6 +289,7 @@ py_guestfs_close (PyObject *self, PyObject *args)
|
||||
pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
|
||||
pr "{\n";
|
||||
|
||||
pr " PyThreadState *py_save = NULL;\n";
|
||||
pr " PyObject *py_g;\n";
|
||||
pr " guestfs_h *g;\n";
|
||||
pr " PyObject *py_r;\n";
|
||||
@@ -293,21 +299,20 @@ py_guestfs_close (PyObject *self, PyObject *args)
|
||||
pr " struct guestfs_%s_argv *optargs = &optargs_s;\n" name;
|
||||
);
|
||||
|
||||
let error_code =
|
||||
match ret with
|
||||
| RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
|
||||
| RInt64 _ -> pr " int64_t r;\n"; "-1"
|
||||
| RConstString _ | RConstOptString _ ->
|
||||
pr " const char *r;\n"; "NULL"
|
||||
| RString _ -> pr " char *r;\n"; "NULL"
|
||||
| RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
|
||||
| RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
|
||||
| RStructList (_, typ) ->
|
||||
pr " struct guestfs_%s_list *r;\n" typ; "NULL"
|
||||
| RBufferOut _ ->
|
||||
pr " char *r;\n";
|
||||
pr " size_t size;\n";
|
||||
"NULL" in
|
||||
(match ret with
|
||||
| RErr | RInt _ | RBool _ -> pr " int r;\n"
|
||||
| RInt64 _ -> pr " int64_t r;\n"
|
||||
| RConstString _ | RConstOptString _ ->
|
||||
pr " const char *r;\n"
|
||||
| RString _ -> pr " char *r;\n"
|
||||
| RStringList _ | RHashtable _ -> pr " char **r;\n"
|
||||
| RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
|
||||
| RStructList (_, typ) ->
|
||||
pr " struct guestfs_%s_list *r;\n" typ
|
||||
| RBufferOut _ ->
|
||||
pr " char *r;\n";
|
||||
pr " size_t size;\n"
|
||||
);
|
||||
|
||||
List.iter (
|
||||
function
|
||||
@@ -441,6 +446,14 @@ py_guestfs_close (PyObject *self, PyObject *args)
|
||||
pr "\n"
|
||||
);
|
||||
|
||||
(* Release Python GIL while running. This code is from
|
||||
* libvirt/python/typewrappers.h. Thanks to Dan Berrange for
|
||||
* showing us how to do this properly.
|
||||
*)
|
||||
pr " if (PyEval_ThreadsInitialized ())\n";
|
||||
pr " py_save = PyEval_SaveThread ();\n";
|
||||
pr "\n";
|
||||
|
||||
if optargs = [] then
|
||||
pr " r = guestfs_%s " name
|
||||
else
|
||||
@@ -448,6 +461,11 @@ py_guestfs_close (PyObject *self, PyObject *args)
|
||||
generate_c_call_args ~handle:"g" style;
|
||||
pr ";\n";
|
||||
|
||||
pr "\n";
|
||||
pr " if (PyEval_ThreadsInitialized ())\n";
|
||||
pr " PyEval_RestoreThread (py_save);\n";
|
||||
pr "\n";
|
||||
|
||||
List.iter (
|
||||
function
|
||||
| Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
|
||||
@@ -457,10 +475,19 @@ py_guestfs_close (PyObject *self, PyObject *args)
|
||||
pr " free (%s);\n" n
|
||||
) args;
|
||||
|
||||
pr " if (r == %s) {\n" error_code;
|
||||
pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
|
||||
pr " return NULL;\n";
|
||||
pr " }\n";
|
||||
(match errcode_of_ret ret with
|
||||
| `CannotReturnError -> ()
|
||||
| `ErrorIsMinusOne ->
|
||||
pr " if (r == -1) {\n";
|
||||
pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
|
||||
pr " return NULL;\n";
|
||||
pr " }\n"
|
||||
| `ErrorIsNULL ->
|
||||
pr " if (r == NULL) {\n";
|
||||
pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
|
||||
pr " return NULL;\n";
|
||||
pr " }\n"
|
||||
);
|
||||
pr "\n";
|
||||
|
||||
(match ret with
|
||||
@@ -639,6 +666,18 @@ class GuestFS:
|
||||
let doc = String.concat "\n " doc in
|
||||
pr " u\"\"\"%s\"\"\"\n" doc;
|
||||
);
|
||||
(* Callers might pass in iterables instead of plain lists;
|
||||
* convert those to plain lists because the C side of things
|
||||
* cannot deal with iterables. (RHBZ#693306).
|
||||
*)
|
||||
List.iter (
|
||||
function
|
||||
| Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
|
||||
| FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
|
||||
| BufferIn _ | Pointer _ -> ()
|
||||
| StringList n | DeviceList n ->
|
||||
pr " %s = list (%s)\n" n n
|
||||
) args;
|
||||
pr " return libguestfsmod.%s (self._o" name;
|
||||
List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (args@optargs);
|
||||
pr ")\n\n";
|
||||
|
||||
@@ -184,21 +184,20 @@ static VALUE ruby_guestfs_close (VALUE gv)
|
||||
pr "\n";
|
||||
);
|
||||
|
||||
let error_code =
|
||||
match ret with
|
||||
| RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
|
||||
| RInt64 _ -> pr " int64_t r;\n"; "-1"
|
||||
| RConstString _ | RConstOptString _ ->
|
||||
pr " const char *r;\n"; "NULL"
|
||||
| RString _ -> pr " char *r;\n"; "NULL"
|
||||
| RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
|
||||
| RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
|
||||
| RStructList (_, typ) ->
|
||||
pr " struct guestfs_%s_list *r;\n" typ; "NULL"
|
||||
| RBufferOut _ ->
|
||||
pr " char *r;\n";
|
||||
pr " size_t size;\n";
|
||||
"NULL" in
|
||||
(match ret with
|
||||
| RErr | RInt _ | RBool _ -> pr " int r;\n"
|
||||
| RInt64 _ -> pr " int64_t r;\n"
|
||||
| RConstString _ | RConstOptString _ ->
|
||||
pr " const char *r;\n"
|
||||
| RString _ -> pr " char *r;\n"
|
||||
| RStringList _ | RHashtable _ -> pr " char **r;\n"
|
||||
| RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
|
||||
| RStructList (_, typ) ->
|
||||
pr " struct guestfs_%s_list *r;\n" typ
|
||||
| RBufferOut _ ->
|
||||
pr " char *r;\n";
|
||||
pr " size_t size;\n"
|
||||
);
|
||||
pr "\n";
|
||||
|
||||
if optargs = [] then
|
||||
@@ -217,8 +216,15 @@ static VALUE ruby_guestfs_close (VALUE gv)
|
||||
pr " free (%s);\n" n
|
||||
) args;
|
||||
|
||||
pr " if (r == %s)\n" error_code;
|
||||
pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
|
||||
(match errcode_of_ret ret with
|
||||
| `CannotReturnError -> ()
|
||||
| `ErrorIsMinusOne ->
|
||||
pr " if (r == -1)\n";
|
||||
pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n"
|
||||
| `ErrorIsNULL ->
|
||||
pr " if (r == NULL)\n";
|
||||
pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n"
|
||||
);
|
||||
pr "\n";
|
||||
|
||||
(match ret with
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(* libguestfs
|
||||
* Copyright (C) 2009-2010 Red Hat Inc.
|
||||
* Copyright (C) 2009-2011 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
|
||||
@@ -203,6 +203,8 @@ and argt =
|
||||
*)
|
||||
| Pointer of (string * string)
|
||||
|
||||
type errcode = [ `CannotReturnError | `ErrorIsMinusOne | `ErrorIsNULL ]
|
||||
|
||||
type flags =
|
||||
| ProtocolLimitWarning (* display warning about protocol size limits *)
|
||||
| DangerWillRobinson (* flags particularly dangerous commands *)
|
||||
@@ -218,7 +220,7 @@ and fish_output_t =
|
||||
| FishOutputOctal (* for int return, print in octal *)
|
||||
| FishOutputHexadecimal (* for int return, print in hex *)
|
||||
|
||||
(* See section "Tests" in HACKING file. *)
|
||||
(* See guestfs(3)/EXTENDING LIBGUESTFS. *)
|
||||
type tests = (test_init * test_prereq * test) list
|
||||
and test =
|
||||
(* Run the command sequence and just expect nothing to fail. *)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(* libguestfs
|
||||
* Copyright (C) 2009-2010 Red Hat Inc.
|
||||
* Copyright (C) 2009-2011 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
|
||||
@@ -28,6 +28,21 @@ open Printf
|
||||
|
||||
open Generator_types
|
||||
|
||||
let errcode_of_ret = function
|
||||
| RConstOptString _ ->
|
||||
`CannotReturnError
|
||||
| RErr | RInt _ | RBool _ | RInt64 _ ->
|
||||
`ErrorIsMinusOne
|
||||
| RConstString _
|
||||
| RString _ | RBufferOut _
|
||||
| RStringList _ | RHashtable _
|
||||
| RStruct _ | RStructList _ ->
|
||||
`ErrorIsNULL
|
||||
|
||||
let string_of_errcode = function
|
||||
| `ErrorIsMinusOne -> "-1"
|
||||
| `ErrorIsNULL -> "NULL"
|
||||
|
||||
(* Generate a uuidgen-compatible UUID (used in tests). However to
|
||||
* avoid having the UUID change every time we rebuild the tests,
|
||||
* generate it as a function of the contents of the
|
||||
@@ -40,6 +55,14 @@ open Generator_types
|
||||
*)
|
||||
let uuidgen () =
|
||||
let s = Digest.to_hex (Digest.file "generator/generator_actions.ml") in
|
||||
|
||||
(* In util-linux <= 2.19, mkswap -U cannot handle the first byte of
|
||||
* the UUID being zero, so we artificially rewrite such UUIDs.
|
||||
* http://article.gmane.org/gmane.linux.utilities.util-linux-ng/4273
|
||||
*)
|
||||
if s.[0] = '0' && s.[1] = '0' then
|
||||
s.[0] <- '1';
|
||||
|
||||
String.sub s 0 8 ^ "-"
|
||||
^ String.sub s 8 4 ^ "-"
|
||||
^ String.sub s 12 4 ^ "-"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(* libguestfs
|
||||
* Copyright (C) 2009-2010 Red Hat Inc.
|
||||
* Copyright (C) 2009-2011 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
|
||||
@@ -20,6 +20,17 @@
|
||||
|
||||
(** Useful utility functions. *)
|
||||
|
||||
val errcode_of_ret : Generator_types.ret -> Generator_types.errcode
|
||||
(** Map [ret] type to the error indication that the action returns,
|
||||
eg. [errcode_of_ret RErr] => [`ErrorIsMinusOne] (meaning that
|
||||
these actions return [-1]).
|
||||
|
||||
Note that [RConstOptString] cannot return an error indication, and
|
||||
this returns [`CannotReturnError]. Callers must deal with it. *)
|
||||
|
||||
val string_of_errcode : [`ErrorIsMinusOne|`ErrorIsNULL] -> string
|
||||
(** Return errcode as a string. Untyped for [`CannotReturnError]. *)
|
||||
|
||||
val uuidgen : unit -> string
|
||||
(** Generate a random UUID (used in tests). *)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{- libguestfs Haskell bindings
|
||||
Copyright (C) 2009-2010 Red Hat Inc.
|
||||
Copyright (C) 2009-2011 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
|
||||
|
||||
@@ -30,6 +30,7 @@ if HAVE_HASKELL
|
||||
TESTS_ENVIRONMENT = \
|
||||
LD_LIBRARY_PATH=$(top_builddir)/src/.libs \
|
||||
LIBGUESTFS_PATH=$(top_builddir)/appliance \
|
||||
TMPDIR=$(top_builddir) \
|
||||
$(VG)
|
||||
|
||||
TESTS = run-bindtests Guestfs005Load Guestfs010Basic
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* CSS to make pod2html files look a little bit better. */
|
||||
@import url("http://people.redhat.com/~rjones/css/standard.css");
|
||||
|
||||
pre.example {
|
||||
font-weight: bold;
|
||||
width: 40em;
|
||||
border: 1px solid #c00;
|
||||
div.example pre {
|
||||
/*font-weight: bold;*/
|
||||
width: 40em;
|
||||
border: 1px solid #c00;
|
||||
}
|
||||
@@ -171,6 +171,7 @@ $(builddir)/test-grep.txt.gz: test-grep.txt
|
||||
fedora.img: guest-aux/make-fedora-img.sh guest-aux/fedora-name.db
|
||||
LIBGUESTFS_PATH=../appliance \
|
||||
LD_LIBRARY_PATH=../src/.libs \
|
||||
TMPDIR=$(top_builddir) \
|
||||
bash $<
|
||||
|
||||
guest-aux/fedora-name.db: guest-aux/fedora-name.db.txt
|
||||
@@ -178,21 +179,24 @@ guest-aux/fedora-name.db: guest-aux/fedora-name.db.txt
|
||||
|
||||
# Make a (dummy) Debian image.
|
||||
debian.img: guest-aux/make-debian-img.sh
|
||||
LIBGUESTFS_PATH=../appliance \
|
||||
LD_LIBRARY_PATH=../src/.libs \
|
||||
LIBGUESTFS_PATH=$(top_builddir)/appliance \
|
||||
LD_LIBRARY_PATH=$(top_builddir)/src/.libs \
|
||||
TMPDIR=$(top_builddir) \
|
||||
bash $<
|
||||
|
||||
# Make a (dummy) Ubuntu image.
|
||||
ubuntu.img: guest-aux/make-ubuntu-img.sh
|
||||
LIBGUESTFS_PATH=../appliance \
|
||||
LD_LIBRARY_PATH=../src/.libs \
|
||||
LIBGUESTFS_PATH=$(top_builddir)/appliance \
|
||||
LD_LIBRARY_PATH=$(top_builddir)/src/.libs \
|
||||
TMPDIR=$(top_builddir) \
|
||||
bash $<
|
||||
|
||||
# Make a (dummy) Windows image.
|
||||
windows.img: guest-aux/make-windows-img.sh \
|
||||
guest-aux/windows-software guest-aux/windows-system
|
||||
LIBGUESTFS_PATH=../appliance \
|
||||
LD_LIBRARY_PATH=../src/.libs \
|
||||
LIBGUESTFS_PATH=$(top_builddir)/appliance \
|
||||
LD_LIBRARY_PATH=$(top_builddir)/src/.libs \
|
||||
TMPDIR=$(top_builddir) \
|
||||
bash $<
|
||||
|
||||
# Since users might not have the tools needed to create this, we
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash -
|
||||
# libguestfs
|
||||
# Copyright (C) 2010 Red Hat Inc.
|
||||
# Copyright (C) 2010-2011 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
|
||||
@@ -21,6 +21,20 @@
|
||||
export LANG=C
|
||||
set -e
|
||||
|
||||
# If the currently compiled libguestfs doesn't support
|
||||
# ntfs-3g/ntfsprogs then we cannot create a Windows phony image.
|
||||
# Nothing actually uses windows.img in the standard build so we can
|
||||
# just 'touch' it and emit a warning.
|
||||
if ! ../fish/guestfish -a /dev/null run : available "ntfs3g ntfsprogs"; then
|
||||
echo "***"
|
||||
echo "Warning: cannot create windows.img because there is no NTFS"
|
||||
echo "support in this build of libguestfs. Just touching the output"
|
||||
echo "file instead."
|
||||
echo "***"
|
||||
touch windows.img
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Create a disk image.
|
||||
../fish/guestfish <<'EOF'
|
||||
sparse windows.img.tmp 512M
|
||||
|
||||
@@ -88,10 +88,18 @@ endif
|
||||
# can run them. Instead you can run them by hand.
|
||||
|
||||
example-debian.xml:
|
||||
./run-inspector-locally ../images/debian.img > $@
|
||||
rm -f $@ $@-t
|
||||
./run-inspector-locally ../images/debian.img > $@-t
|
||||
mv $@-t $@
|
||||
example-fedora.xml:
|
||||
./run-inspector-locally ../images/fedora.img > $@
|
||||
rm -f $@ $@-t
|
||||
./run-inspector-locally ../images/fedora.img > $@-t
|
||||
mv $@-t $@
|
||||
example-ubuntu.xml:
|
||||
./run-inspector-locally ../images/ubuntu.img > $@
|
||||
rm -f $@ $@-t
|
||||
./run-inspector-locally ../images/ubuntu.img > $@-t
|
||||
mv $@-t $@
|
||||
example-windows.xml:
|
||||
./run-inspector-locally ../images/windows.img | fgrep -v '<uuid>' > $@
|
||||
rm -f $@ $@-t
|
||||
./run-inspector-locally ../images/windows.img | fgrep -v '<uuid>' > $@-t
|
||||
mv $@-t $@
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<minor_version>0</minor_version>
|
||||
<package_format>deb</package_format>
|
||||
<package_management>apt</package_management>
|
||||
<hostname>debian.invalid</hostname>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/debian/root">/</mountpoint>
|
||||
<mountpoint dev="/dev/debian/usr">/usr</mountpoint>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<minor_version>0</minor_version>
|
||||
<package_format>rpm</package_format>
|
||||
<package_management>yum</package_management>
|
||||
<hostname>fedora.invalid</hostname>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/VG/Root">/</mountpoint>
|
||||
<mountpoint dev="/dev/sda1">/boot</mountpoint>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<minor_version>10</minor_version>
|
||||
<package_format>deb</package_format>
|
||||
<package_management>apt</package_management>
|
||||
<hostname>ubuntu.invalid</hostname>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda2">/</mountpoint>
|
||||
<mountpoint dev="/dev/sda1">/boot</mountpoint>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<major_version>6</major_version>
|
||||
<minor_version>1</minor_version>
|
||||
<windows_systemroot>/Windows</windows_systemroot>
|
||||
<hostname>windows.invalid</hostname>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda2">/</mountpoint>
|
||||
</mountpoints>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <locale.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <libxml/xmlIO.h>
|
||||
@@ -407,6 +408,14 @@ output_root (xmlTextWriterPtr xo, char *root)
|
||||
free (str);
|
||||
);
|
||||
|
||||
str = guestfs_inspect_get_hostname (g, root);
|
||||
if (!str) exit (EXIT_FAILURE);
|
||||
if (STRNEQ (str, "unknown"))
|
||||
XMLERROR (-1,
|
||||
xmlTextWriterWriteElement (xo, BAD_CAST "hostname",
|
||||
BAD_CAST str));
|
||||
free (str);
|
||||
|
||||
output_mountpoints (xo, root);
|
||||
|
||||
output_filesystems (xo, root);
|
||||
|
||||
@@ -218,9 +218,7 @@ type, the label, and the UUID.
|
||||
|
||||
The related elements E<lt>package_formatE<gt>,
|
||||
E<lt>package_managementE<gt> and E<lt>applicationsE<gt> describe
|
||||
applications installed in the virtual machine. At the moment we are
|
||||
only able to list RPMs and Debian packages installed, but in future we
|
||||
will support other Linux distros and Windows.
|
||||
applications installed in the virtual machine.
|
||||
|
||||
E<lt>package_formatE<gt>, if present, describes the packaging
|
||||
system used. Typical values would be C<rpm> and C<deb>.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
|
||||
<!-- -*- xml -*-
|
||||
This is a RELAX NG schema for the output of 'virt-inspector - -xml'.
|
||||
This is a RELAX NG schema for the output of 'virt-inspector'.
|
||||
|
||||
To validate an existing document against this schema, you can
|
||||
use xmllint, like this:
|
||||
|
||||
virt-inspector - -xml Foo > output.xml
|
||||
virt-inspector -d Foo > output.xml
|
||||
xmllint - -noout - -relaxng virt-inspector.rng output.xml
|
||||
|
||||
(Note that because of limitations of XML, I have had to put spaces
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
<optional><element name="package_format"><text/></element></optional>
|
||||
<optional><element name="package_management"><text/></element></optional>
|
||||
<optional><element name="hostname"><text/></element></optional>
|
||||
|
||||
<ref name="mountpoints"/>
|
||||
<ref name="filesystems"/>
|
||||
|
||||
@@ -102,7 +102,8 @@ TESTS = run-bindtests run-java-tests
|
||||
TESTS_ENVIRONMENT = \
|
||||
JAVA=$(JAVA) \
|
||||
CLASSPATH=.:t:libguestfs-$(VERSION).jar \
|
||||
LIBGUESTFS_PATH=$(top_builddir)/appliance
|
||||
LIBGUESTFS_PATH=$(top_builddir)/appliance \
|
||||
TMPDIR=$(top_builddir)
|
||||
|
||||
noinst_DATA = Bindtests.class $(java_tests:.java=.class)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# generator/generator_*.ml
|
||||
# ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
|
||||
#
|
||||
# Copyright (C) 2009-2010 Red Hat Inc.
|
||||
# Copyright (C) 2009-2011 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh -
|
||||
# libguestfs Perl bindings
|
||||
# Copyright (C) 2009 Red Hat Inc.
|
||||
# Copyright (C) 2009-2011 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
|
||||
@@ -20,5 +20,5 @@ set -e
|
||||
|
||||
for f in t/*.class; do
|
||||
classname=$(basename $f .class)
|
||||
$JAVA -Djava.library.path=.libs $classname
|
||||
$JAVA -Djava.library.path=.libs -ea $classname
|
||||
done
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Map;
|
||||
import com.redhat.et.libguestfs.*;
|
||||
|
||||
public class GuestFS010Basic
|
||||
@@ -24,6 +25,10 @@ public class GuestFS010Basic
|
||||
public static void main (String[] argv)
|
||||
{
|
||||
try {
|
||||
// Delete any previous test file if one was left around.
|
||||
File old = new File ("test.img");
|
||||
old.delete ();
|
||||
|
||||
RandomAccessFile f = new RandomAccessFile ("test.img", "rw");
|
||||
f.setLength (500 * 1024 * 1024);
|
||||
f.close ();
|
||||
@@ -41,6 +46,15 @@ public class GuestFS010Basic
|
||||
assert lvs[0].equals ("/dev/VG/LV1");
|
||||
assert lvs[1].equals ("/dev/VG/LV2");
|
||||
|
||||
g.mkfs ("ext2", "/dev/VG/LV1");
|
||||
|
||||
Map<String,String> m = g.list_filesystems ();
|
||||
assert m.containsKey ("/dev/VG/LV1");
|
||||
assert m.size () == 2;
|
||||
|
||||
assert m.get ("/dev/VG/LV1").equals ("ext2");
|
||||
assert m.get ("/dev/VG/LV2").equals ("unknown");
|
||||
|
||||
g.close ();
|
||||
|
||||
File f2 = new File ("test.img");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user