Compare commits
380 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9b77e7014 | ||
|
|
535977bff8 | ||
|
|
8b9eaec993 | ||
|
|
607784df92 | ||
|
|
db90770ec5 | ||
|
|
6de1a1242e | ||
|
|
dd0707be5f | ||
|
|
fd1a6d8003 | ||
|
|
c7119da130 | ||
|
|
3b352de1e9 | ||
|
|
83c20f02dc | ||
|
|
b1ea8a7808 | ||
|
|
3e9f8d050a | ||
|
|
4ac5e2d218 | ||
|
|
38a0966da8 | ||
|
|
0eaf06e673 | ||
|
|
f6db1ec410 | ||
|
|
9fde0fad08 | ||
|
|
54a7982dc3 | ||
|
|
adb0050d86 | ||
|
|
39a10c9fab | ||
|
|
01e717b3c1 | ||
|
|
e0c3093795 | ||
|
|
be47b66c30 | ||
|
|
0a7b734d2f | ||
|
|
e24af214fe | ||
|
|
6f6485ec34 | ||
|
|
da13c1c0e6 | ||
|
|
49b894599b | ||
|
|
c51caebea2 | ||
|
|
ebdda911b5 | ||
|
|
c655415dc0 | ||
|
|
8824089477 | ||
|
|
8af6237fd6 | ||
|
|
f49a30eba8 | ||
|
|
10df9d88ab | ||
|
|
49218ae6b4 | ||
|
|
871e1cfe3a | ||
|
|
03d052d578 | ||
|
|
6032da6681 | ||
|
|
690ff694ca | ||
|
|
486cafd4ac | ||
|
|
87e03fd48e | ||
|
|
b5f9079302 | ||
|
|
2ac869bcc8 | ||
|
|
6067e1540f | ||
|
|
37aba887d7 | ||
|
|
76044a5c00 | ||
|
|
9a5f784d51 | ||
|
|
ad5b5f96da | ||
|
|
be1419a442 | ||
|
|
1fcec724aa | ||
|
|
1edf00d3bd | ||
|
|
d24e088dc3 | ||
|
|
cd077b8229 | ||
|
|
c649817586 | ||
|
|
498758faee | ||
|
|
5d93d70b4d | ||
|
|
72f5487be2 | ||
|
|
c09db4e834 | ||
|
|
f5a49bf1ca | ||
|
|
a0a8de4253 | ||
|
|
7123f0cab1 | ||
|
|
3c9dfd1e95 | ||
|
|
0ef30bbb31 | ||
|
|
ae45cee728 | ||
|
|
54e91da925 | ||
|
|
19e2f5aa4f | ||
|
|
31fba8d803 | ||
|
|
98edfac1ee | ||
|
|
7d3848ddc0 | ||
|
|
41a7a68cf3 | ||
|
|
2353b9d3b8 | ||
|
|
43942b08cf | ||
|
|
2972987d02 | ||
|
|
6c5f7c954c | ||
|
|
f499d7d425 | ||
|
|
e18058a5a5 | ||
|
|
7f14c042eb | ||
|
|
c48226a502 | ||
|
|
6533491b17 | ||
|
|
615924abaa | ||
|
|
cd1322e30d | ||
|
|
fcb975a642 | ||
|
|
b7addee24d | ||
|
|
e72c200e4c | ||
|
|
922c3623c6 | ||
|
|
655f8037de | ||
|
|
1970a14178 | ||
|
|
1a35ca5908 | ||
|
|
f23352aefd | ||
|
|
ce331df0f1 | ||
|
|
ece902712b | ||
|
|
e7e3a32edc | ||
|
|
00c9755ee3 | ||
|
|
eb7ec6170e | ||
|
|
efef3e3c12 | ||
|
|
27d00960c9 | ||
|
|
cee513112a | ||
|
|
14b1e7b963 | ||
|
|
7708d3e04f | ||
|
|
082a55f76c | ||
|
|
6bd0eec12f | ||
|
|
bcd2dba76e | ||
|
|
e1f395defc | ||
|
|
d81c0829ea | ||
|
|
aa4eb4cd10 | ||
|
|
6ccae55ddc | ||
|
|
c5dbb1e63a | ||
|
|
35c8e4fa7f | ||
|
|
7c89d9ef6b | ||
|
|
f5bfc68fdb | ||
|
|
450134501c | ||
|
|
425374ddc8 | ||
|
|
56c151fe8c | ||
|
|
b5b4816ab0 | ||
|
|
56b3b40603 | ||
|
|
be7cb78906 | ||
|
|
3bbcbd5eea | ||
|
|
2d5841133a | ||
|
|
c55bad93fb | ||
|
|
dd76ce2b4c | ||
|
|
bfc0a5f58d | ||
|
|
cd3d28491d | ||
|
|
c4381dba73 | ||
|
|
7b192f5a67 | ||
|
|
cbd1c45d95 | ||
|
|
182c25b2a4 | ||
|
|
373dca7d12 | ||
|
|
011a248381 | ||
|
|
454a08380d | ||
|
|
c8cb3d27b6 | ||
|
|
34c0542189 | ||
|
|
d3458d7bc4 | ||
|
|
252ad4aa41 | ||
|
|
065b6b5798 | ||
|
|
9b102aae65 | ||
|
|
99ec97dcdf | ||
|
|
7b3137e664 | ||
|
|
ce6c4eeabe | ||
|
|
b83b705959 | ||
|
|
342b4a55d0 | ||
|
|
0cdd944474 | ||
|
|
a7740cb19a | ||
|
|
6f39cfaeac | ||
|
|
7828f4dfe3 | ||
|
|
8bc6e9d6a8 | ||
|
|
a3b2429681 | ||
|
|
3e9f4af1e1 | ||
|
|
c4bd6bba8d | ||
|
|
0c99bb06f4 | ||
|
|
730fb50780 | ||
|
|
a0509ff071 | ||
|
|
ddb3fac1bf | ||
|
|
b051fffc6f | ||
|
|
00a0fab50b | ||
|
|
c11a92751e | ||
|
|
47963bc9cc | ||
|
|
5d48250224 | ||
|
|
6e6b3ff35f | ||
|
|
c81a16a4e2 | ||
|
|
9ba779ea36 | ||
|
|
5f0b75f040 | ||
|
|
edd502543a | ||
|
|
1ecc6b1493 | ||
|
|
29172e7c48 | ||
|
|
af2b0378bb | ||
|
|
271f8e4b70 | ||
|
|
145ed04e41 | ||
|
|
22c72b911e | ||
|
|
04ea1375c5 | ||
|
|
9c299b64bb | ||
|
|
6011b1f803 | ||
|
|
f93e8dbb78 | ||
|
|
22998927f9 | ||
|
|
d1ee71782a | ||
|
|
ffbafadcb8 | ||
|
|
6389826810 | ||
|
|
31e5539a14 | ||
|
|
2116f79cbc | ||
|
|
e2249b7ce1 | ||
|
|
25454b8308 | ||
|
|
646142f513 | ||
|
|
b4791fd404 | ||
|
|
acd06dbe32 | ||
|
|
fdcd33a155 | ||
|
|
fc821f9789 | ||
|
|
4ac261b3ee | ||
|
|
0257e27e17 | ||
|
|
b4da051d54 | ||
|
|
4e3a1205eb | ||
|
|
6f84ef6768 | ||
|
|
365885dab2 | ||
|
|
477c437ba0 | ||
|
|
908fd031d3 | ||
|
|
6edd6cdeba | ||
|
|
7b44f7b3df | ||
|
|
2749d6edfb | ||
|
|
46e08a159a | ||
|
|
d9c4b702e7 | ||
|
|
e077743442 | ||
|
|
a08bfe2896 | ||
|
|
7fef001bd9 | ||
|
|
19005b2cfc | ||
|
|
b0eabcca60 | ||
|
|
bf7f3170ea | ||
|
|
b893294dcc | ||
|
|
163f7df845 | ||
|
|
62909197d1 | ||
|
|
ced99cf69e | ||
|
|
d64fca7b84 | ||
|
|
178a6d78a8 | ||
|
|
119e67a92e | ||
|
|
f4b3351692 | ||
|
|
f223dfa29a | ||
|
|
663b99950d | ||
|
|
51672634fd | ||
|
|
47412f137f | ||
|
|
1e891d9007 | ||
|
|
639232f2b0 | ||
|
|
3814680423 | ||
|
|
35900223df | ||
|
|
21a4cf7ef5 | ||
|
|
e192035bbd | ||
|
|
c214cdc54e | ||
|
|
e7ea6d06ab | ||
|
|
aa67ea2b9b | ||
|
|
025dba7f80 | ||
|
|
31bf0cf313 | ||
|
|
0c06d740b7 | ||
|
|
527079aa0d | ||
|
|
f5172902bc | ||
|
|
9a6e5369b2 | ||
|
|
b148df4df9 | ||
|
|
fef0ff3d86 | ||
|
|
2910413850 | ||
|
|
37cdd39ada | ||
|
|
5d8e4102b4 | ||
|
|
9f19895604 | ||
|
|
040b6cb061 | ||
|
|
41260de67f | ||
|
|
f354f9b4fd | ||
|
|
c46bedf925 | ||
|
|
6aa3ece129 | ||
|
|
f5c9f0e9ee | ||
|
|
a1df33eac2 | ||
|
|
1f615fddaf | ||
|
|
f1041e912b | ||
|
|
472f02d08b | ||
|
|
138e118d62 | ||
|
|
2f6ec8b4da | ||
|
|
6d7d645cdd | ||
|
|
b288a1b971 | ||
|
|
cf4cc11433 | ||
|
|
8cf06ddcdd | ||
|
|
af0c123be8 | ||
|
|
db499d98e7 | ||
|
|
bd1cc12731 | ||
|
|
8b2ebe07c2 | ||
|
|
782a2e0299 | ||
|
|
91730ce7fa | ||
|
|
f25d2300ce | ||
|
|
8f6eed00da | ||
|
|
05a8359c7c | ||
|
|
15d79b5ea9 | ||
|
|
5332515db3 | ||
|
|
1d0683964f | ||
|
|
7d4a99db87 | ||
|
|
787baf1bad | ||
|
|
c019d073a4 | ||
|
|
05c26a9c09 | ||
|
|
248465a620 | ||
|
|
42f3abe42d | ||
|
|
dd73c50dc5 | ||
|
|
9e382f1ae3 | ||
|
|
189c3d6ac1 | ||
|
|
17b26be232 | ||
|
|
11be7d8eee | ||
|
|
baa1618e0f | ||
|
|
049116e181 | ||
|
|
e57c3c37a8 | ||
|
|
f6db819081 | ||
|
|
2135ec267e | ||
|
|
a78a3dea88 | ||
|
|
0beebeb622 | ||
|
|
fe31f1897b | ||
|
|
92dc3748b6 | ||
|
|
e6ed656c98 | ||
|
|
c155330f04 | ||
|
|
d6622d7636 | ||
|
|
c49819f9b3 | ||
|
|
1e35941f62 | ||
|
|
3a54666365 | ||
|
|
df711241ff | ||
|
|
c6be95453d | ||
|
|
ffe0e11b4d | ||
|
|
8daa036857 | ||
|
|
74e4e86309 | ||
|
|
36d8bbb858 | ||
|
|
e59e35708b | ||
|
|
b4bb49ffd1 | ||
|
|
f3341222b3 | ||
|
|
ca8c2b5996 | ||
|
|
b0605f265b | ||
|
|
b3f61a9db3 | ||
|
|
4abb239dcc | ||
|
|
fac15924f5 | ||
|
|
293772bf75 | ||
|
|
b39b3c5c74 | ||
|
|
b57fcc5064 | ||
|
|
2628fa96d8 | ||
|
|
b1f7b5f911 | ||
|
|
5c2f1a2d94 | ||
|
|
4e9ed01847 | ||
|
|
d020350c31 | ||
|
|
04fbcc63eb | ||
|
|
8403f5a9d8 | ||
|
|
ffc01285ee | ||
|
|
322106521f | ||
|
|
3c7b3634b2 | ||
|
|
67030c6ef2 | ||
|
|
aa88c1bbd2 | ||
|
|
fa13b2838f | ||
|
|
8324d2fcf0 | ||
|
|
79e66f89e2 | ||
|
|
660daf31e2 | ||
|
|
84763d7fca | ||
|
|
917f947590 | ||
|
|
b648b1813f | ||
|
|
99624d2922 | ||
|
|
8d8ace19da | ||
|
|
bddde7799b | ||
|
|
cda7fa973c | ||
|
|
912284b02e | ||
|
|
95136b1492 | ||
|
|
c7b88da039 | ||
|
|
7c521c7211 | ||
|
|
cbef2ffb04 | ||
|
|
b3f1457fdd | ||
|
|
504b9d95c4 | ||
|
|
8ab2b85b2a | ||
|
|
8928de32d3 | ||
|
|
73be6db9bf | ||
|
|
5b012024c4 | ||
|
|
eb209a3664 | ||
|
|
085a566906 | ||
|
|
baefb8225c | ||
|
|
f0f3e16211 | ||
|
|
69abc787dd | ||
|
|
ceb3a57f67 | ||
|
|
09a7545649 | ||
|
|
75005e48bb | ||
|
|
2faef37957 | ||
|
|
9420eaf44e | ||
|
|
6146412f06 | ||
|
|
0bd055316f | ||
|
|
d64ad1a403 | ||
|
|
1a4f1df77e | ||
|
|
675f336319 | ||
|
|
0cd5b9ac15 | ||
|
|
54911bdd32 | ||
|
|
d36504e1bb | ||
|
|
4e196ad9a3 | ||
|
|
4fb3b23fb6 | ||
|
|
ce18be33cd | ||
|
|
a31ac8fc32 | ||
|
|
c38cb92ec4 | ||
|
|
b2edcbe1b9 | ||
|
|
631faad971 | ||
|
|
f159619113 | ||
|
|
a24652c7b2 | ||
|
|
2ace9be4cd | ||
|
|
08e77ad8cb | ||
|
|
fa44536b0f | ||
|
|
00fef9eed6 | ||
|
|
9bab154d48 | ||
|
|
4c76aaa391 | ||
|
|
ca727deac1 | ||
|
|
6375aede61 | ||
|
|
a4db75521d |
194
.gitignore
vendored
@@ -2,6 +2,9 @@
|
||||
*.a
|
||||
ABOUT-NLS
|
||||
aclocal.m4
|
||||
align/stamp-virt-alignment-scan.pod
|
||||
align/virt-alignment-scan
|
||||
align/virt-alignment-scan.1
|
||||
appliance/excludelist
|
||||
appliance/make.sh
|
||||
appliance/packagelist
|
||||
@@ -10,21 +13,7 @@ appliance/supermin.d
|
||||
autom4te.cache
|
||||
*.bak
|
||||
bindtests.tmp
|
||||
capitests/test.log
|
||||
capitests/test-add-drive-opts
|
||||
capitests/test-add-libvirt-dom
|
||||
capitests/test-command
|
||||
capitests/test-config
|
||||
capitests/test-create-handle
|
||||
capitests/test-debug-to-file
|
||||
capitests/test-just-header
|
||||
capitests/test-last-errno
|
||||
capitests/test-private-data
|
||||
capitests/test-user-cancel
|
||||
capitests/test*.img
|
||||
capitests/tests
|
||||
capitests/tests.c
|
||||
capitests/test*.tmp
|
||||
/build-aux
|
||||
cat/stamp-virt-*.pod
|
||||
cat/virt-cat
|
||||
cat/virt-cat.1
|
||||
@@ -34,6 +23,9 @@ cat/virt-ls
|
||||
cat/virt-ls.1
|
||||
ChangeLog
|
||||
*.class
|
||||
clone/stamp-virt-sysprep.pod
|
||||
clone/virt-sysprep
|
||||
clone/virt-sysprep.1
|
||||
*.cma
|
||||
*.cmi
|
||||
*.cmo
|
||||
@@ -50,9 +42,9 @@ configure
|
||||
cscope.out
|
||||
csharp/Libguestfs.cs
|
||||
daemon/actions.h
|
||||
daemon/errnostring.c
|
||||
daemon/errnostring_gperf.c
|
||||
daemon/errnostring_gperf.gperf
|
||||
daemon/errnostring.c
|
||||
daemon/errnostring.h
|
||||
daemon/guestfsd
|
||||
daemon/guestfsd.exe
|
||||
@@ -69,21 +61,32 @@ depcomp
|
||||
df/stamp-virt-df.pod
|
||||
df/virt-df
|
||||
df/virt-df.1
|
||||
*.diff
|
||||
edit/stamp-virt-*.pod
|
||||
edit/virt-edit
|
||||
edit/virt-edit.1
|
||||
*.eml
|
||||
emptydisk
|
||||
erlang/erl-guestfs
|
||||
erlang/erl-guestfs.c
|
||||
erlang/examples/guestfs-erlang.3
|
||||
erlang/examples/stamp-guestfs-erlang.pod
|
||||
erlang/guestfs.beam
|
||||
erlang/guestfs.erl
|
||||
examples/create_disk
|
||||
examples/guestfs-examples.3
|
||||
examples/guestfs-recipes.1
|
||||
examples/guestfs-testing.1
|
||||
examples/inspect_vm
|
||||
examples/stamp-guestfs-examples.pod
|
||||
examples/stamp-guestfs-recipes.pod
|
||||
examples/stamp-guestfs-testing.pod
|
||||
examples/virt-dhcp-address
|
||||
fish/cmds.c
|
||||
fish/cmds_gperf.c
|
||||
fish/cmds_gperf.gperf
|
||||
fish/completion.c
|
||||
fish/event-names.c
|
||||
fish/fish-cmds.h
|
||||
fish/guestfish
|
||||
fish/guestfish.1
|
||||
@@ -102,13 +105,23 @@ fish/virt-copy-in.1
|
||||
fish/virt-copy-out.1
|
||||
fish/virt-tar-in.1
|
||||
fish/virt-tar-out.1
|
||||
format/stamp-virt-format.pod
|
||||
format/virt-format
|
||||
format/virt-format.1
|
||||
fuse/guestmount
|
||||
fuse/guestmount.1
|
||||
fuse/stamp-guestmount.pod
|
||||
generator/.pod2text.data*
|
||||
generator/.depend
|
||||
generator/files-generated.txt
|
||||
generator/generator
|
||||
generator/.pod2text.data*
|
||||
generator/stamp-generator
|
||||
.gitattributes
|
||||
.git-module-status
|
||||
/gnulib
|
||||
/GNUmakefile
|
||||
.guestfs-*
|
||||
guestfs.*
|
||||
guestfsd-in-wine.log
|
||||
haskell/Bindtests
|
||||
haskell/Bindtests.hs
|
||||
@@ -118,6 +131,7 @@ haskell/Guestfs.hs
|
||||
*.hi
|
||||
html/guestfish.1.html
|
||||
html/guestfs.3.html
|
||||
html/guestfs-erlang.3.html
|
||||
html/guestfs-examples.3.html
|
||||
html/guestfs-java.3.html
|
||||
html/guestfs-ocaml.3.html
|
||||
@@ -125,13 +139,16 @@ html/guestfs-perl.3.html
|
||||
html/guestfs-python.3.html
|
||||
html/guestfs-recipes.1.html
|
||||
html/guestfs-ruby.3.html
|
||||
html/guestfs-testing.1.html
|
||||
html/guestmount.1.html
|
||||
html/virt-alignment-scan.1.html
|
||||
html/virt-cat.1.html
|
||||
html/virt-copy-in.1.html
|
||||
html/virt-copy-out.1.html
|
||||
html/virt-df.1.html
|
||||
html/virt-edit.1.html
|
||||
html/virt-filesystems.1.html
|
||||
html/virt-format.1.html
|
||||
html/virt-inspector.1.html
|
||||
html/virt-list-filesystems.1.html
|
||||
html/virt-list-partitions.1.html
|
||||
@@ -139,28 +156,12 @@ html/virt-ls.1.html
|
||||
html/virt-make-fs.1.html
|
||||
html/virt-rescue.1.html
|
||||
html/virt-resize.1.html
|
||||
html/virt-sparsify.1.html
|
||||
html/virt-sysprep.1.html
|
||||
html/virt-tar.1.html
|
||||
html/virt-tar-in.1.html
|
||||
html/virt-tar-out.1.html
|
||||
html/virt-win-reg.1.html
|
||||
images/100kallnewlines
|
||||
images/100kallspaces
|
||||
images/100kallzeroes
|
||||
images/100krandom
|
||||
images/10klines
|
||||
images/abssymlink
|
||||
images/debian.img
|
||||
images/fedora.img
|
||||
images/guest-aux/fedora-name.db
|
||||
images/guest-aux/fedora-packages.db
|
||||
images/hello.b64
|
||||
images/initrd
|
||||
images/initrd-x86_64.img
|
||||
images/initrd-x86_64.img.gz
|
||||
images/test.iso
|
||||
images/test-grep.txt.gz
|
||||
images/ubuntu.img
|
||||
images/windows.img
|
||||
inspector/stamp-virt-inspector.pod
|
||||
inspector/virt-inspector
|
||||
inspector/virt-inspector.1
|
||||
@@ -202,13 +203,14 @@ m4/lt~obsolete.m4
|
||||
m4/ltoptions.m4
|
||||
m4/ltsugar.m4
|
||||
m4/ltversion.m4
|
||||
/maint.mk
|
||||
Makefile
|
||||
Makefile.in
|
||||
missing
|
||||
*.o
|
||||
ocamlinit-stamp
|
||||
ocaml/bindtests
|
||||
ocaml/bindtests.ml
|
||||
ocaml/.depend
|
||||
ocaml/dllmlguestfs.so
|
||||
ocaml/examples/create_disk
|
||||
ocaml/examples/guestfs-ocaml.3
|
||||
@@ -219,6 +221,7 @@ ocaml/guestfs_inspector.ml
|
||||
ocaml/guestfs_inspector.mli
|
||||
ocaml/guestfs.ml
|
||||
ocaml/guestfs.mli
|
||||
ocamlinit-stamp
|
||||
ocaml/META
|
||||
ocaml/t/guestfs_005_load
|
||||
ocaml/t/guestfs_010_basic
|
||||
@@ -226,22 +229,21 @@ ocaml/t/guestfs_070_threads
|
||||
ocaml/t/guestfs_080_optargs
|
||||
ocaml/t/guestfs_400_events
|
||||
ocaml/t/guestfs_400_progress
|
||||
*.orig
|
||||
*.patch
|
||||
perl/bindtests.pl
|
||||
perl/blib
|
||||
perl/examples/guestfs-perl.3
|
||||
perl/examples/stamp-guestfs-perl.pod
|
||||
perl/Guestfs.bs
|
||||
perl/Guestfs.c
|
||||
perl/Guestfs.xs
|
||||
perl/examples/guestfs-perl.3
|
||||
perl/examples/stamp-guestfs-perl.pod
|
||||
perl/lib/Sys/Guestfs.pm
|
||||
perl/Makefile-pl
|
||||
perl/Makefile-pl.old
|
||||
perl/Makefile.PL
|
||||
perl/Makefile-pl.old
|
||||
perl/MYMETA.yml
|
||||
perl/pm_to_blib
|
||||
php/extension/Makefile.fragments
|
||||
php/extension/Makefile.global
|
||||
php/extension/Makefile.objects
|
||||
php/extension/acinclude.m4
|
||||
php/extension/build/
|
||||
php/extension/config.nice
|
||||
@@ -253,47 +255,49 @@ php/extension/guestfs_php_*.log
|
||||
php/extension/guestfs_php_*.out
|
||||
php/extension/guestfs_php_*.php
|
||||
php/extension/guestfs_php_*.sh
|
||||
php/extension/Makefile.fragments
|
||||
php/extension/Makefile.global
|
||||
php/extension/Makefile.objects
|
||||
php/extension/mkinstalldirs
|
||||
php/extension/modules/
|
||||
php/extension/php_guestfs_php.h
|
||||
php/extension/run-tests.php
|
||||
php/extension/tmp-php.ini
|
||||
pod2htm?.tmp
|
||||
po/*.gmo
|
||||
po/Makevars.template
|
||||
po/POTFILES
|
||||
po/remove-potcdate.sed
|
||||
po/stamp-it
|
||||
po/stamp-po
|
||||
po/LINGUAS
|
||||
po/Rules-quot
|
||||
po/boldquot.sed
|
||||
po/en@boldquot.header
|
||||
po/en@quot.header
|
||||
po/insert-header.sin
|
||||
po/quot.sed
|
||||
po/remove-potcdate.sin
|
||||
po-docs/po4a.conf
|
||||
po-docs/*/*.pl
|
||||
po-docs/*/*.pod
|
||||
pod2htm?.tmp
|
||||
po-docs/*/*.1
|
||||
po-docs/*/*.3
|
||||
po-docs/*/*.pl
|
||||
po-docs/po4a.conf
|
||||
po-docs/*/*.pod
|
||||
podwrapper.sh
|
||||
po/en@boldquot.header
|
||||
po/en@quot.header
|
||||
po/*.gmo
|
||||
po/insert-header.sin
|
||||
po/LINGUAS
|
||||
po/Makevars.template
|
||||
po/POTFILES
|
||||
po/quot.sed
|
||||
po/remove-potcdate.sed
|
||||
po/remove-potcdate.sin
|
||||
po/Rules-quot
|
||||
po/stamp-it
|
||||
po/stamp-po
|
||||
python/bindtests.py
|
||||
python/examples/guestfs-python.3
|
||||
python/examples/stamp-guestfs-python.pod
|
||||
python/guestfs.py
|
||||
python/guestfs-py.c
|
||||
python/guestfs.pyc
|
||||
regressions/rhbz501893
|
||||
regressions/test1.img
|
||||
regressions/test2.img
|
||||
regressions/test.err
|
||||
regressions/test.out
|
||||
python/__pycache__
|
||||
*.rej
|
||||
rescue/stamp-virt-rescue.pod
|
||||
rescue/virt-rescue
|
||||
rescue/virt-rescue.1
|
||||
resize/.depend
|
||||
resize/stamp-virt-resize.pod
|
||||
resize/utils_tests
|
||||
resize/virt-resize
|
||||
resize/virt-resize.1
|
||||
ruby/bindtests.rb
|
||||
@@ -307,36 +311,74 @@ ruby/ext/guestfs/_guestfs.so
|
||||
ruby/ext/guestfs/mkmf.log
|
||||
ruby/Rakefile
|
||||
run
|
||||
sparsify/.depend
|
||||
sparsify/stamp-virt-sparsify.pod
|
||||
sparsify/virt-sparsify
|
||||
sparsify/virt-sparsify.1
|
||||
src/actions.c
|
||||
src/bindtests.c
|
||||
src/errnostring.c
|
||||
src/errnostring_gperf.c
|
||||
src/errnostring_gperf.gperf
|
||||
src/errnostring.c
|
||||
src/errnostring.h
|
||||
src/guestfs.3
|
||||
src/guestfs-actions.pod
|
||||
src/guestfs-availability.pod
|
||||
src/guestfs.h
|
||||
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/.libs/libguestfs.so
|
||||
src/stamp-guestfs.pod
|
||||
*.swp
|
||||
stamp-h1
|
||||
*.swp
|
||||
test1.img
|
||||
test2.img
|
||||
test.err
|
||||
test.out
|
||||
tests/c-api/test-add-drive-opts
|
||||
tests/c-api/test-add-libvirt-dom
|
||||
tests/c-api/test-command
|
||||
tests/c-api/test-config
|
||||
tests/c-api/test-create-handle
|
||||
tests/c-api/test-debug-to-file
|
||||
tests/c-api/test*.img
|
||||
tests/c-api/test-just-header
|
||||
tests/c-api/test-last-errno
|
||||
tests/c-api/test.log
|
||||
tests/c-api/test-private-data
|
||||
tests/c-api/tests
|
||||
tests/c-api/tests.c
|
||||
tests/c-api/test*.tmp
|
||||
tests/c-api/test-user-cancel
|
||||
tests/data/100kallnewlines
|
||||
tests/data/100kallspaces
|
||||
tests/data/100kallzeroes
|
||||
tests/data/100krandom
|
||||
tests/data/10klines
|
||||
tests/data/abssymlink
|
||||
tests/data/hello.b64
|
||||
tests/data/initrd
|
||||
tests/data/initrd-x86_64.img
|
||||
tests/data/initrd-x86_64.img.gz
|
||||
tests/data/test-grep.txt.gz
|
||||
tests/data/test.iso
|
||||
tests/extra/valgrind.log
|
||||
tests/guests/debian.img
|
||||
tests/guests/fedora.img
|
||||
tests/guests/fedora-md1.img
|
||||
tests/guests/fedora-md2.img
|
||||
tests/guests/guest-aux/fedora-name.db
|
||||
tests/guests/guest-aux/fedora-packages.db
|
||||
tests/guests/ubuntu.img
|
||||
tests/guests/windows.img
|
||||
tests/regressions/rhbz501893
|
||||
test-tool/libguestfs-test-tool
|
||||
test-tool/libguestfs-test-tool.1
|
||||
test-tool/libguestfs-test-tool-helper
|
||||
tools/test.img
|
||||
tools/virt-*.1
|
||||
tools/virt-*.pl
|
||||
/GNUmakefile
|
||||
/maint.mk
|
||||
/build-aux
|
||||
/gnulib
|
||||
.git-module-status
|
||||
.guestfs-*
|
||||
|
||||
2
.gnulib
9
.lvimrc
Normal file
@@ -0,0 +1,9 @@
|
||||
" Custom libguestfs indentation configuration for vim
|
||||
"
|
||||
" This configuration file requires localrc.vim to be installed. You can obtain
|
||||
" localrc.vim from http://www.vim.org/scripts/script.php?script_id=1408
|
||||
|
||||
set sw=2
|
||||
set ts=2
|
||||
set tw=80
|
||||
set expandtab
|
||||
@@ -1,5 +1,5 @@
|
||||
^appliance/debian/modules/
|
||||
^images/
|
||||
^tests/data/
|
||||
^COPYING(.LIB)?$
|
||||
^\.gitmodules$
|
||||
(^|\/)ChangeLog[^/]*$
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
images/bin-win64.exe
|
||||
tests/data/bin-win64.exe
|
||||
*.pod
|
||||
|
||||
45
AUTHORS
@@ -1,21 +1,24 @@
|
||||
Angus Salkeld
|
||||
Ani Peter
|
||||
Charles Duffy
|
||||
Daniel Berrange
|
||||
Daniel Cabrera
|
||||
Douglas Schilling Landgraf
|
||||
Geert Warrink
|
||||
Guido Günther
|
||||
Hilko Bengen
|
||||
Jaswinder Singh
|
||||
Jim Meyering
|
||||
Karel Klíč
|
||||
Matthew Booth
|
||||
Maxim Koltsov
|
||||
Nikita A Menkovich
|
||||
Piotr Drąg
|
||||
Rajesh Ranjan
|
||||
Richard W.M. Jones
|
||||
Sandeep Shedmake
|
||||
Shankar Prasad
|
||||
Thomas S Hatch
|
||||
Angus Salkeld <asalkeld@redhat.com>
|
||||
Ani Peter <apeter@redhat.com>
|
||||
Charles Duffy <cduffy@messageone.com>
|
||||
Daniel Berrange <berrange@redhat.com>
|
||||
Daniel Cabrera <logan@fedoraproject.org>
|
||||
Douglas Schilling Landgraf <dougsland@redhat.com>
|
||||
Erik Nolte <erik_nolte@acm.org>
|
||||
Geert Warrink <geert.warrink@onsnet.nu>
|
||||
Guido Günther <agx@sigxcpu.org>
|
||||
Hilko Bengen <bengen@hilluzination.de>
|
||||
Jaswinder Singh <jsingh@redhat.com>
|
||||
Jim Meyering <jim@meyering.net>
|
||||
Karel Klíč <kklic@redhat.com>
|
||||
Matthew Booth <mbooth@redhat.com>
|
||||
Maxim Koltsov <kolmax94@gmail.com>
|
||||
Michael Scherer <misc@zarb.org>
|
||||
Nikita A Menkovich <menkovich@gmail.com>
|
||||
Piotr Drąg <piotrdrag@gmail.com>
|
||||
Rajesh Ranjan <rranjan@redhat.com>
|
||||
Richard W.M. Jones <rich@annexia.org>
|
||||
Sandeep Shedmake <sshedmak@redhat.com>
|
||||
Shankar Prasad <svenkate@redhat.com>
|
||||
Thomas S Hatch <thatch45@gmail.com>
|
||||
Wanlong Gao <gaowanlong@cn.fujitsu.com>
|
||||
|
||||
128
BUGS
@@ -1,5 +1,5 @@
|
||||
NOTE: This file is automatically generated from "update-bugs.sh".
|
||||
Last updated: 2011-08-18
|
||||
Last updated: 2012-01-18
|
||||
|
||||
This contains a local list of the bugs that are open against
|
||||
libguestfs. Bugs are tracked in the Red Hat Bugzilla database
|
||||
@@ -32,9 +32,6 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
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"
|
||||
|
||||
@@ -44,24 +41,51 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
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
|
||||
|
||||
727247 NEW https://bugzilla.redhat.com/show_bug.cgi?id=727247
|
||||
should not depend on MAKEDEV
|
||||
|
||||
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
|
||||
libguestfs grub-install API needs grub1
|
||||
|
||||
745576 NEW https://bugzilla.redhat.com/show_bug.cgi?id=745576
|
||||
libguestfs (or qemu?) hangs if sparse file runs out of disk space
|
||||
|
||||
745606 NEW https://bugzilla.redhat.com/show_bug.cgi?id=745606
|
||||
libguestfs: error: part_list: could not parse row from output of parted print command
|
||||
|
||||
760221 NEW https://bugzilla.redhat.com/show_bug.cgi?id=760221
|
||||
RFE: Support inspection of cciss devices
|
||||
|
||||
761565 NEW https://bugzilla.redhat.com/show_bug.cgi?id=761565
|
||||
Missing deps on netpbm-progs and icoutils
|
||||
|
||||
767852 NEW https://bugzilla.redhat.com/show_bug.cgi?id=767852
|
||||
dependency on fuse suggested
|
||||
|
||||
769304 NEW https://bugzilla.redhat.com/show_bug.cgi?id=769304
|
||||
virt-resize on RHEL 6 kernel fails to re-read the partition table
|
||||
|
||||
769359 NEW https://bugzilla.redhat.com/show_bug.cgi?id=769359
|
||||
virt-resize on RHEL 6 kernel fails to re-read the partition table
|
||||
|
||||
770075 NEW https://bugzilla.redhat.com/show_bug.cgi?id=770075
|
||||
FEBOOTSTRAP_MODULES fails if modules directory is not under /lib
|
||||
|
||||
770076 NEW https://bugzilla.redhat.com/show_bug.cgi?id=770076
|
||||
FEBOOTSTRAP_KERNEL causes appliance build to fail
|
||||
|
||||
782167 NEW https://bugzilla.redhat.com/show_bug.cgi?id=782167
|
||||
libguestfs doesn't recognize Windows Dynamic disks in some configurations, eg. spanned
|
||||
|
||||
782845 NEW https://bugzilla.redhat.com/show_bug.cgi?id=782845
|
||||
CloudForms CloudEngine missing dependency: imagefactory (and oz) require python-libguestfs
|
||||
|
||||
563450 NEW https://bugzilla.redhat.com/show_bug.cgi?id=563450
|
||||
list-devices returns devices of different types out of order
|
||||
|
||||
@@ -75,7 +99,10 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
[RFE] virt-edit/tar/inspector do not support encrypted system
|
||||
|
||||
679737 NEW https://bugzilla.redhat.com/show_bug.cgi?id=679737
|
||||
zerofree is unavailable
|
||||
libguestfs: improve error message when zerofree is not available in the appliance
|
||||
|
||||
745282 NEW https://bugzilla.redhat.com/show_bug.cgi?id=745282
|
||||
[RFE] Support to use virt-filesystems with remote libvirt systems
|
||||
|
||||
507278 NEW https://bugzilla.redhat.com/show_bug.cgi?id=507278
|
||||
libguestfs fails to build on Fedora sparc64
|
||||
@@ -101,9 +128,6 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
596354 NEW https://bugzilla.redhat.com/show_bug.cgi?id=596354
|
||||
guestfish.1.html and guestfs.3.html declared "XHTML 1.0 Strict" but are not in fact well-formed XML
|
||||
|
||||
596761 NEW https://bugzilla.redhat.com/show_bug.cgi?id=596761
|
||||
Ctrl- causes guestfish to abort
|
||||
|
||||
604041 NEW https://bugzilla.redhat.com/show_bug.cgi?id=604041
|
||||
guestmount absolute symlinks don't work
|
||||
|
||||
@@ -116,27 +140,18 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
627675 NEW https://bugzilla.redhat.com/show_bug.cgi?id=627675
|
||||
libguestfs inspector code cannot handle /dev/disk/by-id/* paths
|
||||
|
||||
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
|
||||
|
||||
635971 NEW https://bugzilla.redhat.com/show_bug.cgi?id=635971
|
||||
glob mkfs ext2 /dev/vd[b-t]1 does not expand
|
||||
|
||||
637251 NEW https://bugzilla.redhat.com/show_bug.cgi?id=637251
|
||||
virt-inspector fails to recognize data-only NTFS disk image
|
||||
|
||||
642821 NEW https://bugzilla.redhat.com/show_bug.cgi?id=642821
|
||||
virt-resize falls over on a disk image with a logical swap partition
|
||||
|
||||
646036 NEW https://bugzilla.redhat.com/show_bug.cgi?id=646036
|
||||
libguestfs fails to launch
|
||||
|
||||
660687 NEW https://bugzilla.redhat.com/show_bug.cgi?id=660687
|
||||
guestmount: "touch" command fails: touch: setting times of `timestamp': Invalid argument
|
||||
|
||||
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
|
||||
|
||||
@@ -146,6 +161,9 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
700342 NEW https://bugzilla.redhat.com/show_bug.cgi?id=700342
|
||||
virt-inspector resports unknown filesystem UUID
|
||||
|
||||
741183 NEW https://bugzilla.redhat.com/show_bug.cgi?id=741183
|
||||
[RFE] Write a tool to align the partition(s) in a Windows XP image to a multiple of 8 sectors
|
||||
|
||||
713678 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=713678
|
||||
Not all febootstrap messages are redirected to log callbacks
|
||||
|
||||
@@ -155,6 +173,9 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
583974 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=583974
|
||||
mount hangs there when you lack proper permission to guest image
|
||||
|
||||
647174 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=647174
|
||||
RHEL6: virt-clone should remove old udev rules when changing MAC address
|
||||
|
||||
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
|
||||
|
||||
@@ -174,58 +195,13 @@ You can help by testing the fixes.
|
||||
691389 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=691389
|
||||
Extended attributes don't work over guestmount (FUSE)
|
||||
|
||||
750889 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=750889
|
||||
Python code incompatible with Python v3.
|
||||
|
||||
657499 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=657499
|
||||
checksum: wrong check sum type causes umount to fail
|
||||
|
||||
684980 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=684980
|
||||
calling guestfs_kill_subprocess() then guestfs_close() causes a lockup in some applications
|
||||
|
||||
627835 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=627835
|
||||
libguestfs protocol loses synchronization if you 'upload' before mounting disks
|
||||
|
||||
729887 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=729887
|
||||
appliance crashes running aug_init with flags=4
|
||||
|
||||
678231 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=678231
|
||||
virt-inspector reports unknown filesystem UUID
|
||||
|
||||
603000 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=603000
|
||||
part-get-bootable gives wrong result with an unordered part layout
|
||||
|
||||
666578 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=666578
|
||||
libguestfs: unknown filesystem label SWAP-sda2
|
||||
|
||||
682980 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=682980
|
||||
libguestfs incorrectly detects Red Hat desktop as 'redhat-based' instead of 'redhat'
|
||||
|
||||
688062 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=688062
|
||||
fish: add luks-open mapped device to tab completion list
|
||||
|
||||
730248 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=730248
|
||||
'guestfish --remote run' hangs in a shell command substitution context
|
||||
|
||||
--------------------------------------------------
|
||||
These bugs are in the VERIFIED state.
|
||||
|
||||
672491 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=672491
|
||||
RFE: guestfs_last_errno should be exposed in perl bindings
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
749828 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=749828
|
||||
p2v does not support raid devices
|
||||
|
||||
End of BUGS file.
|
||||
|
||||
75
Makefile.am
@@ -13,14 +13,17 @@
|
||||
#
|
||||
# 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.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
include $(top_srcdir)/subdir-rules.mk
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
# Gnulib - must be built and tested before the library.
|
||||
SUBDIRS = gnulib/lib gnulib/tests
|
||||
|
||||
# Basic source for the library.
|
||||
SUBDIRS = gnulib/lib images generator src examples po
|
||||
SUBDIRS += tests/data generator src examples po
|
||||
|
||||
if ENABLE_DAEMON
|
||||
SUBDIRS += daemon
|
||||
@@ -29,14 +32,27 @@ if ENABLE_APPLIANCE
|
||||
SUBDIRS += appliance
|
||||
endif
|
||||
|
||||
# Tests and the test-tool.
|
||||
SUBDIRS += gnulib/tests capitests caution regressions test-tool
|
||||
# Tests - order is important.
|
||||
SUBDIRS += tests/qemu
|
||||
SUBDIRS += tests/guests
|
||||
SUBDIRS += tests/c-api
|
||||
SUBDIRS += tests/protocol
|
||||
SUBDIRS += tests/lvm
|
||||
SUBDIRS += tests/luks
|
||||
SUBDIRS += tests/md
|
||||
SUBDIRS += tests/regressions
|
||||
|
||||
# Extra tests don't run by default. You have to do 'make extra-tests'.
|
||||
SUBDIRS += tests/extra
|
||||
|
||||
# libguestfs-test-tool
|
||||
SUBDIRS += test-tool
|
||||
|
||||
# Guestfish.
|
||||
SUBDIRS += fish
|
||||
|
||||
# virt-tools in C.
|
||||
SUBDIRS += cat df edit inspector rescue
|
||||
SUBDIRS += align cat df edit format inspector rescue
|
||||
|
||||
# Language bindings.
|
||||
if HAVE_PERL
|
||||
@@ -60,26 +76,33 @@ endif
|
||||
if HAVE_PHP
|
||||
SUBDIRS += php
|
||||
endif
|
||||
if HAVE_ERLANG
|
||||
SUBDIRS += erlang erlang/examples
|
||||
endif
|
||||
|
||||
# Unconditional because nothing is built yet.
|
||||
SUBDIRS += csharp
|
||||
|
||||
# virt-resize 2.0 is written in OCaml.
|
||||
# virt-resize (new version) and virt-sparsify are written in OCaml.
|
||||
if HAVE_OCAML
|
||||
if HAVE_OCAML_PCRE
|
||||
SUBDIRS += resize
|
||||
endif
|
||||
SUBDIRS += resize sparsify
|
||||
endif
|
||||
|
||||
# Perl tools and guestmount.
|
||||
# Perl tools.
|
||||
if HAVE_TOOLS
|
||||
SUBDIRS += tools
|
||||
endif
|
||||
|
||||
# guestmount
|
||||
if HAVE_FUSE
|
||||
SUBDIRS += fuse
|
||||
endif
|
||||
|
||||
# virt-tools in shell. This uses guestmount and virt-inspector.
|
||||
if HAVE_FUSE
|
||||
SUBDIRS += clone
|
||||
endif
|
||||
|
||||
# po-docs must come after tools, inspector.
|
||||
if HAVE_PO4A
|
||||
SUBDIRS += po-docs
|
||||
@@ -92,7 +115,23 @@ EXTRA_DIST = \
|
||||
bugs-in-changelog.sh \
|
||||
autogen.sh \
|
||||
bindtests \
|
||||
contrib/autobuild/autobuild.sh \
|
||||
contrib/guestfsd-in-wine.sh \
|
||||
contrib/intro/libguestfs-intro.html \
|
||||
contrib/intro/overview.svg \
|
||||
contrib/intro/talk.txt \
|
||||
contrib/intro/tools.svg \
|
||||
contrib/README \
|
||||
contrib/visualize-alignment/.gitignore \
|
||||
contrib/visualize-alignment/guestfish-add-mount.qtr \
|
||||
contrib/visualize-alignment/guestfish-lv-ext4-4k.qtr \
|
||||
contrib/visualize-alignment/guestfish-lv-ext4-4k-write-hello.qtr \
|
||||
contrib/visualize-alignment/guestfish-N-fs-10M-aligned-part-disk.qtr \
|
||||
contrib/visualize-alignment/guestfish-N-fs-10M.qtr \
|
||||
contrib/visualize-alignment/guestfish-write-hello.qtr \
|
||||
contrib/visualize-alignment/qemu-0.13-trace-block-device-access.patch \
|
||||
contrib/visualize-alignment/README \
|
||||
contrib/visualize-alignment/tracetops.ml \
|
||||
debian/.gitignore \
|
||||
debian/changelog \
|
||||
debian/compat \
|
||||
@@ -131,20 +170,24 @@ EXTRA_DIST = \
|
||||
HTMLFILES = \
|
||||
html/guestfs.3.html \
|
||||
html/guestfs-examples.3.html \
|
||||
html/guestfs-erlang.3.html \
|
||||
html/guestfs-java.3.html \
|
||||
html/guestfs-ocaml.3.html \
|
||||
html/guestfs-perl.3.html \
|
||||
html/guestfs-python.3.html \
|
||||
html/guestfs-recipes.1.html \
|
||||
html/guestfs-ruby.3.html \
|
||||
html/guestfs-testing.1.html \
|
||||
html/guestfish.1.html \
|
||||
html/guestmount.1.html \
|
||||
html/virt-alignment-scan.1.html \
|
||||
html/virt-cat.1.html \
|
||||
html/virt-copy-in.1.html \
|
||||
html/virt-copy-out.1.html \
|
||||
html/virt-df.1.html \
|
||||
html/virt-edit.1.html \
|
||||
html/virt-filesystems.1.html \
|
||||
html/virt-format.1.html \
|
||||
html/virt-inspector.1.html \
|
||||
html/virt-list-filesystems.1.html \
|
||||
html/virt-list-partitions.1.html \
|
||||
@@ -152,6 +195,8 @@ HTMLFILES = \
|
||||
html/virt-make-fs.1.html \
|
||||
html/virt-rescue.1.html \
|
||||
html/virt-resize.1.html \
|
||||
html/virt-sparsify.1.html \
|
||||
html/virt-sysprep.1.html \
|
||||
html/virt-tar.1.html \
|
||||
html/virt-tar-in.1.html \
|
||||
html/virt-tar-out.1.html \
|
||||
@@ -177,7 +222,7 @@ dist-hook:
|
||||
$(top_srcdir)/update-bugs.sh > BUGS-t
|
||||
mv BUGS-t BUGS
|
||||
cp BUGS $(distdir)/BUGS
|
||||
git log --pretty="format:%an" | sort -u | \
|
||||
git log --pretty="format:%an <%ae>" | sort -u | uniq -w 10 | \
|
||||
grep -v rjones | \
|
||||
grep -v "Richard Jones" \
|
||||
> AUTHORS-t
|
||||
@@ -190,7 +235,7 @@ all-local:
|
||||
find $(DIST_SUBDIRS) \
|
||||
-name '*.c' -o -name '*.pl' -o -name '*.pm' | \
|
||||
grep -v '^perl/blib/' | \
|
||||
grep -v '^capitests/' | \
|
||||
grep -v '^tests/' | \
|
||||
grep -v '^daemon/lib/' | \
|
||||
grep -v '^daemon/tests/' | \
|
||||
grep -v '^examples/' | \
|
||||
@@ -200,6 +245,7 @@ all-local:
|
||||
grep -v '/rc_protocol.c' | \
|
||||
grep -v 'appliance/debian/root' | \
|
||||
grep -v '^po-docs/' | \
|
||||
grep -v '^images/' | \
|
||||
LC_ALL=C sort | \
|
||||
sed 's,^\./,,' > po/POTFILES.in
|
||||
|
||||
@@ -221,6 +267,11 @@ CLEANFILES = \
|
||||
quickcheck:
|
||||
./run test-tool/libguestfs-test-tool $(QUICKCHECK_TEST_TOOL_ARGS)
|
||||
|
||||
# Run extra-tests in tests/extra/ subdirectory.
|
||||
|
||||
extra-tests:
|
||||
make -C tests/extra $@
|
||||
|
||||
# Make binary distribution.
|
||||
|
||||
BINTMPDIR = /tmp/libguestfs-bin
|
||||
|
||||
19
README
@@ -77,6 +77,9 @@ For basic functionality and the C tools:
|
||||
- Berkeley DB 'db_dump' and 'db_load' utilities
|
||||
(db4-utils or db4.X-util or similar) (optional)
|
||||
|
||||
- systemtap/DTrace userspace probes (optional)
|
||||
http://sourceware.org/systemtap/wiki/AddingUserSpaceProbingToApps
|
||||
|
||||
- perldoc (pod2man, pod2text, pod2html) to generate the manual pages
|
||||
and other documentation.
|
||||
|
||||
@@ -98,10 +101,6 @@ To build FUSE support (guestmount):
|
||||
|
||||
- FUSE libraries and kernel module (optional)
|
||||
|
||||
To build virt-resize:
|
||||
|
||||
- OCaml PCRE bindings (ocaml-pcre) (optional)
|
||||
|
||||
To build language bindings:
|
||||
|
||||
- Perl if you want to build the perl bindings (optional)
|
||||
@@ -131,6 +130,10 @@ To build the Perl tools:
|
||||
|
||||
- perl-libintl for translating perl code (optional)
|
||||
|
||||
To run virt-sysprep:
|
||||
|
||||
- virt-sysprep requires FUSE support since it uses guestmount
|
||||
|
||||
|
||||
Building
|
||||
----------------------------------------------------------------------
|
||||
@@ -144,6 +147,14 @@ Finally run the tests:
|
||||
|
||||
make check
|
||||
|
||||
There are some extra tests, but these require that you have some
|
||||
libvirt guests installed, that these guests' disks are accessible by
|
||||
the current user, and these tests may fail for other reasons which are
|
||||
not necessarily because of real problems. If you want to run these
|
||||
extra tests do:
|
||||
|
||||
make extra-tests
|
||||
|
||||
If everything works, you can install the library and tools by running
|
||||
this command as root:
|
||||
|
||||
|
||||
297
RELEASE-NOTES
@@ -1,3 +1,300 @@
|
||||
Release notes for libguestfs 1.16.0
|
||||
-----------------------------------
|
||||
|
||||
NOT FINAL, COVERS UP TO COMMIT 54a7982dc3a6d3cc903c8d6e73be30c46fdf90d4
|
||||
|
||||
These release notes only cover the differences from the previous
|
||||
stable/dev branch split (1.14.0). For detailed changelogs, please see
|
||||
the git repository, or the ChangeLog file distributed in the tarball.
|
||||
|
||||
New features
|
||||
|
||||
libguestfs:
|
||||
|
||||
- allow XFS filesystems to be created over an existing filesystem
|
||||
(Wanlong Gao)
|
||||
|
||||
- the (unspecified) default alignment for part-disk has been
|
||||
changed to 64K for better support of high-end network-attached
|
||||
storage
|
||||
|
||||
- new guestfs-testing(1) man page
|
||||
|
||||
- list-filesystems returns MD devices containing filesystems
|
||||
(Matthew Booth)
|
||||
|
||||
- support for GCC >= 4.7 (Jim Meyering)
|
||||
|
||||
- check user does not add the same drive twice (Wanlong Gao).
|
||||
|
||||
language bindings:
|
||||
|
||||
- support for Ruby >= 1.9
|
||||
|
||||
- Ruby bindings can be disabled individually (Hilko Bengen)
|
||||
|
||||
- support for Python 2.5, 2.6 (Hilko Bengen)
|
||||
|
||||
- support for Python 3
|
||||
|
||||
- new %guestfs_introspection hash is available in Perl bindings so
|
||||
you can query which optional arguments are available
|
||||
|
||||
inspection:
|
||||
|
||||
- guests with MD devices can be inspected (Matthew Booth)
|
||||
|
||||
- support for GNU/Hurd guests
|
||||
|
||||
guestfish:
|
||||
|
||||
- libguestfs events (such as progress bar events and log messages) can
|
||||
be trapped and processed by user-defined shell scripts.
|
||||
|
||||
- MD devices are tab-completed (Matthew Booth)
|
||||
|
||||
virt tools:
|
||||
|
||||
- virt-sparsify new --compress and -o options to allow for compressed
|
||||
and different format output
|
||||
|
||||
- virt-sparsify can now detect and sparsify .vdi files
|
||||
|
||||
- virt-sysprep no longer requires xmlstarlet; a new virt-inspector --xpath
|
||||
option has been added to replace this functionality
|
||||
|
||||
- virt-rescue has a new --suggest option which suggests mount commands
|
||||
for the guest
|
||||
|
||||
- virt-resize no longer requires OCaml pcre library
|
||||
|
||||
libguestfs live:
|
||||
|
||||
- daemon will no longer try to edit your live /etc/lvm configuration
|
||||
|
||||
- fix a potential security problem with predictable /tmp names (Steve Kemp)
|
||||
|
||||
Security
|
||||
|
||||
CVE-2011-4127, RHBZ#757071
|
||||
Mitigate possible privilege escalation via SG_IO ioctl
|
||||
For more information, see: https://github.com/libguestfs/libguestfs/commit/9a5f784d511a8f00a8386f316eab41fe660430db
|
||||
|
||||
New APIs
|
||||
|
||||
blkid: print all attributes of a device known to blkid (Wanlong Gao)
|
||||
list-md-devices: list of Linux MD devices (Matthew Booth)
|
||||
md-create: create an MD device
|
||||
md-detail: returns metadata for an MD device (Matthew Booth)
|
||||
md-stop: stop an MD device (Wanlong Gao)
|
||||
tune2fs: allow ext2/3/4 filesystems to be tuned
|
||||
|
||||
Internals
|
||||
|
||||
Git hosting has moved to http://github.com/libguestfs
|
||||
|
||||
The various test directories have been rearranged logically, and now
|
||||
all appear under 'tests/'.
|
||||
|
||||
There is a 'make extra-tests' rule which runs ordinary tests and
|
||||
additional tests, using valgrind to check for memory problems.
|
||||
|
||||
Multiple memory leaks and other problems found by valgrind and fixed.
|
||||
|
||||
Support for optional arguments in the generator has been rewritten
|
||||
to provide more features and safety (Matthew Booth).
|
||||
|
||||
RHashtable functions can be tested in the generator.
|
||||
|
||||
ADD_ARG macro in daemon allows arg lists to be constructed without
|
||||
risk of stack smashing.
|
||||
|
||||
Fix generation of OCaml functions that have more than 10 arguments.
|
||||
|
||||
Bugs fixed
|
||||
|
||||
[./bugs-in-changelog.sh 1.14.0..]
|
||||
|
||||
- 769680 temporary directories created during appliance builds are not cleaned up on error
|
||||
- 761460 guestfs_utimens hangs on named pipes
|
||||
- 761451 guestfs_utimens cannot set times on a directory
|
||||
- 760775 "guestfish: multi-boot operating systems are not supported by the -i option" should be more explanatory
|
||||
- 760669 guestfish copy-in and <! (inline execution) don't mix well: pclose: No child processes
|
||||
- 760000 libguestfs fails to compile with Ruby >= 1.9
|
||||
- 750889 Python code incompatible with Python v3.
|
||||
- 596761 Ctrl-\ causes guestfish to abort
|
||||
|
||||
|
||||
Release notes for libguestfs 1.14.0
|
||||
-----------------------------------
|
||||
|
||||
These release notes only cover the differences from the previous
|
||||
stable/dev branch split (1.12.0). For detailed changelogs, please see
|
||||
the git repository, or the ChangeLog file distributed in the tarball.
|
||||
|
||||
New features
|
||||
|
||||
Erlang bindings.
|
||||
|
||||
virt-alignment-scan is a new tool to check the alignment of
|
||||
partitions within virtual machines or disk images.
|
||||
|
||||
virt-sparsify is a new tool to make virtual machine disk images
|
||||
sparse.
|
||||
|
||||
virt-sysprep is a new tool to make cloning guests from a template
|
||||
simpler.
|
||||
|
||||
guestfish:
|
||||
|
||||
- New commands setenv, unsetenv, to set environment variables.
|
||||
|
||||
- The input file and line number is printed in error messages.
|
||||
|
||||
- guestfish progress bars are now a "mini-library" used by other
|
||||
tools too.
|
||||
|
||||
guestmount:
|
||||
|
||||
- the --live option (for access to live VMs) now works.
|
||||
|
||||
virt-cat:
|
||||
|
||||
- virt-cat can now handle Windows paths and drive letters (RHBZ#693359).
|
||||
|
||||
virt-filesystems:
|
||||
|
||||
- the MBR partition type byte is displayed in --long output.
|
||||
|
||||
virt-make-fs:
|
||||
|
||||
- virt-make-fs now sets the MBR partition type byte correctly,
|
||||
improving compatibility with Windows (RHBZ#746295).
|
||||
|
||||
virt-resize:
|
||||
|
||||
- virt-resize can now work with guests using extended and logical
|
||||
partitions, in particular Ubuntu guests.
|
||||
|
||||
- virt-resize can now align the first partition of Windows guests,
|
||||
improving performance. The new virt-resize --align-first option
|
||||
controls this behaviour.
|
||||
|
||||
- The virt-resize --machine-readable flag makes it possible to use
|
||||
virt-resize from other programs.
|
||||
|
||||
- Partitions are now aligned to 128 sectors (usually 64K) by
|
||||
default. This improves efficiency on high-end storage. The new
|
||||
virt-resize --alignment option allows the alignment to be
|
||||
adjusted.
|
||||
|
||||
virt-win-reg:
|
||||
|
||||
- The syntax for deleting registry keys and values is documented
|
||||
in the man page (RHBZ#737944).
|
||||
|
||||
library:
|
||||
|
||||
- non-printing characters are escaped correctly in debug output.
|
||||
|
||||
- GUESTFS_EVENT_ENTER is a new event type generated whenever a
|
||||
libguestfs function is called.
|
||||
|
||||
- the library contains systemtap/DTrace probes.
|
||||
|
||||
- the library can now be compiled without hivex (RHBZ#723474).
|
||||
|
||||
inspection:
|
||||
|
||||
- Improve detection of Windows disks.
|
||||
|
||||
- Adds support for:
|
||||
ttylinux - a minimal Linux
|
||||
Mageia (thanks Michael Scherer)
|
||||
OpenSUSE and zypper (thanks Michael Scherer, Vincent Untz)
|
||||
Ubuntu logos (thanks Michael Scherer)
|
||||
NetBSD and pkgsrc (thanks Michael Scherer)
|
||||
|
||||
- Handle some guest types that use /dev/root in /etc/fstab.
|
||||
|
||||
- Fix handling of guests with > 26 disks (thanks Matthew Booth)
|
||||
|
||||
- Add support for guests with HP Smart Array disks (thanks Matthew Booth)
|
||||
|
||||
febootstrap:
|
||||
|
||||
- FEBOOTSTRAP_KERNEL, FEBOOTSTRAP_MODULES environment variables can
|
||||
be set in order to choose which kernel to use for the appliance.
|
||||
|
||||
misc:
|
||||
|
||||
- ArchLinux support now working with Linux 3.0 (thanks Erik Nolte)
|
||||
|
||||
- libvirt disks marked <readonly/> are now added readonly when
|
||||
using the virt-tools '-d' option.
|
||||
|
||||
Security
|
||||
|
||||
(no security problems were found or fixed in this release)
|
||||
|
||||
New APIs
|
||||
|
||||
compress-out, compress-device-out, copy-device-to-device,
|
||||
copy-device-to-file, copy-file-to-device, copy-file-to-file,
|
||||
get-smp, part-to-partnum, set-smp.
|
||||
|
||||
The mount API no longer implicitly adds -o sync,noatime options.
|
||||
|
||||
add-domain has a new 'readonlydisk' optional parameter to control
|
||||
how <readonly/> disks are handled.
|
||||
|
||||
Internals
|
||||
|
||||
- Coverity was run on the source and more bugs were identified and
|
||||
fixed.
|
||||
|
||||
- PCRE library is now required to build libguestfs.
|
||||
|
||||
- APIC is now the default for the appliance. You can also enable
|
||||
SMP support in the appliance.
|
||||
|
||||
- OCaml bindings now correctly acquire GC lock during callbacks.
|
||||
|
||||
- Out of tree builds should now work correctly (thanks Hilko Bengen).
|
||||
|
||||
- ./configure --with-extra="..." can be used by packagers to set
|
||||
the extra version string.
|
||||
|
||||
- zero, zero-device APIs: if the blocks already contain zeroes,
|
||||
don't write zeroes, so that we don't unnecessarily make the
|
||||
underlying storage non-sparse.
|
||||
|
||||
- is-zero, is-zero-device APIs: optimize these so zero detection is
|
||||
faster.
|
||||
|
||||
Bugs fixed
|
||||
|
||||
- 748266 libguestfs should detect versions of qemu which require -machine pc option
|
||||
- 747290 libguestfs ignores <readonly/> in libvirt XML
|
||||
- 747287 Misleading error message when permission denied opening a disk image
|
||||
- 746295 virt-make-fs doesn't set partition ID
|
||||
- 744795 guestmount --live is not usable
|
||||
- 737944 virt-win-reg hyphen (delete key) syntax may be wrong, and is not documented
|
||||
- 733297 ruby event handlers fail with "exception in callback: wrong argument type Proc (expected Data)"
|
||||
- 731744 libguestfs should escape special/non-printing characters in debug output
|
||||
- 729887 appliance crashes running aug_init with flags=4
|
||||
- 729075 libguestfs confuses Hp_recovery partition with Windows root filesystem
|
||||
- 727178 error: luks_open: cryptsetup: error while loading shared libraries: libfipscheck.so.1: cannot open shared object file: No such file or directory
|
||||
- 726739 libguestfs: error: aug_get: no matching node, trying to find hostname
|
||||
- 723474 If hivex and/or pcre not installed, libguestfs fails to compile
|
||||
- 693359 virt-cat and virt-edit don't handle case sensitive NTFS paths properly
|
||||
- 678231 virt-inspector reports unknown filesystem UUID
|
||||
- 671082 libguestfs does not work with kernel-rt
|
||||
- 666578 libguestfs: unknown filesystem label SWAP-sda2
|
||||
- 642821 virt-resize falls over on a disk image with a logical swap partition
|
||||
|
||||
|
||||
|
||||
Release notes for libguestfs 1.12.0
|
||||
-----------------------------------
|
||||
|
||||
|
||||
25
ROADMAP
@@ -7,20 +7,20 @@ Before you read this:
|
||||
|
||||
(2) To see the list of bugs, read 'BUGS'.
|
||||
|
||||
(3) To understand libguestfs versioning, read section
|
||||
'LIBGUESTFS VERSION NUMBERS' of guestfs(3) man page.
|
||||
(3) To understand libguestfs versioning, read this:
|
||||
http://libguestfs.org/guestfs.3.html#libguestfs_version_numbers
|
||||
|
||||
(4) For general "might be good to have" items, see 'TODO'.
|
||||
|
||||
For next major stable release (1.14)
|
||||
For next major stable release (1.16)
|
||||
------------------------------------
|
||||
|
||||
Bugs assigned to 1.14 (put "1.14" in the Devel Whiteboard field in
|
||||
Bugs assigned to 1.16 (put "1.16" in the Devel Whiteboard field in
|
||||
Bugzilla):
|
||||
|
||||
https://bugzilla.redhat.com/buglist.cgi?query_format=advanced&field0-0-0=cf_devel_whiteboard&bug_status=NEW&bug_status=ASSIGNED&bug_status=MODIFIED&bug_status=ON_DEV&bug_status=ON_QA&bug_status=VERIFIED&bug_status=FAILS_QA&bug_status=RELEASE_PENDING&bug_status=POST&bug_status=PASSES_QA&type0-0-0=anywords&value0-0-0=1.14&component=libguestfs&product=Virtualization%20Tools&classification=Other
|
||||
https://bugzilla.redhat.com/buglist.cgi?query_format=advanced&field0-0-0=cf_devel_whiteboard&bug_status=NEW&bug_status=ASSIGNED&bug_status=MODIFIED&bug_status=ON_DEV&bug_status=ON_QA&bug_status=VERIFIED&bug_status=FAILS_QA&bug_status=RELEASE_PENDING&bug_status=POST&bug_status=PASSES_QA&type0-0-0=anywords&value0-0-0=1.16&component=libguestfs&product=Virtualization%20Tools
|
||||
|
||||
Beyond 1.14
|
||||
Beyond 1.16
|
||||
-----------
|
||||
|
||||
* Make 'guestfish --ro' be the default, and get users to use
|
||||
@@ -30,16 +30,11 @@ Beyond 1.14
|
||||
'guestfish --rw' option out there to do this yet.
|
||||
|
||||
* Allow alternate methods to start the appliance, including through
|
||||
libvirt and by connecting to an existing appliance. This was
|
||||
originally planned for 1.10 but we didn't get patches in time.
|
||||
libvirt, by connecting to an existing appliance, and remotely over
|
||||
ssh. Libvirt integration was originally planned for 1.10 but we
|
||||
didn't get patches in time.
|
||||
|
||||
* Deeper and wider support for progress messages. Many long-running
|
||||
operations in guestfs-browser don't display progress messages, eg.
|
||||
"du", "tar-in/out", because it's hard to estimate the runtime of
|
||||
these commands.
|
||||
|
||||
* Better handling of partitions, including MBR extended partitions.
|
||||
Write a new partition handling library to replace parted, and use it
|
||||
* Write a new partition handling library to replace parted, and use it
|
||||
instead of parted. (RHBZ#593511, RHBZ#642821).
|
||||
|
||||
* Hot plugging of disks using QMP. This would allow more efficient
|
||||
|
||||
71
TODO
@@ -94,7 +94,6 @@ Ideas for extra commands
|
||||
chattr
|
||||
lsattr
|
||||
badblocks
|
||||
blkid
|
||||
debugfs
|
||||
dumpe2fs
|
||||
e2image
|
||||
@@ -532,3 +531,73 @@ libosinfo mappings for virt-inspector
|
||||
-------------------------------------
|
||||
|
||||
Return libosinfo mappings from inspection API.
|
||||
|
||||
virt-sysprep ideas
|
||||
------------------
|
||||
|
||||
- touch /.unconfigured ?
|
||||
- other Spacewalk / RHN IDs (?)
|
||||
- Kerberos keys
|
||||
- Puppet registration
|
||||
- user accounts
|
||||
- Windows sysprep
|
||||
(see: https://github.com/clalancette/oz/blob/e74ce83283d468fd987583d6837b441608e5f8f0/oz/Windows.py )
|
||||
- blue skies: change the background image
|
||||
- (librarian suggests ...)
|
||||
. install a firstboot script virt-sysprep --script=/tmp/foo.sh
|
||||
. run an external shell script
|
||||
. run external guestfish script virt-sysprep --fish=/tmp/foo.fish
|
||||
. rm /var/cache/apt/archives/*
|
||||
- /var/run/* and pam_faillock's data files
|
||||
- homedirs/.ssh directory, especially /root/.ssh (Steve Grubb)
|
||||
- if drives are encrypted, then dm-crypt key should be changed
|
||||
and drives all re-encrypted
|
||||
- /etc/pki
|
||||
(Steve says ...)
|
||||
Rpm uses nss. Nss sets up its crypto database in
|
||||
/etc/pki. Depending on how long the machine ran before cloning, you
|
||||
may have picked up some certificates or things. This is an area
|
||||
that you would want to look into.
|
||||
- secure erase of inodes etc using scrub (Steve Grubb)
|
||||
- other directories that could require cleaning include:
|
||||
/var/cache/gdm/*
|
||||
/var/lib/fprint/*
|
||||
/var/run/*
|
||||
/var/lib/AccountService/users/*
|
||||
/var/lib/sss/db/*
|
||||
/var/lib/samba/*
|
||||
/var/lib/samba/*/*
|
||||
(thanks Marko Myllynen, James Antill)
|
||||
- remove or modify UUIDs in /etc/fstab (eg. on Ubuntu)
|
||||
(thanks Joshua Daniel Franklin)
|
||||
|
||||
Launch remote sessions over ssh
|
||||
-------------------------------
|
||||
|
||||
We had an idea you could add a launch method that uses ssh, ie. all
|
||||
febootstrap and qemu commands happen the same as now, but prefixed by
|
||||
ssh so it happens on a remote machine.
|
||||
|
||||
Note that proper remote support and integration with libvirt is
|
||||
different from this, and people are working on that. ssh would just
|
||||
be "remote-lite".
|
||||
|
||||
virt-make-fs and virt-win-reg need to not be in Perl
|
||||
----------------------------------------------------
|
||||
|
||||
Probably they should be in C or OCaml.
|
||||
|
||||
Integrate snap-type functionality in inspection tools
|
||||
-----------------------------------------------------
|
||||
|
||||
Mo Morsi's "snap" program lets you describe a guest as the list of
|
||||
packages (eg. RPMs) installed + changes made to those RPMs + files
|
||||
added.
|
||||
|
||||
http://projects.morsi.org/wiki/Snap
|
||||
|
||||
This results in a compact description of the guest. He even managed
|
||||
to do a kind of migration of guests by simply recreating the guest
|
||||
from the description on the target machine.
|
||||
|
||||
It would be ideal to integrate this and/or use inspection to do this.
|
||||
|
||||
79
align/Makefile.am
Normal file
@@ -0,0 +1,79 @@
|
||||
# libguestfs virt alignment tools
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
include $(top_srcdir)/subdir-rules.mk
|
||||
|
||||
EXTRA_DIST = \
|
||||
virt-alignment-scan.pod
|
||||
|
||||
CLEANFILES = stamp-virt-alignment-scan.pod
|
||||
|
||||
bin_PROGRAMS = virt-alignment-scan
|
||||
|
||||
SHARED_SOURCE_FILES = \
|
||||
../fish/config.c \
|
||||
../fish/inspect.c \
|
||||
../fish/keys.c \
|
||||
../fish/options.h \
|
||||
../fish/options.c \
|
||||
../fish/virt.c
|
||||
|
||||
virt_alignment_scan_SOURCES = \
|
||||
$(SHARED_SOURCE_FILES) \
|
||||
scan.c
|
||||
|
||||
virt_alignment_scan_CFLAGS = \
|
||||
-DGUESTFS_WARN_DEPRECATED=1 \
|
||||
-I$(top_srcdir)/src -I$(top_builddir)/src \
|
||||
-I$(top_srcdir)/fish \
|
||||
-I$(srcdir)/../gnulib/lib -I../gnulib/lib \
|
||||
-DLOCALEBASEDIR=\""$(datadir)/locale"\" \
|
||||
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
|
||||
$(LIBCONFIG_CFLAGS) \
|
||||
$(LIBVIRT_CFLAGS)
|
||||
|
||||
virt_alignment_scan_LDADD = \
|
||||
$(LIBCONFIG_LIBS) \
|
||||
$(top_builddir)/src/libguestfs.la \
|
||||
../gnulib/lib/libgnu.la \
|
||||
$(LIBVIRT_LIBS) \
|
||||
-lm
|
||||
|
||||
# Manual pages and HTML files for the website.
|
||||
man_MANS = virt-alignment-scan.1
|
||||
noinst_DATA = $(top_builddir)/html/virt-alignment-scan.1.html
|
||||
|
||||
virt-alignment-scan.1 $(top_builddir)/html/virt-alignment-scan.1.html: stamp-virt-alignment-scan.pod
|
||||
|
||||
stamp-virt-alignment-scan.pod: virt-alignment-scan.pod
|
||||
$(top_builddir)/podwrapper.sh \
|
||||
--man virt-alignment-scan.1 \
|
||||
--html $(top_builddir)/html/virt-alignment-scan.1.html \
|
||||
$<
|
||||
touch $@
|
||||
|
||||
# Tests.
|
||||
|
||||
# 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)
|
||||
|
||||
# TESTS = test-virt-alignment-scan.sh
|
||||
291
align/scan.c
Normal file
@@ -0,0 +1,291 @@
|
||||
/* virt-alignment-scan
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <locale.h>
|
||||
#include <assert.h>
|
||||
#include <libintl.h>
|
||||
|
||||
#ifdef HAVE_LIBVIRT
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#endif
|
||||
|
||||
#include "progname.h"
|
||||
#include "c-ctype.h"
|
||||
|
||||
#include "guestfs.h"
|
||||
#include "options.h"
|
||||
|
||||
/* These globals are shared with options.c. */
|
||||
guestfs_h *g;
|
||||
|
||||
int read_only = 1;
|
||||
int live = 0;
|
||||
int verbose = 0;
|
||||
int keys_from_stdin = 0;
|
||||
int echo_keys = 0;
|
||||
const char *libvirt_uri = NULL;
|
||||
int inspector = 0;
|
||||
|
||||
static int quiet = 0; /* --quiet */
|
||||
|
||||
static int scan (void);
|
||||
|
||||
static inline char *
|
||||
bad_cast (char const *s)
|
||||
{
|
||||
return (char *) s;
|
||||
}
|
||||
|
||||
static void __attribute__((noreturn))
|
||||
usage (int status)
|
||||
{
|
||||
if (status != EXIT_SUCCESS)
|
||||
fprintf (stderr, _("Try `%s --help' for more information.\n"),
|
||||
program_name);
|
||||
else {
|
||||
fprintf (stdout,
|
||||
_("%s: check alignment of virtual machine partitions\n"
|
||||
"Copyright (C) 2011 Red Hat Inc.\n"
|
||||
"Usage:\n"
|
||||
" %s [--options] -d domname\n"
|
||||
" %s [--options] -a disk.img [-a disk.img ...]\n"
|
||||
"Options:\n"
|
||||
" -a|--add image Add image\n"
|
||||
" -c|--connect uri Specify libvirt URI for -d option\n"
|
||||
" -d|--domain guest Add disks from libvirt guest\n"
|
||||
" --format[=raw|..] Force disk format for -a option\n"
|
||||
" --help Display brief help\n"
|
||||
" -q|--quiet No output, just exit code\n"
|
||||
" -v|--verbose Verbose messages\n"
|
||||
" -V|--version Display version and exit\n"
|
||||
" -x Trace libguestfs API calls\n"
|
||||
"For more information, see the manpage %s(1).\n"),
|
||||
program_name, program_name, program_name,
|
||||
program_name);
|
||||
}
|
||||
exit (status);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
/* Set global program name that is not polluted with libtool artifacts. */
|
||||
set_program_name (argv[0]);
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (PACKAGE, LOCALEBASEDIR);
|
||||
textdomain (PACKAGE);
|
||||
|
||||
enum { HELP_OPTION = CHAR_MAX + 1 };
|
||||
|
||||
static const char *options = "a:c:d:qvVx";
|
||||
static const struct option long_options[] = {
|
||||
{ "add", 1, 0, 'a' },
|
||||
{ "connect", 1, 0, 'c' },
|
||||
{ "domain", 1, 0, 'd' },
|
||||
{ "format", 2, 0, 0 },
|
||||
{ "help", 0, 0, HELP_OPTION },
|
||||
{ "quiet", 0, 0, 'q' },
|
||||
{ "verbose", 0, 0, 'v' },
|
||||
{ "version", 0, 0, 'V' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
struct drv *drvs = NULL;
|
||||
struct drv *drv;
|
||||
const char *format = NULL;
|
||||
int c;
|
||||
int option_index;
|
||||
int exit_code;
|
||||
|
||||
g = guestfs_create ();
|
||||
if (g == NULL) {
|
||||
fprintf (stderr, _("guestfs_create: failed to create handle\n"));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
argv[0] = bad_cast (program_name);
|
||||
|
||||
for (;;) {
|
||||
c = getopt_long (argc, argv, options, long_options, &option_index);
|
||||
if (c == -1) break;
|
||||
|
||||
switch (c) {
|
||||
case 0: /* options which are long only */
|
||||
if (STREQ (long_options[option_index].name, "format")) {
|
||||
if (!optarg || STREQ (optarg, ""))
|
||||
format = NULL;
|
||||
else
|
||||
format = optarg;
|
||||
} else {
|
||||
fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
|
||||
program_name, long_options[option_index].name, option_index);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
OPTION_a;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
OPTION_c;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
OPTION_d;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
OPTION_v;
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
OPTION_V;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
OPTION_x;
|
||||
break;
|
||||
|
||||
case HELP_OPTION:
|
||||
usage (EXIT_SUCCESS);
|
||||
|
||||
default:
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* These are really constants, but they have to be variables for the
|
||||
* options parsing code. Assert here that they have known-good
|
||||
* values.
|
||||
*/
|
||||
assert (read_only == 1);
|
||||
assert (inspector == 0);
|
||||
assert (live == 0);
|
||||
|
||||
/* Must be no extra arguments on the command line. */
|
||||
if (optind != argc)
|
||||
usage (EXIT_FAILURE);
|
||||
|
||||
/* The user didn't specify any drives to scan. */
|
||||
if (drvs == NULL)
|
||||
usage (EXIT_FAILURE);
|
||||
|
||||
/* Add domains/drives from the command line (for a single guest). */
|
||||
add_drives (drvs, 'a');
|
||||
|
||||
if (guestfs_launch (g) == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
/* Free up data structures, no longer needed after this point. */
|
||||
free_drives (drvs);
|
||||
|
||||
/* Perform the scan. */
|
||||
exit_code = scan ();
|
||||
|
||||
guestfs_close (g);
|
||||
|
||||
exit (exit_code);
|
||||
}
|
||||
|
||||
static int
|
||||
scan (void)
|
||||
{
|
||||
int exit_code = 0;
|
||||
char **devices;
|
||||
size_t i, j;
|
||||
size_t alignment;
|
||||
uint64_t start;
|
||||
struct guestfs_partition_list *parts;
|
||||
|
||||
devices = guestfs_list_devices (g);
|
||||
if (devices == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
for (i = 0; devices[i] != NULL; ++i) {
|
||||
parts = guestfs_part_list (g, devices[i]);
|
||||
if (parts == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
/* Canonicalize the name of the device for printing. */
|
||||
if (STRPREFIX (devices[i], "/dev/") &&
|
||||
(devices[i][5] == 'h' || devices[i][5] == 'v') &&
|
||||
devices[i][6] == 'd' &&
|
||||
c_isalpha (devices[i][7]))
|
||||
devices[i][5] = 's';
|
||||
|
||||
for (j = 0; j < parts->len; ++j) {
|
||||
/* Start offset of the partition in bytes. */
|
||||
start = parts->val[j].part_start;
|
||||
|
||||
if (!quiet)
|
||||
printf ("%s%d %12" PRIu64 " ",
|
||||
devices[i], (int) parts->val[j].part_num, start);
|
||||
|
||||
/* What's the alignment? */
|
||||
if (start == 0) /* Probably not possible, but anyway. */
|
||||
alignment = 64;
|
||||
else
|
||||
for (alignment = 0; (start & 1) == 0; alignment++, start /= 2)
|
||||
;
|
||||
|
||||
if (!quiet) {
|
||||
if (alignment < 10)
|
||||
printf ("%12" PRIu64 " ", UINT64_C(1) << alignment);
|
||||
else if (alignment < 64)
|
||||
printf ("%12" PRIu64 "K ", UINT64_C(1) << (alignment - 10));
|
||||
else
|
||||
printf ("- ");
|
||||
}
|
||||
|
||||
if (alignment < 12) { /* Bad in general: < 4K alignment */
|
||||
exit_code = 3;
|
||||
if (!quiet)
|
||||
printf ("bad (%s)\n", _("alignment < 4K"));
|
||||
} else if (alignment < 16) { /* Bad on NetApps: < 64K alignment */
|
||||
if (exit_code < 2)
|
||||
exit_code = 2;
|
||||
if (!quiet)
|
||||
printf ("bad (%s)\n", _("alignment < 64K"));
|
||||
} else {
|
||||
if (!quiet)
|
||||
printf ("ok\n");
|
||||
}
|
||||
}
|
||||
|
||||
guestfs_free_partition_list (parts);
|
||||
free (devices[i]);
|
||||
}
|
||||
free (devices);
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
381
align/virt-alignment-scan.pod
Executable file
@@ -0,0 +1,381 @@
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
virt-alignment-scan - Check alignment of virtual machine partitions
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
virt-alignment-scan [--options] -d domname
|
||||
|
||||
virt-alignment-scan [--options] -a disk.img [-a disk.img ...]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
When older operating systems install themselves, the partitioning
|
||||
tools place partitions at a sector misaligned with the underlying
|
||||
storage (commonly the first partition starts on sector C<63>).
|
||||
Misaligned partitions can result in an operating system issuing more
|
||||
I/O than should be necessary.
|
||||
|
||||
The virt-alignment-scan tool checks the alignment of partitions in
|
||||
virtual machines and disk images and warns you if there are alignment
|
||||
problems.
|
||||
|
||||
Currently there is no virt tool for fixing alignment problems. You
|
||||
can only reinstall the guest operating system. The following NetApp
|
||||
document summarises the problem and possible solutions:
|
||||
L<http://media.netapp.com/documents/tr-3747.pdf>
|
||||
|
||||
=head1 OUTPUT
|
||||
|
||||
To run this tool on a disk image directly, use the I<-a> option:
|
||||
|
||||
$ virt-alignment-scan -a winxp.img
|
||||
/dev/sda1 32256 512 bad (alignment < 4K)
|
||||
|
||||
$ virt-alignment-scan -a fedora16.img
|
||||
/dev/sda1 1048576 1024K ok
|
||||
/dev/sda2 2097152 2048K ok
|
||||
/dev/sda3 526385152 2048K ok
|
||||
|
||||
To run the tool on a guest known to libvirt, use the I<-d> option and
|
||||
possibly the I<-c> option:
|
||||
|
||||
# virt-alignment-scan -d RHEL5
|
||||
/dev/sda1 32256 512 bad (alignment < 4K)
|
||||
/dev/sda2 106928640 512 bad (alignment < 4K)
|
||||
|
||||
$ virt-alignment-scan -c qemu:///system -d Win7TwoDisks
|
||||
/dev/sda1 1048576 1024K ok
|
||||
/dev/sda2 105906176 1024K ok
|
||||
/dev/sdb1 65536 64K ok
|
||||
|
||||
The output consists of 4 or more whitespace-separated columns. Only
|
||||
the first 4 columns are signficant if you want to parse this from a
|
||||
program. The columns are:
|
||||
|
||||
=over 4
|
||||
|
||||
=item col 1
|
||||
|
||||
the device and partition name (eg. C</dev/sda1> meaning the
|
||||
first partition on the first block device)
|
||||
|
||||
=item col 2
|
||||
|
||||
the start of the partition in bytes
|
||||
|
||||
=item col 3
|
||||
|
||||
the alignment in bytes or Kbytes (eg. C<512> or C<4K>)
|
||||
|
||||
=item col 4
|
||||
|
||||
C<ok> if the alignment is best for performance, or C<bad> if the
|
||||
alignment can cause performance problems
|
||||
|
||||
=item cols 5+
|
||||
|
||||
optional free-text explanation.
|
||||
|
||||
=back
|
||||
|
||||
The exit code from the program changes depending on whether poorly
|
||||
aligned partitions were found. See L</EXIT STATUS> below.
|
||||
|
||||
If you just want the exit code with no output, use the I<-q> option.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<--help>
|
||||
|
||||
Display brief help.
|
||||
|
||||
=item B<-a> file
|
||||
|
||||
=item B<--add> file
|
||||
|
||||
Add I<file> which should be a disk image from a virtual machine.
|
||||
|
||||
The format of the disk image is auto-detected. To override this and
|
||||
force a particular format use the I<--format=..> option.
|
||||
|
||||
=item B<-c> URI
|
||||
|
||||
=item B<--connect> URI
|
||||
|
||||
If using libvirt, connect to the given I<URI>. If omitted, then we
|
||||
connect to the default libvirt hypervisor.
|
||||
|
||||
If you specify guest block devices directly (I<-a>), then libvirt is
|
||||
not used at all.
|
||||
|
||||
=item B<-d> guest
|
||||
|
||||
=item B<--domain> guest
|
||||
|
||||
Add all the disks from the named libvirt guest. Domain UUIDs can be
|
||||
used instead of names.
|
||||
|
||||
=item B<--format=raw|qcow2|..>
|
||||
|
||||
=item B<--format>
|
||||
|
||||
The default for the I<-a> option is to auto-detect the format of the
|
||||
disk image. Using this forces the disk format for I<-a> options which
|
||||
follow on the command line. Using I<--format> with no argument
|
||||
switches back to auto-detection for subsequent I<-a> options.
|
||||
|
||||
For example:
|
||||
|
||||
virt-alignment-scan --format=raw -a disk.img
|
||||
|
||||
forces raw format (no auto-detection) for C<disk.img>.
|
||||
|
||||
virt-alignment-scan --format=raw -a disk.img --format -a another.img
|
||||
|
||||
forces raw format (no auto-detection) for C<disk.img> and reverts to
|
||||
auto-detection for C<another.img>.
|
||||
|
||||
If you have untrusted raw-format guest disk images, you should use
|
||||
this option to specify the disk format. This avoids a possible
|
||||
security problem with malicious guests (CVE-2010-3851).
|
||||
|
||||
=item B<-q>
|
||||
|
||||
=item B<--quiet>
|
||||
|
||||
Don't produce any output. Just set the exit code
|
||||
(see L</EXIT STATUS> below).
|
||||
|
||||
=item B<-v>
|
||||
|
||||
=item B<--verbose>
|
||||
|
||||
Enable verbose messages for debugging.
|
||||
|
||||
=item B<-V>
|
||||
|
||||
=item B<--version>
|
||||
|
||||
Display version number and exit.
|
||||
|
||||
=item B<-x>
|
||||
|
||||
Enable tracing of libguestfs API calls.
|
||||
|
||||
=back
|
||||
|
||||
=head1 RECOMMENDED ALIGNMENT
|
||||
|
||||
Operating systems older than Windows 2008 and Linux before ca.2010
|
||||
place the first sector of the first partition at sector 63, with a 512
|
||||
byte sector size. This happens because of a historical accident.
|
||||
Drives have to report a cylinder / head / sector (CHS) geometry to the
|
||||
BIOS. The geometry is completely meaningless on modern drives, but it
|
||||
happens that the geometry reported always has 63 sectors per track.
|
||||
The operating system therefore places the first partition at the start
|
||||
of the second "track", at sector 63.
|
||||
|
||||
When the guest OS is virtualized, the host operating system and
|
||||
hypervisor may prefer accesses aligned to one of:
|
||||
|
||||
=over 4
|
||||
|
||||
=item * 512 bytes
|
||||
|
||||
if the host OS uses local storage directly on hard drive partitions,
|
||||
and the hard drive has 512 byte physical sectors.
|
||||
|
||||
=item * 4 Kbytes
|
||||
|
||||
for local storage on new hard drives with 4Kbyte physical sectors; for
|
||||
file-backed storage on filesystems with 4Kbyte block size; or for some
|
||||
types of network-attached storage.
|
||||
|
||||
=item * 64 Kbytes
|
||||
|
||||
for high-end network-attached storage. This is the optimal block size
|
||||
for some NetApp hardware.
|
||||
|
||||
=item * 1 Mbyte
|
||||
|
||||
see L</1 MB PARTITION ALIGNMENT> below.
|
||||
|
||||
=back
|
||||
|
||||
Partitions which are not aligned correctly to the underlying
|
||||
storage cause extra I/O. For example:
|
||||
|
||||
sect#63
|
||||
+--------------------------+------
|
||||
| guest |
|
||||
| filesystem block |
|
||||
---+------------------+------+-------------------+-----+---
|
||||
| host block | host block |
|
||||
| | |
|
||||
---+-------------------------+-------------------------+---
|
||||
|
||||
In this example, each time a 4K guest block is read, two blocks on the
|
||||
host must be accessed (so twice as much I/O is done). When a 4K guest
|
||||
block is written, two host blocks must first be read, the old and new
|
||||
data combined, and the two blocks written back (4x I/O).
|
||||
|
||||
=head2 LINUX HOST BLOCK AND I/O SIZE
|
||||
|
||||
New versions of the Linux kernel expose the physical and logical block
|
||||
size, and minimum and recommended I/O size.
|
||||
|
||||
For a typical consumer hard drive with 512 byte sectors:
|
||||
|
||||
$ cat /sys/block/sda/queue/hw_sector_size
|
||||
512
|
||||
$ cat /sys/block/sda/queue/physical_block_size
|
||||
512
|
||||
$ cat /sys/block/sda/queue/logical_block_size
|
||||
512
|
||||
$ cat /sys/block/sda/queue/minimum_io_size
|
||||
512
|
||||
$ cat /sys/block/sda/queue/optimal_io_size
|
||||
0
|
||||
|
||||
For a new consumer hard drive with 4Kbyte sectors:
|
||||
|
||||
$ cat /sys/block/sda/queue/hw_sector_size
|
||||
4096
|
||||
$ cat /sys/block/sda/queue/physical_block_size
|
||||
4096
|
||||
$ cat /sys/block/sda/queue/logical_block_size
|
||||
4096
|
||||
$ cat /sys/block/sda/queue/minimum_io_size
|
||||
4096
|
||||
$ cat /sys/block/sda/queue/optimal_io_size
|
||||
0
|
||||
|
||||
For a NetApp LUN:
|
||||
|
||||
$ cat /sys/block/sdc/queue/logical_block_size
|
||||
512
|
||||
$ cat /sys/block/sdc/queue/physical_block_size
|
||||
512
|
||||
$ cat /sys/block/sdc/queue/minimum_io_size
|
||||
4096
|
||||
$ cat /sys/block/sdc/queue/optimal_io_size
|
||||
65536
|
||||
|
||||
The NetApp allows 512 byte accesses (but they will be very
|
||||
inefficient), prefers a minimum 4K I/O size, but the optimal I/O size
|
||||
is 64K.
|
||||
|
||||
For detailed information about what these numbers mean, see
|
||||
L<http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Storage_Administration_Guide/newstorage-iolimits.html>
|
||||
|
||||
[Thanks to Matt Booth for providing 4K drive data. Thanks to Mike
|
||||
Snitzer for providing NetApp data and additional information.]
|
||||
|
||||
=head2 1 MB PARTITION ALIGNMENT
|
||||
|
||||
Microsoft picked 1 MB as the default alignment for all partitions
|
||||
starting with Windows 2008 Server, and Linux has followed this.
|
||||
|
||||
Assuming 512 byte sectors in the guest, you will now see the first
|
||||
partition starting at sector 2048, and subsequent partitions (if any)
|
||||
will start at a multiple of 2048 sectors.
|
||||
|
||||
1 MB alignment is compatible with all current alignment requirements
|
||||
(4K, 64K) and provides room for future growth in physical block sizes.
|
||||
|
||||
=head2 SETTING ALIGNMENT
|
||||
|
||||
L<virt-resize(1)> can change the alignment of the partitions of some
|
||||
guests. Currently it can fully align all the partitions of all
|
||||
Windows guests, and it will fix the bootloader where necessary. For
|
||||
Linux guests, it can align the second and subsequent partitions, so
|
||||
the majority of OS accesses except at boot will be aligned.
|
||||
|
||||
Another way to correct partition alignment problems is to reinstall
|
||||
your guest operating systems. If you install operating systems from
|
||||
templates, ensure these have correct partition alignment too.
|
||||
|
||||
For older versions of Windows, the following NetApp document contains
|
||||
useful information: L<http://media.netapp.com/documents/tr-3747.pdf>
|
||||
|
||||
For Red Hat Enterprise Linux E<le> 5, use a Kickstart script that
|
||||
contains an explicit C<%pre> section that creates aligned partitions
|
||||
using L<parted(8)>. Do not use the Kickstart C<part> command. The
|
||||
NetApp document above contains an example.
|
||||
|
||||
=head1 SHELL QUOTING
|
||||
|
||||
Libvirt guest names can contain arbitrary characters, some of which
|
||||
have meaning to the shell such as C<#> and space. You may need to
|
||||
quote or escape these characters on the command line. See the shell
|
||||
manual page L<sh(1)> for details.
|
||||
|
||||
=head1 EXIT STATUS
|
||||
|
||||
This program returns:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
0
|
||||
|
||||
successful exit, all partitions are aligned E<ge> 64K for best performance
|
||||
|
||||
=item *
|
||||
|
||||
1
|
||||
|
||||
an error scanning the disk image or guest
|
||||
|
||||
=item *
|
||||
|
||||
2
|
||||
|
||||
successful exit, some partitions have alignment E<lt> 64K which can result
|
||||
in poor performance on high end network storage
|
||||
|
||||
=item *
|
||||
|
||||
3
|
||||
|
||||
successful exit, some partitions have alignment E<lt> 4K which can result
|
||||
in poor performance on most hypervisors
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<guestfs(3)>,
|
||||
L<guestfish(1)>,
|
||||
L<virt-filesystems(1)>,
|
||||
L<virt-rescue(1)>,
|
||||
L<virt-resize(1)>,
|
||||
L<http://libguestfs.org/>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
@@ -13,7 +13,7 @@
|
||||
#
|
||||
# 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.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
include $(top_srcdir)/subdir-rules.mk
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ mkdir -p /sysroot
|
||||
|
||||
rm -f /proc; mkdir /proc
|
||||
mount -t proc /proc /proc
|
||||
rm -f /sys; mkdir /sys
|
||||
mount -t sysfs /sys /sys
|
||||
mkdir -p /run/lock
|
||||
|
||||
if [ ! -L /etc/init.d/udev -a -x /etc/init.d/udev ]; then
|
||||
if type service >/dev/null 2>&1; then
|
||||
@@ -29,6 +31,11 @@ elif [ -x /sbin/udevd ]; then
|
||||
/sbin/udevd --daemon
|
||||
/sbin/udevadm trigger
|
||||
/sbin/udevadm settle
|
||||
elif [ -x /lib/udev/udevd ]; then
|
||||
echo -e '\000\000\000\000' > /proc/sys/kernel/hotplug
|
||||
/lib/udev/udevd --daemon
|
||||
/sbin/udevadm trigger
|
||||
/sbin/udevadm settle
|
||||
else
|
||||
echo No udev, creating /dev manually
|
||||
mount -t tmpfs none /dev
|
||||
@@ -63,6 +70,9 @@ ifconfig lo 127.0.0.1
|
||||
ifconfig eth0 169.254.2.10
|
||||
route add default gw 169.254.2.2
|
||||
|
||||
# Scan for MDs.
|
||||
mdadm -As --auto=yes --run
|
||||
|
||||
# Scan for LVM.
|
||||
modprobe dm_mod ||:
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#
|
||||
# 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.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
unset CDPATH
|
||||
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
#ifdef REDHAT
|
||||
augeas-libs
|
||||
btrfs-progs
|
||||
cryptsetup-luks
|
||||
cryptsetup
|
||||
cryptsetup-luks /* old name used before Fedora 17 */
|
||||
diffutils
|
||||
e2fsprogs
|
||||
/* e4fsprogs only exists on RHEL 5, will be ignored everywhere else. */
|
||||
@@ -72,7 +73,7 @@
|
||||
#endif /* DEBIAN */
|
||||
|
||||
#ifdef ARCHLINUX
|
||||
kernel26
|
||||
linux
|
||||
vim
|
||||
btrfs-progs-unstable
|
||||
cryptsetup
|
||||
@@ -104,8 +105,11 @@ gawk
|
||||
grep
|
||||
gzip
|
||||
jfsutils
|
||||
libxml2
|
||||
lsof
|
||||
lvm2
|
||||
lzop
|
||||
mdadm
|
||||
module-init-tools
|
||||
net-tools
|
||||
/*
|
||||
|
||||
96
autobuild.sh
@@ -1,96 +0,0 @@
|
||||
#!/bin/bash -
|
||||
|
||||
PROJECT=libguestfs
|
||||
FEBOOTSTRAP_PATH=$HOME/d/febootstrap
|
||||
MAILTO=libguestfs@redhat.com
|
||||
HOSTNAME="$(hostname -s)"
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Helper functions.
|
||||
|
||||
failed ()
|
||||
{
|
||||
mail -s "$HOSTNAME $PROJECT FAILED $1 $gitsha" $MAILTO < local-log
|
||||
}
|
||||
|
||||
ok ()
|
||||
{
|
||||
mail -s "$HOSTNAME $PROJECT success $gitsha" $MAILTO < local-log
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
# Make sure we build and test against latest febootstrap.
|
||||
PATH=$FEBOOTSTRAP_PATH:$FEBOOTSTRAP_PATH/helper:$PATH
|
||||
|
||||
# Remove any old cache directories.
|
||||
rm -rf /tmp/guestfs.* ||:
|
||||
|
||||
rm -f local-log
|
||||
cat > local-log <<EOF
|
||||
|
||||
This is an automatic message generated by the builder on
|
||||
$HOSTNAME for $PROJECT. Log files from the build
|
||||
follow below.
|
||||
|
||||
$(uname -a)
|
||||
$(date)
|
||||
|
||||
-----
|
||||
|
||||
EOF
|
||||
exec >> local-log 2>&1
|
||||
|
||||
# Pull from the public repo so that we don't need ssh-agent.
|
||||
git pull --rebase git://git.annexia.org/git/libguestfs.git master
|
||||
git clean -d -f
|
||||
|
||||
# The git version we are building.
|
||||
gitsha=$(git log|head -1|awk '{print $2}')
|
||||
|
||||
# Do the configure step.
|
||||
./bootstrap ||:
|
||||
./autogen.sh --enable-gcc-warnings || {
|
||||
failed "configure step"
|
||||
exit 1
|
||||
}
|
||||
|
||||
make clean ||:
|
||||
|
||||
# Do the build step.
|
||||
make || {
|
||||
failed "build step"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Tests that are skipped (note that these tests should be fixed).
|
||||
case "$HOSTNAME" in
|
||||
builder-ubuntu)
|
||||
# get_e2uuid: /dev/vdc: [no error message]
|
||||
# get_e2label: /dev/vda1: [no error message]
|
||||
# Diagnosis: either mkjournal is not writing a UUID or blkid is
|
||||
# unable to pick it up.
|
||||
export SKIP_TEST_GET_E2UUID=1
|
||||
export SKIP_TEST_SET_E2UUID=1
|
||||
export SKIP_TEST_SET_E2LABEL=1
|
||||
|
||||
# Avoids:
|
||||
# device-mapper: ioctl: unable to remove open device temporary-cryptsetup-661
|
||||
# device-mapper: remove ioctl failed: Device or resource busy
|
||||
# guestfsd: error: Device lukstest is busy.
|
||||
# Diagnosis: appears to be a bug in cryptsetup on Ubuntu.
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=527056
|
||||
export SKIP_TEST_LUKS_SH=1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Run the tests.
|
||||
make check || {
|
||||
failed "tests"
|
||||
exit 1
|
||||
}
|
||||
|
||||
ok
|
||||
@@ -14,7 +14,7 @@
|
||||
#
|
||||
# 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.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Rebuild the autotools environment.
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#
|
||||
# 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.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
# Used when preparing the RELEASE-NOTES file. This script looks at
|
||||
# the bugs noted in the git changelog since the last stable release
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#
|
||||
# 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.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
include $(top_srcdir)/subdir-rules.mk
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ export LANG=C
|
||||
set -e
|
||||
|
||||
# Read out the test files from the image using virt-cat.
|
||||
if [ "$(./virt-cat ../images/fedora.img /etc/test1)" != "abcdefg" ]; then
|
||||
if [ "$(./virt-cat ../tests/guests/fedora.img /etc/test1)" != "abcdefg" ]; then
|
||||
echo "$0: error: mismatch in file test1"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$(./virt-cat ../images/fedora.img /etc/test2)" != "" ]; then
|
||||
if [ "$(./virt-cat ../tests/guests/fedora.img /etc/test2)" != "" ]; then
|
||||
echo "$0: error: mismatch in file test2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
export LANG=C
|
||||
set -e
|
||||
|
||||
output="$(./virt-filesystems -a ../images/fedora.img | sort)"
|
||||
output="$(./virt-filesystems -a ../tests/guests/fedora.img | sort)"
|
||||
expected="/dev/VG/LV1
|
||||
/dev/VG/LV2
|
||||
/dev/VG/LV3
|
||||
@@ -16,7 +16,7 @@ if [ "$output" != "$expected" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
output="$(./virt-filesystems -a ../images/fedora.img --all --long --uuid -h --no-title | awk '{print $1}' | sort -u)"
|
||||
output="$(./virt-filesystems -a ../tests/guests/fedora.img --all --long --uuid -h --no-title | awk '{print $1}' | sort -u)"
|
||||
expected="/dev/VG
|
||||
/dev/VG/LV1
|
||||
/dev/VG/LV2
|
||||
|
||||
@@ -4,7 +4,7 @@ export LANG=C
|
||||
set -e
|
||||
|
||||
# Read out the test directory using virt-ls.
|
||||
if [ "$(./virt-ls ../images/fedora.img /bin)" != "ls
|
||||
if [ "$(./virt-ls ../tests/guests/fedora.img /bin)" != "ls
|
||||
test1
|
||||
test2
|
||||
test3
|
||||
@@ -17,7 +17,7 @@ test7" ]; then
|
||||
fi
|
||||
|
||||
# Try the -lR option.
|
||||
output="$(./virt-ls -lR ../images/fedora.img /boot | awk '{print $1 $2 $4}')"
|
||||
output="$(./virt-ls -lR ../tests/guests/fedora.img /boot | awk '{print $1 $2 $4}')"
|
||||
expected="d0755/boot
|
||||
d0755/boot/grub
|
||||
-0644/boot/grub/grub.conf
|
||||
|
||||
150
cat/virt-cat.c
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <libintl.h>
|
||||
|
||||
#include "progname.h"
|
||||
#include "c-ctype.h"
|
||||
|
||||
#include "guestfs.h"
|
||||
#include "options.h"
|
||||
@@ -44,6 +45,9 @@ int echo_keys = 0;
|
||||
const char *libvirt_uri = NULL;
|
||||
int inspector = 1;
|
||||
|
||||
static int is_windows (guestfs_h *g, const char *root);
|
||||
static char *windows_path (guestfs_h *g, const char *root, const char *filename);
|
||||
|
||||
static inline char *
|
||||
bad_cast (char const *s)
|
||||
{
|
||||
@@ -185,18 +189,17 @@ main (int argc, char *argv[])
|
||||
while (optind < argc - 1) {
|
||||
if (strchr (argv[optind], '/') ||
|
||||
access (argv[optind], F_OK) == 0) { /* simulate -a option */
|
||||
drv = malloc (sizeof (struct drv));
|
||||
drv = calloc (1, sizeof (struct drv));
|
||||
if (!drv) {
|
||||
perror ("malloc");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
drv->type = drv_a;
|
||||
drv->a.filename = argv[optind];
|
||||
drv->a.format = NULL;
|
||||
drv->next = drvs;
|
||||
drvs = drv;
|
||||
} else { /* simulate -d option */
|
||||
drv = malloc (sizeof (struct drv));
|
||||
drv = calloc (1, sizeof (struct drv));
|
||||
if (!drv) {
|
||||
perror ("malloc");
|
||||
exit (EXIT_FAILURE);
|
||||
@@ -241,14 +244,147 @@ main (int argc, char *argv[])
|
||||
free_drives (drvs);
|
||||
|
||||
unsigned errors = 0;
|
||||
int windows;
|
||||
char *root, **roots;
|
||||
|
||||
while (optind < argc) {
|
||||
if (guestfs_download (g, argv[optind], "/dev/stdout") == -1)
|
||||
/* Get root mountpoint. See: fish/inspect.c:inspect_mount */
|
||||
roots = guestfs_inspect_get_roots (g);
|
||||
assert (roots);
|
||||
assert (roots[0] != NULL);
|
||||
assert (roots[1] == NULL);
|
||||
root = roots[0];
|
||||
free (roots);
|
||||
|
||||
/* Windows? Special handling is required. */
|
||||
windows = is_windows (g, root);
|
||||
|
||||
for (; optind < argc; optind++) {
|
||||
char *filename_to_free = NULL;
|
||||
const char *filename = argv[optind];
|
||||
|
||||
if (windows) {
|
||||
filename = filename_to_free = windows_path (g, root, filename);
|
||||
if (filename == NULL) {
|
||||
errors++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (guestfs_download (g, filename, "/dev/stdout") == -1)
|
||||
errors++;
|
||||
optind++;
|
||||
|
||||
free (filename_to_free);
|
||||
}
|
||||
|
||||
free (root);
|
||||
|
||||
guestfs_close (g);
|
||||
|
||||
exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int
|
||||
is_windows (guestfs_h *g, const char *root)
|
||||
{
|
||||
char *type;
|
||||
int w;
|
||||
|
||||
type = guestfs_inspect_get_type (g, root);
|
||||
if (!type)
|
||||
return 0;
|
||||
|
||||
w = STREQ (type, "windows");
|
||||
free (type);
|
||||
return w;
|
||||
}
|
||||
|
||||
static void mount_drive_letter_ro (char drive_letter, const char *root);
|
||||
|
||||
static char *
|
||||
windows_path (guestfs_h *g, const char *root, const char *path)
|
||||
{
|
||||
char *ret;
|
||||
size_t i;
|
||||
|
||||
/* If there is a drive letter, rewrite the path. */
|
||||
if (c_isalpha (path[0]) && path[1] == ':') {
|
||||
char drive_letter = c_tolower (path[0]);
|
||||
/* This returns the newly allocated string. */
|
||||
mount_drive_letter_ro (drive_letter, root);
|
||||
ret = strdup (path + 2);
|
||||
if (ret == NULL) {
|
||||
perror ("strdup");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else if (!*path) {
|
||||
ret = strdup ("/");
|
||||
if (ret == NULL) {
|
||||
perror ("strdup");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = strdup (path);
|
||||
if (ret == NULL) {
|
||||
perror ("strdup");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Blindly convert any backslashes into forward slashes. Is this good? */
|
||||
for (i = 0; i < strlen (ret); ++i)
|
||||
if (ret[i] == '\\')
|
||||
ret[i] = '/';
|
||||
|
||||
/* If this fails, we want to return NULL. */
|
||||
char *t = guestfs_case_sensitive_path (g, ret);
|
||||
free (ret);
|
||||
ret = t;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
mount_drive_letter_ro (char drive_letter, const char *root)
|
||||
{
|
||||
char **drives;
|
||||
char *device;
|
||||
size_t i;
|
||||
|
||||
/* Resolve the drive letter using the drive mappings table. */
|
||||
drives = guestfs_inspect_get_drive_mappings (g, root);
|
||||
if (drives == NULL || drives[0] == NULL) {
|
||||
fprintf (stderr, _("%s: to use Windows drive letters, this must be a Windows guest\n"),
|
||||
program_name);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
device = NULL;
|
||||
for (i = 0; drives[i] != NULL; i += 2) {
|
||||
if (c_tolower (drives[i][0]) == drive_letter && drives[i][1] == '\0') {
|
||||
device = drives[i+1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (device == NULL) {
|
||||
fprintf (stderr, _("%s: drive '%c:' not found.\n"),
|
||||
program_name, drive_letter);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Unmount current disk and remount device. */
|
||||
if (guestfs_umount_all (g) == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
if (guestfs_mount_ro (g, device, "/") == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
for (i = 0; drives[i] != NULL; ++i)
|
||||
free (drives[i]);
|
||||
free (drives);
|
||||
/* Don't need to free (device) because that string was in the
|
||||
* drives array.
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -165,6 +165,46 @@ name as a guest.
|
||||
|
||||
For compatibility the old style is still supported.
|
||||
|
||||
=head1 WINDOWS PATHS
|
||||
|
||||
C<virt-cat> has a limited ability to understand Windows drive letters
|
||||
and paths (eg. C<E:\foo\bar.txt>).
|
||||
|
||||
If and only if the guest is running Windows then:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Drive letter prefixes like C<C:> are resolved against the
|
||||
Windows Registry to the correct filesystem.
|
||||
|
||||
=item *
|
||||
|
||||
Any backslash (C<\>) characters in the path are replaced
|
||||
with forward slashes so that libguestfs can process it.
|
||||
|
||||
=item *
|
||||
|
||||
The path is resolved case insensitively to locate the file
|
||||
that should be displayed.
|
||||
|
||||
=back
|
||||
|
||||
There are some known shortcomings:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Some NTFS symbolic links may not be followed correctly.
|
||||
|
||||
=item *
|
||||
|
||||
NTFS junction points that cross filesystems are not followed.
|
||||
|
||||
=back
|
||||
|
||||
=head1 USING GUESTFISH
|
||||
|
||||
L<guestfish(1)> is a more powerful, lower level tool which you can use
|
||||
@@ -186,8 +226,7 @@ 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.
|
||||
within the disk image, and C<file> is the full path to the file.
|
||||
|
||||
=head1 SHELL QUOTING
|
||||
|
||||
@@ -196,6 +235,11 @@ have meaning to the shell such as C<#> and space. You may need to
|
||||
quote or escape these characters on the command line. See the shell
|
||||
manual page L<sh(1)> for details.
|
||||
|
||||
=head1 EXIT STATUS
|
||||
|
||||
This program returns 0 if successful, or non-zero if there was an
|
||||
error.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<guestfs(3)>,
|
||||
@@ -225,4 +269,4 @@ 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.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -75,10 +75,11 @@ static int output = 0;
|
||||
#define COLUMN_TYPE 2
|
||||
#define COLUMN_VFS_TYPE 4 /* if --filesystems */
|
||||
#define COLUMN_VFS_LABEL 8 /* if --filesystems */
|
||||
#define COLUMN_SIZE 16 /* bytes, or human-readable if -h */
|
||||
#define COLUMN_PARENT_NAME 32 /* only for partitions, LVs */
|
||||
#define COLUMN_UUID 64 /* if --uuid */
|
||||
#define NR_COLUMNS 7
|
||||
#define COLUMN_MBR 16
|
||||
#define COLUMN_SIZE 32 /* bytes, or human-readable if -h */
|
||||
#define COLUMN_PARENT_NAME 64 /* only for partitions, LVs */
|
||||
#define COLUMN_UUID 128 /* if --uuid */
|
||||
#define NR_COLUMNS 8
|
||||
static int columns;
|
||||
|
||||
static char *canonical_device (const char *dev);
|
||||
@@ -335,6 +336,8 @@ main (int argc, char *argv[])
|
||||
}
|
||||
if ((output & (OUTPUT_PARTITIONS|OUTPUT_LVS)))
|
||||
columns |= COLUMN_PARENT_NAME;
|
||||
if ((output & OUTPUT_PARTITIONS))
|
||||
columns |= COLUMN_MBR;
|
||||
if (uuid)
|
||||
columns |= COLUMN_UUID;
|
||||
}
|
||||
@@ -373,7 +376,7 @@ static void do_output_vgs (void);
|
||||
static void do_output_pvs (void);
|
||||
static void do_output_partitions (void);
|
||||
static void do_output_blockdevs (void);
|
||||
static void write_row (const char *name, const char *type, const char *vfs_type, const char *vfs_label, int64_t size, const char *parent_name, const char *uuid);
|
||||
static void write_row (const char *name, const char *type, const char *vfs_type, const char *vfs_label, int mbr_id, int64_t size, const char *parent_name, const char *uuid);
|
||||
static void write_row_strings (char **strings, size_t len);
|
||||
|
||||
static void
|
||||
@@ -391,6 +394,8 @@ do_output_title (void)
|
||||
headings[len++] = "VFS";
|
||||
if ((columns & COLUMN_VFS_LABEL))
|
||||
headings[len++] = "Label";
|
||||
if ((columns & COLUMN_MBR))
|
||||
headings[len++] = "MBR";
|
||||
if ((columns & COLUMN_SIZE))
|
||||
headings[len++] = "Size";
|
||||
if ((columns & COLUMN_PARENT_NAME))
|
||||
@@ -444,7 +449,7 @@ do_output_filesystems (void)
|
||||
/* Skip swap and unknown, unless --extra flag was given. */
|
||||
if (!(output & OUTPUT_FILESYSTEMS_EXTRA) &&
|
||||
(STREQ (fses[i+1], "swap") || STREQ (fses[i+1], "unknown")))
|
||||
continue;
|
||||
goto next;
|
||||
|
||||
dev = canonical_device (fses[i]);
|
||||
|
||||
@@ -482,11 +487,13 @@ do_output_filesystems (void)
|
||||
}
|
||||
|
||||
write_row (dev, "filesystem",
|
||||
fses[i+1], vfs_label, size, NULL, vfs_uuid);
|
||||
fses[i+1], vfs_label, -1, size, NULL, vfs_uuid);
|
||||
|
||||
free (dev);
|
||||
free (vfs_label);
|
||||
free (vfs_uuid);
|
||||
|
||||
next:
|
||||
free (fses[i]);
|
||||
free (fses[i+1]);
|
||||
}
|
||||
@@ -530,7 +537,7 @@ do_output_lvs (void)
|
||||
}
|
||||
|
||||
write_row (lvs[i], "lv",
|
||||
NULL, NULL, size, parent_name, uuid);
|
||||
NULL, NULL, -1, size, parent_name, uuid);
|
||||
|
||||
free (uuid);
|
||||
free (parent_name);
|
||||
@@ -559,7 +566,7 @@ do_output_vgs (void)
|
||||
memcpy (uuid, vgs->val[i].vg_uuid, 32);
|
||||
uuid[32] = '\0';
|
||||
write_row (name, "vg",
|
||||
NULL, NULL, (int64_t) vgs->val[i].vg_size, NULL, uuid);
|
||||
NULL, NULL, -1, (int64_t) vgs->val[i].vg_size, NULL, uuid);
|
||||
|
||||
}
|
||||
|
||||
@@ -585,7 +592,7 @@ do_output_pvs (void)
|
||||
memcpy (uuid, pvs->val[i].pv_uuid, 32);
|
||||
uuid[32] = '\0';
|
||||
write_row (dev, "pv",
|
||||
NULL, NULL, (int64_t) pvs->val[i].pv_size, NULL, uuid);
|
||||
NULL, NULL, -1, (int64_t) pvs->val[i].pv_size, NULL, uuid);
|
||||
|
||||
free (dev);
|
||||
}
|
||||
@@ -593,6 +600,32 @@ do_output_pvs (void)
|
||||
guestfs_free_lvm_pv_list (pvs);
|
||||
}
|
||||
|
||||
static int
|
||||
get_mbr_id (const char *dev, const char *parent_name)
|
||||
{
|
||||
char *parttype = NULL;
|
||||
int mbr_id = -1, partnum;
|
||||
|
||||
DISABLE_GUESTFS_ERRORS_FOR (
|
||||
parttype = guestfs_part_get_parttype (g, parent_name);
|
||||
);
|
||||
|
||||
if (parttype && STREQ (parttype, "msdos")) {
|
||||
DISABLE_GUESTFS_ERRORS_FOR (
|
||||
partnum = guestfs_part_to_partnum (g, dev);
|
||||
);
|
||||
if (partnum >= 0) {
|
||||
DISABLE_GUESTFS_ERRORS_FOR (
|
||||
mbr_id = guestfs_part_get_mbr_id (g, parent_name, partnum);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
free (parttype);
|
||||
|
||||
return mbr_id;
|
||||
}
|
||||
|
||||
static void
|
||||
do_output_partitions (void)
|
||||
{
|
||||
@@ -606,6 +639,7 @@ do_output_partitions (void)
|
||||
for (i = 0; parts[i] != NULL; ++i) {
|
||||
char *dev, *parent_name = NULL;
|
||||
int64_t size = -1;
|
||||
int mbr_id = -1;
|
||||
|
||||
dev = canonical_device (parts[i]);
|
||||
|
||||
@@ -618,13 +652,17 @@ do_output_partitions (void)
|
||||
parent_name = guestfs_part_to_dev (g, parts[i]);
|
||||
if (parent_name == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
if ((columns & COLUMN_MBR))
|
||||
mbr_id = get_mbr_id (parts[i], parent_name);
|
||||
|
||||
char *p = canonical_device (parent_name);
|
||||
free (parent_name);
|
||||
parent_name = p;
|
||||
}
|
||||
|
||||
write_row (dev, "partition",
|
||||
NULL, NULL, size, parent_name, NULL);
|
||||
NULL, NULL, mbr_id, size, parent_name, NULL);
|
||||
|
||||
free (dev);
|
||||
free (parent_name);
|
||||
@@ -657,7 +695,7 @@ do_output_blockdevs (void)
|
||||
}
|
||||
|
||||
write_row (dev, "device",
|
||||
NULL, NULL, size, NULL, NULL);
|
||||
NULL, NULL, -1, size, NULL, NULL);
|
||||
|
||||
free (dev);
|
||||
free (devices[i]);
|
||||
@@ -688,13 +726,14 @@ canonical_device (const char *dev)
|
||||
|
||||
static void
|
||||
write_row (const char *name, const char *type,
|
||||
const char *vfs_type, const char *vfs_label,
|
||||
const char *vfs_type, const char *vfs_label, int mbr_id,
|
||||
int64_t size, const char *parent_name, const char *uuid)
|
||||
{
|
||||
const char *strings[NR_COLUMNS];
|
||||
size_t len = 0;
|
||||
char hum[LONGEST_HUMAN_READABLE];
|
||||
char num[256];
|
||||
char mbr_id_str[3];
|
||||
|
||||
if ((columns & COLUMN_NAME))
|
||||
strings[len++] = name;
|
||||
@@ -704,6 +743,13 @@ write_row (const char *name, const char *type,
|
||||
strings[len++] = vfs_type;
|
||||
if ((columns & COLUMN_VFS_LABEL))
|
||||
strings[len++] = vfs_label;
|
||||
if ((columns & COLUMN_MBR)) {
|
||||
if (mbr_id >= 0) {
|
||||
snprintf (mbr_id_str, sizeof mbr_id_str, "%02x", mbr_id);
|
||||
strings[len++] = mbr_id_str;
|
||||
} else
|
||||
strings[len++] = NULL;
|
||||
}
|
||||
if ((columns & COLUMN_SIZE)) {
|
||||
if (size >= 0) {
|
||||
if (human) {
|
||||
|
||||
@@ -316,6 +316,14 @@ type if one could be detected, eg. C<ext4>.
|
||||
If the object has a label (used for identifying and mounting
|
||||
filesystems) then this column contains the label.
|
||||
|
||||
=item B<MBR>
|
||||
|
||||
The partition type byte, displayed as a two digit hexadecimal number.
|
||||
A comprehensive list of partition types can be found here:
|
||||
L<http://www.win.tue.nl/~aeb/partitions/partition_types-1.html>
|
||||
|
||||
This is only applicable for DOS (MBR) partitions.
|
||||
|
||||
=item B<Size>
|
||||
|
||||
The size of the object in bytes. If the I<--human> option is used
|
||||
@@ -369,6 +377,11 @@ have meaning to the shell such as C<#> and space. You may need to
|
||||
quote or escape these characters on the command line. See the shell
|
||||
manual page L<sh(1)> for details.
|
||||
|
||||
=head1 EXIT STATUS
|
||||
|
||||
This program returns 0 if successful, or non-zero if there was an
|
||||
error.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<guestfs(3)>,
|
||||
@@ -400,4 +413,4 @@ 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.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -297,18 +297,17 @@ main (int argc, char *argv[])
|
||||
while (optind < argc - 1) {
|
||||
if (strchr (argv[optind], '/') ||
|
||||
access (argv[optind], F_OK) == 0) { /* simulate -a option */
|
||||
drv = malloc (sizeof (struct drv));
|
||||
drv = calloc (1, sizeof (struct drv));
|
||||
if (!drv) {
|
||||
perror ("malloc");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
drv->type = drv_a;
|
||||
drv->a.filename = argv[optind];
|
||||
drv->a.format = NULL;
|
||||
drv->next = drvs;
|
||||
drvs = drv;
|
||||
} else { /* simulate -d option */
|
||||
drv = malloc (sizeof (struct drv));
|
||||
drv = calloc (1, sizeof (struct drv));
|
||||
if (!drv) {
|
||||
perror ("malloc");
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
@@ -487,6 +487,11 @@ have meaning to the shell such as C<#> and space. You may need to
|
||||
quote or escape these characters on the command line. See the shell
|
||||
manual page L<sh(1)> for details.
|
||||
|
||||
=head1 EXIT STATUS
|
||||
|
||||
This program returns 0 if successful, or non-zero if there was an
|
||||
error.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<guestfs(3)>,
|
||||
@@ -519,4 +524,4 @@ 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.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
51
clone/Makefile.am
Normal file
@@ -0,0 +1,51 @@
|
||||
# libguestfs cloning tools
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
include $(top_srcdir)/subdir-rules.mk
|
||||
|
||||
EXTRA_DIST = \
|
||||
test-virt-sysprep.sh \
|
||||
virt-sysprep.pod
|
||||
|
||||
CLEANFILES = stamp-virt-sysprep.pod
|
||||
|
||||
bin_SCRIPTS = virt-sysprep
|
||||
|
||||
# Manual pages and HTML files for the website.
|
||||
man_MANS = virt-sysprep.1
|
||||
noinst_DATA = $(top_builddir)/html/virt-sysprep.1.html
|
||||
|
||||
virt-sysprep.1 $(top_builddir)/html/virt-sysprep.1.html: stamp-virt-sysprep.pod
|
||||
|
||||
stamp-virt-sysprep.pod: virt-sysprep.pod
|
||||
$(top_builddir)/podwrapper.sh \
|
||||
--man virt-sysprep.1 \
|
||||
--html $(top_builddir)/html/virt-sysprep.1.html \
|
||||
$<
|
||||
touch $@
|
||||
|
||||
# Tests.
|
||||
|
||||
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)
|
||||
|
||||
TESTS = test-virt-sysprep.sh
|
||||
49
clone/test-virt-sysprep.sh
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash -
|
||||
# libguestfs virt-sysprep test script
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
export LANG=C
|
||||
set -e
|
||||
|
||||
if [ ! -w /dev/fuse ]; then
|
||||
echo "SKIPPING virt-sysprep test, because there is no /dev/fuse."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
rm -f test.img guestfish
|
||||
|
||||
qemu-img create -f qcow2 -o backing_file=../tests/guests/fedora.img test.img
|
||||
|
||||
# Provide alternate 'virt-inspector' and 'guestmount' binaries
|
||||
# that run the just-built programs.
|
||||
|
||||
cat <<'EOF' > virt-inspector
|
||||
#!/bin/sh -
|
||||
../run ../inspector/virt-inspector "$@"
|
||||
EOF
|
||||
chmod +x virt-inspector
|
||||
cat <<'EOF' > guestmount
|
||||
#!/bin/sh -
|
||||
../run ../fuse/guestmount "$@"
|
||||
EOF
|
||||
chmod +x guestmount
|
||||
|
||||
PATH=.:$PATH
|
||||
|
||||
./virt-sysprep -a test.img
|
||||
|
||||
rm -f test.img virt-inspector guestmount
|
||||
398
clone/virt-sysprep.in
Normal file
@@ -0,0 +1,398 @@
|
||||
#!/bin/bash -
|
||||
# @configure_input@
|
||||
# libguestfs virt-sysprep tool
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
unset CDPATH
|
||||
program="virt-sysprep"
|
||||
version="@PACKAGE_VERSION@"
|
||||
|
||||
# Uncomment this to see every shell command that is executed.
|
||||
#set -x
|
||||
|
||||
TEMP=`getopt \
|
||||
-o a:c:d:vVx \
|
||||
--long help,add:,connect:,domain:,enable:,format::,hostname:,list-operations,selinux-relabel,no-selinux-relabel,verbose,version \
|
||||
-n $program -- "$@"`
|
||||
if [ $? != 0 ]; then
|
||||
echo "$program: problem parsing the command line arguments"
|
||||
exit 1
|
||||
fi
|
||||
eval set -- "$TEMP"
|
||||
|
||||
# This array accumulates the arguments we pass through to guestmount.
|
||||
declare -a params
|
||||
i=0
|
||||
|
||||
verbose=
|
||||
add_params=0
|
||||
enable=
|
||||
hostname_param=localhost.localdomain
|
||||
selinux_relabel=auto
|
||||
|
||||
usage ()
|
||||
{
|
||||
echo "Usage:"
|
||||
echo " $program [--options] -d domname"
|
||||
echo " $program [--options] -a disk.img [-a disk.img ...]"
|
||||
echo
|
||||
echo "Read $program(1) man page for more information."
|
||||
echo
|
||||
echo "NOTE: $program modifies the guest or disk image *in place*."
|
||||
exit $1
|
||||
}
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
-a|--add)
|
||||
params[i++]="-a"
|
||||
params[i++]="$2"
|
||||
((add_params++))
|
||||
shift 2;;
|
||||
-c|--connect)
|
||||
params[i++]="-c"
|
||||
params[i++]="$2"
|
||||
shift 2;;
|
||||
-d|--domain)
|
||||
params[i++]="-d"
|
||||
params[i++]="$2"
|
||||
((add_params++))
|
||||
shift 2;;
|
||||
--enable)
|
||||
if [ -n "$enable" ]; then
|
||||
echo "error: --enable option can only be given once"
|
||||
exit 1
|
||||
fi
|
||||
enable="$2"
|
||||
shift 2;;
|
||||
--format)
|
||||
if [ -n "$2" ]; then
|
||||
params[i++]="--format=$2"
|
||||
else
|
||||
params[i++]="--format"
|
||||
fi
|
||||
shift 2;;
|
||||
--help)
|
||||
usage 0;;
|
||||
--hostname)
|
||||
hostname_param="$2"
|
||||
shift 2;;
|
||||
--list-operations)
|
||||
enable=list
|
||||
shift;;
|
||||
--selinux-relabel)
|
||||
selinux_relabel=yes
|
||||
shift;;
|
||||
--no-selinux-relabel)
|
||||
selinux_relabel=no
|
||||
shift;;
|
||||
-v|--verbose)
|
||||
params[i++]="-v"
|
||||
verbose=yes
|
||||
shift;;
|
||||
-V|--version)
|
||||
echo "$program $version"
|
||||
exit 0;;
|
||||
-x)
|
||||
# Can't pass the -x option directly to guestmount because
|
||||
# that stops guestmount from forking, which means we can't
|
||||
# coordinate with guestmount when it has finished
|
||||
# initializing. So instead set just the underlying option
|
||||
# in libguestfs by exporting LIBGUESTFS_TRACE.
|
||||
# Unfortunately (a) this omits FUSE calls, but don't worry
|
||||
# about that for now, and more importantly (b) trace
|
||||
# messages disappear into never-never land after the fork.
|
||||
export LIBGUESTFS_TRACE=1
|
||||
shift;;
|
||||
--)
|
||||
shift
|
||||
break;;
|
||||
*)
|
||||
echo "Internal error!"
|
||||
exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Different sysprep operations that can be enabled. Default is to
|
||||
# enable all of these, although some of them are only done on certain
|
||||
# guest types (see details below).
|
||||
if [ -z "$enable" ]; then
|
||||
cron_spool=yes
|
||||
dhcp_client_state=yes
|
||||
dhcp_server_state=yes
|
||||
hostname=yes
|
||||
logfiles=yes
|
||||
mail_spool=yes
|
||||
net_hwaddr=yes
|
||||
random_seed=yes
|
||||
rhn_systemid=yes
|
||||
smolt_uuid=yes
|
||||
ssh_hostkeys=yes
|
||||
udev_persistent_net=yes
|
||||
utmp=yes
|
||||
yum_uuid=yes
|
||||
elif [ "$enable" = "list" ]; then
|
||||
echo "cron-spool"
|
||||
echo "dhcp-client-state"
|
||||
echo "dhcp-server-state"
|
||||
echo "hostname"
|
||||
echo "logfiles"
|
||||
echo "mail-spool"
|
||||
echo "net-hwaddr"
|
||||
echo "random-seed"
|
||||
echo "rhn-systemid"
|
||||
echo "smolt-uuid"
|
||||
echo "ssh-hostkeys"
|
||||
echo "udev-persistent-net"
|
||||
echo "utmp"
|
||||
echo "yum-uuid"
|
||||
exit 0
|
||||
else
|
||||
for opt in $(echo "$enable" | sed 's/,/ /g'); do
|
||||
case "$opt" in
|
||||
cron-spool) cron_spool=yes ;;
|
||||
dhcp-client-state) dhcp_client_state=yes ;;
|
||||
dhcp-server-state) dhcp_server_state=yes ;;
|
||||
hostname) hostname=yes ;;
|
||||
logfiles) logfiles=yes ;;
|
||||
mail-spool) mail_spool=yes ;;
|
||||
net-hwaddr) net_hwaddr=yes ;;
|
||||
random-seed) random_seed=yes ;;
|
||||
rhn-systemid) rhn_systemid=yes ;;
|
||||
smolt-uuid) smolt_uuid=yes ;;
|
||||
ssh-hostkeys) ssh_hostkeys=yes ;;
|
||||
udev-persistent-net) udev_persistent_net=yes ;;
|
||||
utmp) utmp=yes ;;
|
||||
yum-uuid) yum_uuid=yes ;;
|
||||
*)
|
||||
echo "error: unknown --enable feature: $opt"
|
||||
exit 1
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
# Make sure there were no extra parameters on the command line.
|
||||
if [ $# -gt 0 ]; then
|
||||
echo "error: $program: extra parameters on the command line"
|
||||
echo
|
||||
usage 1
|
||||
fi
|
||||
|
||||
# Did the user specify at least one -a or -d option?
|
||||
if [ $add_params -eq 0 ]; then
|
||||
echo "error: $program: you need at least one -a or -d option"
|
||||
echo
|
||||
usage 1
|
||||
fi
|
||||
|
||||
# end of command line parsing
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$verbose" = "yes" ]; then
|
||||
echo params: "${params[@]}"
|
||||
fi
|
||||
|
||||
# Create a temporary directory for general purpose use during operations.
|
||||
tmpdir="$(mktemp -d)"
|
||||
|
||||
cleanup ()
|
||||
{
|
||||
if [ -d $tmpdir/mnt ]; then
|
||||
fusermount -u $tmpdir/mnt >/dev/null 2>&1 ||:
|
||||
fi
|
||||
rm -rf $tmpdir ||:
|
||||
}
|
||||
trap cleanup EXIT ERR
|
||||
|
||||
# Run virt-inspector and grab inspection information about this guest.
|
||||
virt-inspector "${params[@]}" > $tmpdir/xml
|
||||
virt-inspector --xpath \
|
||||
"string(/operatingsystems/operatingsystem[position()=1]/name)" \
|
||||
< $tmpdir/xml > $tmpdir/type
|
||||
virt-inspector --xpath \
|
||||
"string(/operatingsystems/operatingsystem[position()=1]/distro)" \
|
||||
< $tmpdir/xml > $tmpdir/distro ||:
|
||||
virt-inspector --xpath \
|
||||
"string(/operatingsystems/operatingsystem[position()=1]/package_format)" \
|
||||
< $tmpdir/xml > $tmpdir/package_format ||:
|
||||
virt-inspector --xpath \
|
||||
"string(/operatingsystems/operatingsystem[position()=1]/package_management)" \
|
||||
< $tmpdir/xml > $tmpdir/package_management ||:
|
||||
|
||||
type="$(cat $tmpdir/type)"
|
||||
distro="$(cat $tmpdir/distro)"
|
||||
package_format="$(cat $tmpdir/package_format)"
|
||||
package_management="$(cat $tmpdir/package_management)"
|
||||
|
||||
# Mount the disk.
|
||||
mkdir $tmpdir/mnt
|
||||
guestmount --rw -i "${params[@]}" $tmpdir/mnt
|
||||
|
||||
mnt="$tmpdir/mnt"
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# The sysprep operations.
|
||||
|
||||
if [ "$cron_spool" = "yes" ]; then
|
||||
rm -rf $mnt/var/spool/cron/*
|
||||
fi
|
||||
|
||||
if [ "$dhcp_client_state" = "yes" ]; then
|
||||
case "$type" in
|
||||
linux)
|
||||
rm -rf $mnt/var/lib/dhclient/*
|
||||
# RHEL 3:
|
||||
rm -rf $mnt/var/lib/dhcp/*
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$dhcp_server_state" = "yes" ]; then
|
||||
case "$type" in
|
||||
linux)
|
||||
rm -rf $mnt/var/lib/dhcpd/*
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$hostname" = "yes" ]; then
|
||||
case "$type/$distro" in
|
||||
linux/fedora)
|
||||
echo "HOSTNAME=$hostname_param" > $mnt/etc/sysconfig/network.new
|
||||
sed '/^HOSTNAME=/d' < $mnt/etc/sysconfig/network >> $mnt/etc/sysconfig/network.new
|
||||
mv -f $mnt/etc/sysconfig/network.new $mnt/etc/sysconfig/network
|
||||
created_files=yes
|
||||
;;
|
||||
linux/debian|linux/ubuntu)
|
||||
echo "$hostname_param" > $mnt/etc/hostname
|
||||
created_files=yes
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$logfiles" = "yes" ]; then
|
||||
case "$type" in
|
||||
linux)
|
||||
rm -rf $mnt/var/log/*.log*
|
||||
rm -rf $mnt/var/log/audit/*
|
||||
rm -rf $mnt/var/log/btmp*
|
||||
rm -rf $mnt/var/log/cron*
|
||||
rm -rf $mnt/var/log/dmesg*
|
||||
rm -rf $mnt/var/log/lastlog*
|
||||
rm -rf $mnt/var/log/maillog*
|
||||
rm -rf $mnt/var/log/mail/*
|
||||
rm -rf $mnt/var/log/messages*
|
||||
rm -rf $mnt/var/log/secure*
|
||||
rm -rf $mnt/var/log/spooler*
|
||||
rm -rf $mnt/var/log/tallylog*
|
||||
rm -rf $mnt/var/log/wtmp*
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$mail_spool" = "yes" ]; then
|
||||
rm -rf $mnt/var/spool/mail/*
|
||||
rm -rf $mnt/var/mail/*
|
||||
fi
|
||||
|
||||
if [ "$net_hwaddr" = "yes" ]; then
|
||||
case "$type/$distro" in
|
||||
linux/fedora)
|
||||
if [ -d $mnt/etc/sysconfig/network-scripts ]; then
|
||||
rm_hwaddr ()
|
||||
{
|
||||
sed '/^HWADDR=/d' < "$1" > "$1.new"
|
||||
mv -f "$1.new" "$1"
|
||||
}
|
||||
export -f rm_hwaddr
|
||||
find $mnt/etc/sysconfig/network-scripts \
|
||||
-name 'ifcfg-*' -type f \
|
||||
-exec bash -c 'rm_hwaddr "$0"' {} \;
|
||||
created_files=yes
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$random_seed" = "yes" -a "$type" = "linux" ]; then
|
||||
f=
|
||||
if [ -f $mnt/var/lib/random-seed ]; then
|
||||
# Fedora
|
||||
f=$mnt/var/lib/random-seed
|
||||
elif [ -f $mnt/var/lib/urandom/random-seed ]; then
|
||||
# Debian
|
||||
f=$mnt/var/lib/urandom/random-seed
|
||||
fi
|
||||
if [ -n "$f" ]; then
|
||||
dd if=/dev/urandom of="$f" bs=8 count=1 conv=nocreat,notrunc 2>/dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$rhn_systemid" = "yes" -a "$type/$distro" = "linux/rhel" ]; then
|
||||
rm -f $mnt/etc/sysconfig/rhn/systemid
|
||||
fi
|
||||
|
||||
if [ "$smolt_uuid" = "yes" -a "$type" = "linux" ]; then
|
||||
rm -f $mnt/etc/sysconfig/hw-uuid
|
||||
rm -f $mnt/etc/smolt/uuid
|
||||
rm -f $mnt/etc/smolt/hw-uuid
|
||||
fi
|
||||
|
||||
if [ "$ssh_hostkeys" = "yes" -a "$type" != "windows" ]; then
|
||||
rm -rf $mnt/etc/ssh/*_host_*
|
||||
fi
|
||||
|
||||
if [ "$udev_persistent_net" = "yes" -a "$type" = "linux" ]; then
|
||||
rm -f $mnt/etc/udev/rules.d/70-persistent-net.rules
|
||||
fi
|
||||
|
||||
if [ "$utmp" = "yes" -a "$type" != "windows" ]; then
|
||||
rm -f $mnt/var/run/utmp
|
||||
fi
|
||||
|
||||
if [ "$yum_uuid" = "yes" -a "$package_management" = "yum" ]; then
|
||||
rm -f $mnt/var/lib/yum/uuid
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Clean up and close down.
|
||||
|
||||
# If we created any new files and the guest uses SELinux, then we have
|
||||
# to relabel the filesystem on boot. Could do with a better way to
|
||||
# test "guest uses SELinux" (XXX).
|
||||
case "$selinux_relabel/$created_files" in
|
||||
yes/*)
|
||||
touch $mnt/.autorelabel;;
|
||||
auto/yes)
|
||||
case "$type/$distro" in
|
||||
linux/fedora|linux/rhel|linux/centos|linux/scientificlinux|linux/redhat-based)
|
||||
touch $mnt/.autorelabel
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
sync
|
||||
|
||||
fusermount -u $tmpdir/mnt
|
||||
rm -rf $tmpdir
|
||||
|
||||
trap - EXIT ERR
|
||||
|
||||
exit 0
|
||||
521
clone/virt-sysprep.pod
Executable file
@@ -0,0 +1,521 @@
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
virt-sysprep - Reset or unconfigure a virtual machine so clones can be made
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
virt-sysprep [--options] -d domname
|
||||
|
||||
virt-sysprep [--options] -a disk.img [-a disk.img ...]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Virt-sysprep "resets" or "unconfigures" a virtual machine so that
|
||||
clones can be made from it. Steps in this process include removing
|
||||
SSH host keys, removing persistent network MAC configuration, and
|
||||
removing user accounts. Each step can be enabled or disabled as
|
||||
required.
|
||||
|
||||
Virt-sysprep is a simple shell script, allowing easy inspection or
|
||||
customization by the system administrator.
|
||||
|
||||
Virt-sysprep modifies the guest or disk image I<in place>. The guest
|
||||
must be shut down. If you want to preserve the existing contents of
|
||||
the guest, you I<must copy or clone the disk first>.
|
||||
See L</COPYING AND CLONING> below.
|
||||
|
||||
You do I<not> need to run virt-sysprep as root. In fact we'd
|
||||
generally recommend that you don't. The time you might want to run it
|
||||
as root is when you need root in order to access the disk image, but
|
||||
even in this case it would be better to change the permissions on the
|
||||
disk image to be writable as the non-root user running virt-sysprep.
|
||||
|
||||
"Sysprep" stands for "system preparation" tool. The name comes from
|
||||
the Microsoft program C<sysprep.exe> which is used to unconfigure
|
||||
Windows machines in preparation for cloning them. Having said that,
|
||||
virt-sysprep does I<not> currently work on Microsoft Windows guests.
|
||||
We plan to support Windows sysprepping in a future version, and we
|
||||
already have code to do it.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<--help>
|
||||
|
||||
Display brief help.
|
||||
|
||||
=item B<-a> file
|
||||
|
||||
=item B<--add> file
|
||||
|
||||
Add I<file> which should be a disk image from a virtual machine.
|
||||
|
||||
The format of the disk image is auto-detected. To override this and
|
||||
force a particular format use the I<--format=..> option.
|
||||
|
||||
=item B<-c> URI
|
||||
|
||||
=item B<--connect> URI
|
||||
|
||||
If using libvirt, connect to the given I<URI>. If omitted, then we
|
||||
connect to the default libvirt hypervisor.
|
||||
|
||||
If you specify guest block devices directly (I<-a>), then libvirt is
|
||||
not used at all.
|
||||
|
||||
=item B<-d> guest
|
||||
|
||||
=item B<--domain> guest
|
||||
|
||||
Add all the disks from the named libvirt guest. Domain UUIDs can be
|
||||
used instead of names.
|
||||
|
||||
=item B<--enable=...>
|
||||
|
||||
Choose which sysprep operations to perform. Give a comma-separated
|
||||
list of operations, for example:
|
||||
|
||||
--enable=ssh-hostkeys,udev-persistent-net
|
||||
|
||||
would enable ONLY C<ssh-hostkeys> and C<udev-persistent-net> operations.
|
||||
|
||||
If the I<--enable> option is not given, then we default to trying all
|
||||
possible sysprep operations. But some sysprep operations are skipped
|
||||
for some guest types.
|
||||
|
||||
Use I<--list-operations> to list operations supported by a particular
|
||||
version of virt-sysprep.
|
||||
|
||||
See L</OPERATIONS> below for a list and an explanation of each
|
||||
operation.
|
||||
|
||||
=item B<--format=raw|qcow2|..>
|
||||
|
||||
=item B<--format>
|
||||
|
||||
The default for the I<-a> option is to auto-detect the format of the
|
||||
disk image. Using this forces the disk format for I<-a> options which
|
||||
follow on the command line. Using I<--format> with no argument
|
||||
switches back to auto-detection for subsequent I<-a> options.
|
||||
|
||||
For example:
|
||||
|
||||
virt-sysprep --format=raw -a disk.img
|
||||
|
||||
forces raw format (no auto-detection) for C<disk.img>.
|
||||
|
||||
virt-sysprep --format=raw -a disk.img --format -a another.img
|
||||
|
||||
forces raw format (no auto-detection) for C<disk.img> and reverts to
|
||||
auto-detection for C<another.img>.
|
||||
|
||||
If you have untrusted raw-format guest disk images, you should use
|
||||
this option to specify the disk format. This avoids a possible
|
||||
security problem with malicious guests (CVE-2010-3851).
|
||||
|
||||
=item B<--hostname> newhostname
|
||||
|
||||
Change the hostname. See the L</hostname> operation below.
|
||||
If not given, defaults to C<localhost.localdomain>.
|
||||
|
||||
=item B<--list-operations>
|
||||
|
||||
List the operations supported by the virt-sysprep program.
|
||||
|
||||
=item B<--selinux-relabel>
|
||||
|
||||
=item B<--no-selinux-relabel>
|
||||
|
||||
I<--selinux-relabel> forces SELinux relabelling next time the guest
|
||||
boots. I<--no-selinux-relabel> disables relabelling.
|
||||
|
||||
The default is to try to detect if SELinux relabelling is required.
|
||||
See L</SELINUX RELABELLING> below for more details.
|
||||
|
||||
=item B<-v>
|
||||
|
||||
=item B<--verbose>
|
||||
|
||||
Enable verbose messages for debugging.
|
||||
|
||||
=item B<-V>
|
||||
|
||||
=item B<--version>
|
||||
|
||||
Display version number and exit.
|
||||
|
||||
=item B<-x>
|
||||
|
||||
Enable tracing of libguestfs API calls.
|
||||
|
||||
=back
|
||||
|
||||
=head1 OPERATIONS
|
||||
|
||||
If the I<--enable> option is I<not> given, then
|
||||
I<all sysprep operations are enabled>, although some are skipped
|
||||
depending on the type of guest.
|
||||
|
||||
Operations can be individually enabled using the I<--enable> option.
|
||||
Use a comma-separated list, for example:
|
||||
|
||||
virt-sysprep --enable=ssh-hostkeys,udev-persistent-net [etc..]
|
||||
|
||||
To list the operations supported by the current version of
|
||||
virt-sysprep, use I<--list-operations>.
|
||||
|
||||
Future versions of virt-sysprep may add more operations. If you are
|
||||
using virt-sysprep and want predictable behaviour, specify only the
|
||||
operations that you want to have enabled.
|
||||
|
||||
=head2 cron-spool
|
||||
|
||||
Remove user at-jobs and cron-jobs.
|
||||
|
||||
=head2 dhcp-client-state
|
||||
|
||||
Remove DHCP client leases.
|
||||
|
||||
=head2 dhcp-server-state
|
||||
|
||||
Remove DHCP server leases.
|
||||
|
||||
=head2 hostname
|
||||
|
||||
Changes the hostname of the guest to the value given in the
|
||||
I<--hostname> parameter.
|
||||
|
||||
If the I<--hostname> parameter is not given, then the hostname is
|
||||
changed to C<localhost.localdomain>.
|
||||
|
||||
=head2 logfiles
|
||||
|
||||
Remove many log files.
|
||||
|
||||
=head2 mail-spool
|
||||
|
||||
Remove email from the local mail spool directory.
|
||||
|
||||
=head2 net-hwaddr
|
||||
|
||||
Remove HWADDR (hard-coded MAC address) configuration. For Fedora and
|
||||
Red Hat Enterprise Linux, this is removed from C<ifcfg-*> files.
|
||||
|
||||
=head2 random-seed
|
||||
|
||||
Write some random bytes from the host into the random seed file of
|
||||
the guest.
|
||||
|
||||
See L</RANDOM SEED> below.
|
||||
|
||||
=head2 rhn-systemid
|
||||
|
||||
Remove the RHN system ID.
|
||||
|
||||
=head2 smolt-uuid
|
||||
|
||||
Remove the Smolt hardware UUID.
|
||||
|
||||
=head2 ssh-hostkeys
|
||||
|
||||
Remove the SSH host keys in the guest.
|
||||
|
||||
The SSH host keys are regenerated (differently) next time the guest is
|
||||
booted.
|
||||
|
||||
If, after cloning, the guest gets the same IP address, ssh will give
|
||||
you a stark warning about the host key changing:
|
||||
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
|
||||
|
||||
=head2 udev-persistent-net
|
||||
|
||||
Remove udev persistent net rules which map the guest's existing MAC
|
||||
address to a fixed ethernet device (eg. eth0).
|
||||
|
||||
After a guest is cloned, the MAC address usually changes. Since the
|
||||
old MAC address occupies the old name (eg. eth0), this means the fresh
|
||||
MAC address is assigned to a new name (eg. eth1) and this is usually
|
||||
undesirable. Erasing the udev persistent net rules avoids this.
|
||||
|
||||
=head2 utmp
|
||||
|
||||
Remove the utmp file.
|
||||
|
||||
This records who is currently logged in on a machine. In modern Linux
|
||||
distros it is stored in a ramdisk and hence not part of the virtual
|
||||
machine's disk, but it was stored on disk in older distros.
|
||||
|
||||
=head2 yum-uuid
|
||||
|
||||
Remove the yum UUID.
|
||||
|
||||
Yum creates a fresh UUID the next time it runs when it notices that
|
||||
the original UUID has been erased.
|
||||
|
||||
=head1 COPYING AND CLONING
|
||||
|
||||
Virt-sysprep can be used as part of a process of cloning guests, or to
|
||||
prepare a template from which guests can be cloned. There are many
|
||||
different ways to achieve this using the virt tools, and this section
|
||||
is just an introduction.
|
||||
|
||||
A virtual machine (when switched off) consists of two parts:
|
||||
|
||||
=over 4
|
||||
|
||||
=item I<configuration>
|
||||
|
||||
The configuration or description of the guest. eg. The libvirt
|
||||
XML (see C<virsh dumpxml>), the running configuration of the guest,
|
||||
or another external format like OVF.
|
||||
|
||||
Some configuration items that might need to be changed:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
name
|
||||
|
||||
=item *
|
||||
|
||||
UUID
|
||||
|
||||
=item *
|
||||
|
||||
path to block device(s)
|
||||
|
||||
=item *
|
||||
|
||||
network card MAC address
|
||||
|
||||
=back
|
||||
|
||||
=item I<block device(s)>
|
||||
|
||||
One or more hard disk images, themselves containing files,
|
||||
directories, applications, kernels, configuration, etc.
|
||||
|
||||
Some things inside the block devices that might need to be changed:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
hostname and other net configuration
|
||||
|
||||
=item *
|
||||
|
||||
UUID
|
||||
|
||||
=item *
|
||||
|
||||
SSH host keys
|
||||
|
||||
=item *
|
||||
|
||||
Windows unique security ID (SID)
|
||||
|
||||
=item *
|
||||
|
||||
Puppet registration
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
||||
=head2 COPYING THE BLOCK DEVICE
|
||||
|
||||
Starting with an original guest, you probably wish to copy the guest
|
||||
block device and its configuration to make a template. Then once you
|
||||
are happy with the template, you will want to make many clones from
|
||||
it.
|
||||
|
||||
virt-sysprep
|
||||
|
|
||||
v
|
||||
original guest --------> template ---------->
|
||||
\------> cloned
|
||||
\-----> guests
|
||||
\---->
|
||||
|
||||
You can, of course, just copy the block device on the host using
|
||||
L<cp(1)> or L<dd(1)>.
|
||||
|
||||
dd dd
|
||||
original guest --------> template ---------->
|
||||
\------> cloned
|
||||
\-----> guests
|
||||
\---->
|
||||
|
||||
There are some smarter (and faster) ways too:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
snapshot
|
||||
template ---------->
|
||||
\------> cloned
|
||||
\-----> guests
|
||||
\---->
|
||||
|
||||
Use the block device as a backing file and create a snapshot on top
|
||||
for each guest. The advantage is that you don't need to copy the
|
||||
block device (very fast) and only changes are stored (less storage
|
||||
required).
|
||||
|
||||
Note that writing to the backing file once you have created guests on
|
||||
top of it is not possible: you will corrupt the guests.
|
||||
|
||||
Tools that can do this include:
|
||||
L<qemu-img(1)> (with the I<create -f qcow2 -o backing_file> option),
|
||||
L<lvcreate(8)> (I<--snapshot> option). Some filesystems (such as
|
||||
btrfs) and most Network Attached Storage devices can also create cheap
|
||||
snapshots from files or LUNs.
|
||||
|
||||
=item *
|
||||
|
||||
Get your NAS to snapshot and/or duplicate the LUN.
|
||||
|
||||
=item *
|
||||
|
||||
Prepare your template using L<virt-sparsify(1)>. See below.
|
||||
|
||||
=back
|
||||
|
||||
=head2 VIRT-CLONE
|
||||
|
||||
A separate tool, L<virt-clone(1)>, can be used to duplicate the block
|
||||
device and/or modify the external libvirt configuration of a guest.
|
||||
It will reset the name, UUID and MAC address of the guest in the
|
||||
libvirt XML.
|
||||
|
||||
L<virt-clone(1)> does not use libguestfs and cannot look inside the
|
||||
disk image. This was the original motivation to write virt-sysprep.
|
||||
|
||||
=head2 SPARSIFY
|
||||
|
||||
virt-sparsify
|
||||
original guest --------> template
|
||||
|
||||
L<virt-sparsify(1)> can be used to make the cloning template smaller,
|
||||
making it easier to compress and/or faster to copy.
|
||||
|
||||
Notice that since virt-sparsify also copies the image, you can use it
|
||||
to make the initial copy (instead of C<dd>).
|
||||
|
||||
=head2 RESIZE
|
||||
|
||||
virt-resize
|
||||
template ---------->
|
||||
\------> cloned
|
||||
\-----> guests
|
||||
\---->
|
||||
|
||||
If you want to give people cloned guests, but let them pick the size
|
||||
of the guest themselves (eg. depending on how much they are prepared
|
||||
to pay for disk space), then instead of copying the template, you can
|
||||
run L<virt-resize(1)>. Virt-resize performs a copy and resize, and
|
||||
thus is ideal for cloning guests from a template.
|
||||
|
||||
=head1 SECURITY
|
||||
|
||||
Although virt-sysprep removes some sensitive information from the
|
||||
guest, it does not pretend to remove all of it. You should examine
|
||||
the L</OPERATIONS> above, and the implementation of the operations in
|
||||
the shell script. You should also examine the guest afterwards.
|
||||
|
||||
Sensitive files are simply removed. The data they contained may still
|
||||
exist on the disk, easily recovered with a hex editor or undelete
|
||||
tool. Use L<virt-sparsify(1)> as one way to remove this content. See
|
||||
also the L<scrub(1)> command to get rid of deleted content in
|
||||
directory entries and inodes.
|
||||
|
||||
=head2 RANDOM SEED
|
||||
|
||||
I<(This section applies to Linux guests only)>
|
||||
|
||||
The virt-sysprep C<random-seed> operation writes a few bytes of
|
||||
randomness from the host into the guest's random seed file.
|
||||
|
||||
If this is just done once and the guest is cloned from the same
|
||||
template, then each guest will start with the same entropy, and things
|
||||
like SSH host keys and TCP sequence numbers may be predictable.
|
||||
|
||||
Therefore you should arrange to add more randomness I<after> cloning
|
||||
from a template too, which can be done by just enabling the
|
||||
C<random-seed> operation:
|
||||
|
||||
cp template.img newguest.img
|
||||
virt-sysprep --enable=random-seed -a newguest.img
|
||||
|
||||
=head2 SELINUX RELABELLING
|
||||
|
||||
I<(This section applies to Linux guests using SELinux only)>
|
||||
|
||||
If any new files are created by virt-sysprep, then virt-sysprep
|
||||
touches C</.autorelabel> so that these will be correctly labelled by
|
||||
SELinux the next time the guest is booted. This process interrupts
|
||||
boot and can take some time.
|
||||
|
||||
You can force relabelling for all guests by supplying the
|
||||
I<--selinux-relabel> option.
|
||||
|
||||
You can disable relabelling entirely by supplying the
|
||||
I<--no-selinux-relabel> option.
|
||||
|
||||
=head1 SHELL QUOTING
|
||||
|
||||
Libvirt guest names can contain arbitrary characters, some of which
|
||||
have meaning to the shell such as C<#> and space. You may need to
|
||||
quote or escape these characters on the command line. See the shell
|
||||
manual page L<sh(1)> for details.
|
||||
|
||||
=head1 EXIT STATUS
|
||||
|
||||
This program returns 0 on success, or 1 if there was an error.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<guestfs(3)>,
|
||||
L<guestfish(1)>,
|
||||
L<virt-clone(1)>,
|
||||
L<virt-rescue(1)>,
|
||||
L<virt-resize(1)>,
|
||||
L<virt-sparsify(1)>,
|
||||
L<virsh(1)>,
|
||||
L<lvcreate(8)>,
|
||||
L<qemu-img(1)>,
|
||||
L<scrub(1)>,
|
||||
L<http://libguestfs.org/>,
|
||||
L<http://libvirt.org/>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
203
configure.ac
@@ -13,14 +13,14 @@
|
||||
#
|
||||
# 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.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
# major/minor/release must be numbers
|
||||
# The major, minor, and release fields MUST be numbers. Packagers can
|
||||
# add extra information using --with-extra="..." which may be any
|
||||
# freeform string.
|
||||
m4_define([libguestfs_major], [1])
|
||||
m4_define([libguestfs_minor], [13])
|
||||
m4_define([libguestfs_release], [6])
|
||||
# extra can be any string
|
||||
m4_define([libguestfs_extra], [])
|
||||
m4_define([libguestfs_minor], [15])
|
||||
m4_define([libguestfs_release], [17])
|
||||
|
||||
AC_INIT([libguestfs],libguestfs_major.libguestfs_minor.libguestfs_release)
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
@@ -31,12 +31,6 @@ AM_SILENT_RULES([yes]) # make --enable-silent-rules the default.
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
dnl Split up the version string.
|
||||
AC_DEFINE([PACKAGE_VERSION_MAJOR],[libguestfs_major],[Major version number])
|
||||
AC_DEFINE([PACKAGE_VERSION_MINOR],[libguestfs_minor],[Minor version number])
|
||||
AC_DEFINE([PACKAGE_VERSION_RELEASE],[libguestfs_release],[Release number])
|
||||
AC_DEFINE([PACKAGE_VERSION_EXTRA],["libguestfs_extra"],[Extra version string])
|
||||
|
||||
dnl Stable or unstable version?
|
||||
AC_MSG_CHECKING([if this is a stable or unstable branch of libguestfs])
|
||||
AS_IF([test "$((libguestfs_minor % 2))" -eq 0 ],[
|
||||
@@ -53,12 +47,30 @@ please see the section "LIBGUESTFS VERSION NUMBERS" in guestfs(3).
|
||||
***])
|
||||
])
|
||||
|
||||
dnl Extra string, a freeform string defined by packagers.
|
||||
AC_ARG_WITH([extra],
|
||||
[AS_HELP_STRING([--with-extra],
|
||||
[extra version string (for use by packagers)])],
|
||||
[libguestfs_extra="$withval"],
|
||||
[libguestfs_extra=]
|
||||
)
|
||||
|
||||
AC_MSG_NOTICE([libguestfs version libguestfs_major.libguestfs_minor.libguestfs_release$libguestfs_extra])
|
||||
|
||||
dnl Split up the version string.
|
||||
AC_DEFINE([PACKAGE_VERSION_MAJOR],[libguestfs_major],[Major version number])
|
||||
AC_DEFINE([PACKAGE_VERSION_MINOR],[libguestfs_minor],[Minor version number])
|
||||
AC_DEFINE([PACKAGE_VERSION_RELEASE],[libguestfs_release],[Release number])
|
||||
AC_DEFINE_UNQUOTED([PACKAGE_VERSION_EXTRA],["$libguestfs_extra"],[Extra version string])
|
||||
|
||||
dnl Early gnulib initialization.
|
||||
gl_EARLY
|
||||
gl_INIT
|
||||
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_PROG_SED
|
||||
|
||||
dnl Check for basic C environment.
|
||||
AC_PROG_CC_STDC
|
||||
AC_PROG_INSTALL
|
||||
@@ -109,6 +121,9 @@ if test "$gl_gcc_warnings" = yes; then
|
||||
# failures (seen on Ubuntu).
|
||||
nw="$nw -Wmissing-noreturn" # Don't warn about missed noreturn funcs
|
||||
# (seen on Ubuntu).
|
||||
nw="$nw -Wsuggest-attribute=pure" # Don't suggest pure functions.
|
||||
nw="$nw -Wsuggest-attribute=const" # Don't suggest const functions.
|
||||
nw="$nw -Wunsuffixed-float-constants" # Don't care about these.
|
||||
|
||||
gl_MANYWARN_ALL_GCC([ws])
|
||||
gl_MANYWARN_COMPLEMENT([ws], [$ws], [$nw])
|
||||
@@ -126,6 +141,10 @@ if test "$gl_gcc_warnings" = yes; then
|
||||
# Work around warning in src/inspect.c. This seems to be a bug in gcc 4.5.1.
|
||||
gl_WARN_ADD([-Wno-strict-overflow])
|
||||
|
||||
# Missing field initializers is not a bug in C. Adding this to $nw above
|
||||
# did not work, so force it here instead.
|
||||
gl_WARN_ADD([-Wno-missing-field-initializers])
|
||||
|
||||
gl_WARN_ADD([-fdiagnostics-show-option])
|
||||
|
||||
AC_SUBST([WARN_CFLAGS])
|
||||
@@ -147,6 +166,12 @@ VERSION_SCRIPT_FLAGS=-Wl,--version-script=
|
||||
VERSION_SCRIPT_FLAGS="-Wl,-M -Wl,"
|
||||
AC_SUBST(VERSION_SCRIPT_FLAGS)
|
||||
|
||||
dnl Use -fvisibility=hidden by default in the library.
|
||||
dnl http://gcc.gnu.org/wiki/Visibility
|
||||
AS_IF([test -n "$GCC"],
|
||||
[AC_SUBST([GCC_VISIBILITY_HIDDEN], [-fvisibility=hidden])],
|
||||
[AC_SUBST([GCC_VISIBILITY_HIDDEN], [:])])
|
||||
|
||||
dnl Check support for 64 bit file offsets.
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
@@ -300,22 +325,19 @@ AC_CHECK_LIB([portablexdr],[xdrmem_create],[],[
|
||||
AC_SEARCH_LIBS([xdrmem_create],[rpc xdr nsl])
|
||||
])
|
||||
|
||||
dnl Check for Augeas (now optional).
|
||||
AC_CHECK_LIB([augeas],[aug_match],[
|
||||
have_augeas=yes
|
||||
AUGEAS_LIB="-laugeas"
|
||||
dnl Check for Augeas (optional).
|
||||
PKG_CHECK_MODULES([AUGEAS], [augeas],
|
||||
[AC_SUBST([AUGEAS_CFLAGS])
|
||||
AC_SUBST([AUGEAS_LIBS])
|
||||
AC_DEFINE([HAVE_AUGEAS],[1],[Define to 1 if you have Augeas])
|
||||
|
||||
old_LIBS="$LIBS"
|
||||
LIBS="$LIBS $AUGEAS_LIB"
|
||||
dnl Check for functions not available in earlier versions of Augeas.
|
||||
AC_CHECK_FUNCS([aug_load aug_defvar aug_defnode])
|
||||
LIBS="$old_LIBS"
|
||||
|
||||
],[have_augeas=no])
|
||||
if test "x$have_augeas" = "xyes"; then
|
||||
AC_DEFINE([HAVE_AUGEAS],[1],[Define to 1 if you have Augeas])
|
||||
fi
|
||||
AC_SUBST([AUGEAS_LIB])
|
||||
old_LIBS="$LIBS"
|
||||
LIBS="$LIBS $AUGEAS_LIBS"
|
||||
dnl Check for functions not available in earlier versions of Augeas.
|
||||
AC_CHECK_FUNCS([aug_load aug_defvar aug_defnode])
|
||||
LIBS="$old_LIBS"
|
||||
],
|
||||
[AC_MSG_WARN([augeas not found, some core features will be disabled])])
|
||||
|
||||
dnl Check for libselinux (optional).
|
||||
AC_CHECK_HEADERS([selinux/selinux.h])
|
||||
@@ -334,6 +356,11 @@ if test "x$have_libselinux" = "xyes"; then
|
||||
fi
|
||||
AC_SUBST([SELINUX_LIB])
|
||||
|
||||
dnl Check for systemtap/DTrace userspace probes (optional).
|
||||
dnl http://sourceware.org/systemtap/wiki/AddingUserSpaceProbingToApps
|
||||
AC_CHECK_HEADERS([sys/sdt.h])
|
||||
dnl AC_CHECK_PROG([DTRACE],[dtrace],[dtrace],[no])
|
||||
|
||||
dnl Check for cpio which isn't in the default Pardus install amazingly.
|
||||
AC_CHECK_PROG([CPIO],[cpio],[cpio],[no])
|
||||
test "x$CPIO" = "xno" &&
|
||||
@@ -429,8 +456,53 @@ working.
|
||||
])
|
||||
fi
|
||||
|
||||
dnl qemu 0.15 was released with broken support for '-machine',
|
||||
dnl requiring you to add the machine type: '-machine pc,[...]'.
|
||||
dnl The problem is that 'pc' is only applicable for PC-like
|
||||
dnl hardware, so we cannot do this as a general solution. Since
|
||||
dnl qemu 0.15, this problem has been fixed so now the default
|
||||
dnl machine type is chosen (qemu commit 2645c6dcaf6ea2a51a).
|
||||
dnl
|
||||
dnl We need to work out if this qemu is the broken version, so we
|
||||
dnl can add 'pc' just for this broken version.
|
||||
dnl
|
||||
dnl Note that old qemu didn't support the '-machine' option at all.
|
||||
dnl
|
||||
dnl We use the -kernel option for testing this, because this option
|
||||
dnl is processed very late, after qemu has set up the machine.
|
||||
AC_MSG_CHECKING([for broken '-machine accel=tcg' option in $QEMU])
|
||||
LC_ALL=C $QEMU -nographic -machine accel=tcg -kernel /NO_SUCH_FILE \
|
||||
> config1.tmp 2>&1
|
||||
LC_ALL=C $QEMU -nographic -machine pc,accel=tcg -kernel /NO_SUCH_FILE \
|
||||
> config2.tmp 2>&1
|
||||
if cmp -s config1.tmp config2.tmp; then
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([QEMU_MACHINE_TYPE_IS_BROKEN],[1],[qemu -machine accel=tcg option is broken (in qemu 0.15 only)])
|
||||
fi
|
||||
rm config1.tmp config2.tmp
|
||||
|
||||
dnl See if the '-machine [pc,]accel=tcg' option is required in
|
||||
dnl order to run the virtio-serial test below. This happens when
|
||||
dnl we run qemu-kvm inside a VM without forcing TCG:
|
||||
dnl
|
||||
dnl Could not access KVM kernel module: No such file or directory
|
||||
dnl failed to initialize KVM: No such file or directory
|
||||
dnl No accelerator found!
|
||||
AC_MSG_CHECKING([if -machine @<:@pc,@:>@accel=tcg option is required to test virtio-serial feature])
|
||||
if $QEMU -nographic -device \? >/dev/null 2>&1; then
|
||||
:
|
||||
elif $QEMU -machine accel=tcg -nographic -device \? >/dev/null 2>&1; then
|
||||
QEMU_EXTRA_OPTIONS_FOR_TEST="-machine accel=tcg"
|
||||
elif $QEMU -machine pc,accel=tcg -nographic -device \? >/dev/null 2>&1; then
|
||||
QEMU_EXTRA_OPTIONS_FOR_TEST="-machine pc,accel=tcg"
|
||||
# else nothing ... it'll fail below.
|
||||
fi
|
||||
AC_MSG_RESULT([$QEMU_EXTRA_OPTIONS_FOR_TEST])
|
||||
|
||||
AC_MSG_CHECKING([for virtio-serial support in $QEMU])
|
||||
if $QEMU -nographic -device \? 2>&1 | grep -sq virtio-serial; then
|
||||
if $QEMU $QEMU_EXTRA_OPTIONS_FOR_TEST -nographic -device \? 2>&1 | grep -sq virtio-serial; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
@@ -590,14 +662,9 @@ AS_IF([test "x$enable_ocaml" != "xno"],
|
||||
OCAMLFIND=
|
||||
AC_PROG_OCAML
|
||||
AC_PROG_FINDLIB
|
||||
|
||||
AS_IF([test "x$OCAMLC" != "xno" && test "x$OCAMLFIND" != "xno"],
|
||||
[AC_CHECK_OCAML_PKG([pcre])])
|
||||
])
|
||||
AM_CONDITIONAL([HAVE_OCAML],
|
||||
[test "x$OCAMLC" != "xno" && test "x$OCAMLFIND" != "xno"])
|
||||
AM_CONDITIONAL([HAVE_OCAML_PCRE],
|
||||
[test "x$OCAMLC" != "xno" && test "x$OCAMLFIND" != "xno" && test "x$OCAML_PKG_pcre" != "xno"])
|
||||
AM_CONDITIONAL([HAVE_OCAMLDOC],
|
||||
[test "x$OCAMLDOC" != "xno"])
|
||||
|
||||
@@ -647,11 +714,13 @@ AS_IF([test "x$enable_python" != "xno"],
|
||||
|
||||
if test "x$PYTHON" != "xno"; then
|
||||
AC_MSG_CHECKING([Python prefix])
|
||||
PYTHON_PREFIX=`$PYTHON -c "import sys; print sys.prefix"`
|
||||
PYTHON_PREFIX=`$PYTHON -c "import sys; print (sys.prefix)"`
|
||||
AC_MSG_RESULT([$PYTHON_PREFIX])
|
||||
|
||||
AC_MSG_CHECKING([Python version])
|
||||
PYTHON_VERSION=`$PYTHON -c "import sys; print sys.version[[0:3]]"`
|
||||
PYTHON_VERSION_MAJOR=`$PYTHON -c "import sys; print (sys.version_info@<:@0@:>@)"`
|
||||
PYTHON_VERSION_MINOR=`$PYTHON -c "import sys; print (sys.version_info@<:@1@:>@)"`
|
||||
PYTHON_VERSION="$PYTHON_VERSION_MAJOR.$PYTHON_VERSION_MINOR"
|
||||
AC_MSG_RESULT([$PYTHON_VERSION])
|
||||
|
||||
AC_MSG_CHECKING([for Python include path])
|
||||
@@ -679,9 +748,20 @@ AS_IF([test "x$enable_python" != "xno"],
|
||||
AC_MSG_RESULT([$PYTHON_INSTALLDIR])
|
||||
fi
|
||||
|
||||
dnl Look for some optional symbols in libpython.
|
||||
old_LIBS="$LIBS"
|
||||
LIBS="$LIBS -lpython$PYTHON_VERSION"
|
||||
AC_CHECK_FUNCS([PyCapsule_New])
|
||||
|
||||
PYTHON_BLDLIBRARY=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print (distutils.sysconfig.get_config_var('BLDLIBRARY'))"`
|
||||
AC_CHECK_LIB([c],[PyCapsule_New],
|
||||
[AC_DEFINE([HAVE_PYCAPSULE_NEW],1,
|
||||
[Found PyCapsule_New in libpython])],
|
||||
[],[$PYTHON_BLDLIBRARY])
|
||||
AC_CHECK_LIB([c],[PyString_AsString],
|
||||
[AC_DEFINE([HAVE_PYSTRING_ASSTRING],1,
|
||||
[Found PyString_AsString in libpython])],
|
||||
[],[$PYTHON_BLDLIBRARY])
|
||||
|
||||
LIBS="$old_LIBS"
|
||||
fi
|
||||
|
||||
@@ -700,8 +780,10 @@ AC_ARG_ENABLE([ruby],
|
||||
[enable_ruby=yes])
|
||||
AS_IF([test "x$enable_ruby" != "xno"],
|
||||
[
|
||||
AC_CHECK_LIB([ruby],[ruby_init],[HAVE_LIBRUBY=1],[HAVE_LIBRUBY=0])
|
||||
AC_CHECK_PROG([RUBY],[ruby],[ruby],[no])
|
||||
AC_CHECK_PROG([RAKE],[rake],[rake],[no])
|
||||
AC_CHECK_LIB([ruby],[ruby_init],[HAVE_LIBRUBY=1],[HAVE_LIBRUBY=0])
|
||||
AC_SUBST([RAKE])
|
||||
])
|
||||
AM_CONDITIONAL([HAVE_RUBY],
|
||||
[test "x$RAKE" != "xno" && test -n "$HAVE_LIBRUBY"])
|
||||
@@ -874,6 +956,25 @@ AS_IF([test "x$enable_php" != "xno"],
|
||||
])
|
||||
AM_CONDITIONAL([HAVE_PHP], [test "x$PHP" != "xno" && test "x$PHPIZE" != "xno"])
|
||||
|
||||
dnl Erlang
|
||||
ERLANG=no
|
||||
AC_ARG_ENABLE([erlang],
|
||||
AS_HELP_STRING([--disable-erlang], [Disable Erlang language bindings]),
|
||||
[],
|
||||
[enable_erlang=yes])
|
||||
# NB: Don't use AS_IF here: it doesn't work.
|
||||
if test "x$enable_erlang" != "xno"; then
|
||||
ERLANG=
|
||||
AC_ERLANG_PATH_ERLC([no])
|
||||
|
||||
if test "x$ERLC" != "xno"; then
|
||||
AC_ERLANG_CHECK_LIB([erl_interface], [],
|
||||
[AC_MSG_FAILURE([Erlang erl_interface library not installed. Use --disable-erlang to disable.])])
|
||||
AC_ERLANG_SUBST_LIB_DIR
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_ERLANG], [test "x$ERLANG" != "xno" && test "x$ERLC" != "xno"])
|
||||
|
||||
dnl Check for Perl modules needed by Perl virt tools (virt-df, etc.)
|
||||
AS_IF([test "x$PERL" != "xno"],
|
||||
[
|
||||
@@ -907,28 +1008,32 @@ AC_SUBST([LIBTOOL])
|
||||
dnl Produce output files.
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
dnl http://www.mail-archive.com/automake@gnu.org/msg10204.html
|
||||
AC_CONFIG_FILES([clone/virt-sysprep],
|
||||
[chmod +x clone/virt-sysprep])
|
||||
AC_CONFIG_FILES([podwrapper.sh],
|
||||
[chmod +x podwrapper.sh])
|
||||
AC_CONFIG_FILES([run],
|
||||
[chmod +x run])
|
||||
AC_CONFIG_FILES([Makefile
|
||||
align/Makefile
|
||||
appliance/Makefile
|
||||
capitests/Makefile
|
||||
cat/Makefile
|
||||
caution/Makefile
|
||||
clone/Makefile
|
||||
csharp/Makefile
|
||||
daemon/Makefile
|
||||
debian/changelog
|
||||
df/Makefile
|
||||
edit/Makefile
|
||||
erlang/Makefile
|
||||
erlang/examples/Makefile
|
||||
examples/Makefile
|
||||
fish/Makefile
|
||||
format/Makefile
|
||||
fuse/Makefile
|
||||
generator/Makefile
|
||||
gnulib/lib/Makefile
|
||||
gnulib/tests/Makefile
|
||||
haskell/Makefile
|
||||
images/Makefile
|
||||
inspector/Makefile
|
||||
java/Makefile
|
||||
java/examples/Makefile
|
||||
@@ -946,14 +1051,24 @@ AC_CONFIG_FILES([Makefile
|
||||
po/Makefile.in
|
||||
python/Makefile
|
||||
python/examples/Makefile
|
||||
regressions/Makefile
|
||||
rescue/Makefile
|
||||
resize/Makefile
|
||||
ruby/Makefile
|
||||
ruby/Rakefile
|
||||
ruby/examples/Makefile
|
||||
sparsify/Makefile
|
||||
src/Makefile
|
||||
test-tool/Makefile
|
||||
tests/c-api/Makefile
|
||||
tests/data/Makefile
|
||||
tests/extra/Makefile
|
||||
tests/guests/Makefile
|
||||
tests/luks/Makefile
|
||||
tests/lvm/Makefile
|
||||
tests/md/Makefile
|
||||
tests/protocol/Makefile
|
||||
tests/qemu/Makefile
|
||||
tests/regressions/Makefile
|
||||
tools/Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -982,11 +1097,13 @@ echo -n "Haskell bindings .................... "
|
||||
if test "x$HAVE_HASKELL_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo -n "PHP bindings ........................ "
|
||||
if test "x$HAVE_PHP_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo -n "Erlang bindings ..................... "
|
||||
if test "x$HAVE_ERLANG_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo "guestfish and C virt tools .......... yes"
|
||||
echo -n "Perl virt tools ..................... "
|
||||
if test "x$HAVE_TOOLS_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo -n "virt-resize ......................... "
|
||||
if test "x$HAVE_OCAML_TRUE" = "x" && test "x$HAVE_OCAML_PCRE_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
if test "x$HAVE_OCAML_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo "FUSE filesystem ..................... $enable_fuse"
|
||||
echo
|
||||
echo "If any optional component is configured 'no' when you expected 'yes'"
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
Random contributions and things which don't fit in anywhere else
|
||||
----------------------------------------------------------------------
|
||||
|
||||
autobuild/
|
||||
The autobuild script that we use to build and test the
|
||||
tarballs on Debian and elsewhere.
|
||||
|
||||
centos5.3-libguestfs.spec
|
||||
[REMOVED]
|
||||
This used to be a centos5.3 specfile. Please use the specfile
|
||||
@@ -24,6 +28,12 @@ guestfsd-in-wine.sh
|
||||
Run a Windows-compiled guestfsd under Wine. Read the
|
||||
instructions at the top of this file carefully.
|
||||
|
||||
intro/ "Slides" for an intro to libguestfs. This is a short (10-15
|
||||
min) talk that I give to introduce the main features of
|
||||
libguestfs. The slides are in the form of a complete
|
||||
self-contained HTML page with a handful images that can be
|
||||
easily distributed before the talk.
|
||||
|
||||
visualize-alignment/
|
||||
Tests for visualizing block device reads and writes and
|
||||
alignment using a patched qemu. See the README file in that
|
||||
|
||||
109
contrib/autobuild/autobuild.sh
Executable file
@@ -0,0 +1,109 @@
|
||||
#!/bin/bash -
|
||||
# libguestfs autobuild script
|
||||
# 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
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
# This script is used to download and test the latest tarball on
|
||||
# Debian and other platforms. It runs from a cron job and sends email
|
||||
# to the mailing list about the status.
|
||||
|
||||
set -e
|
||||
|
||||
# Subject line of email prefix.
|
||||
prefix="${1:-[autobuild]}"
|
||||
|
||||
# Where we send mail.
|
||||
mailto="rjones@redhat.com"
|
||||
|
||||
# Move to temporary directory for building.
|
||||
tmpdir="$(mktemp -d --tmpdir=/var/tmp)"
|
||||
cd "$tmpdir"
|
||||
|
||||
# The libguestfs index page contains some hidden fields to help us
|
||||
# find the latest version programmatically.
|
||||
version=$(wget --no-cache -O- -q http://libguestfs.org |
|
||||
grep '^LATEST-VERSION:' | awk '{print $2}')
|
||||
url=$(wget --no-cache -O- -q http://libguestfs.org |
|
||||
grep '^LATEST-URL:' | awk '{print $2}')
|
||||
filename=$(basename "$url")
|
||||
directory=$(basename "$url" .tar.gz)
|
||||
|
||||
echo "--------------------------------------------------"
|
||||
echo "prefix $prefix"
|
||||
echo "libguestfs $version"
|
||||
echo "url $url"
|
||||
echo "build dir $tmpdir/$directory"
|
||||
echo "--------------------------------------------------"
|
||||
|
||||
# Grab the latest tarball from upstream.
|
||||
wget "$url"
|
||||
|
||||
# Unpack the tarball.
|
||||
tar zxf "$filename"
|
||||
|
||||
# Enter directory.
|
||||
cd "$directory"
|
||||
|
||||
# This function is called if any step fails.
|
||||
failed ()
|
||||
{
|
||||
tail -100 ../build.log > ../build.log.tail
|
||||
mutt -s "$prefix libguestfs $version FAILED $1" "$mailto" -a ../build.log.tail <<EOF
|
||||
Autobuild failed. The last 100 lines of the build log are
|
||||
attached.
|
||||
|
||||
For the full log see the build machine, in
|
||||
$tmpdir/build.log
|
||||
EOF
|
||||
rm ../build.log.tail
|
||||
}
|
||||
|
||||
# This function is called if the build is successful.
|
||||
ok ()
|
||||
{
|
||||
mutt -s "$prefix libguestfs $version ok" "$mailto" <<EOF
|
||||
Autobuild was successful.
|
||||
|
||||
For the full log see the build machine, in
|
||||
$tmpdir/build.log
|
||||
EOF
|
||||
}
|
||||
|
||||
# Ensure that we get full debugging output.
|
||||
export LIBGUESTFS_DEBUG=1
|
||||
export LIBGUESTFS_TRACE=1
|
||||
|
||||
# Configure and build.
|
||||
echo "configure"
|
||||
./configure > ../build.log 2>&1 || {
|
||||
failed "configure"
|
||||
exit 1
|
||||
}
|
||||
echo "make"
|
||||
make >> ../build.log 2>&1 || {
|
||||
failed "make"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Run the tests.
|
||||
echo "make check"
|
||||
make check >> ../build.log 2>&1 || {
|
||||
failed "make check"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "finished"
|
||||
ok
|
||||
@@ -13,7 +13,7 @@
|
||||
#
|
||||
# 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.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
# INSTRUCTIONS
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
400
contrib/intro/libguestfs-intro.html
Normal file
@@ -0,0 +1,400 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
|
||||
<title>Short introduction to libguestfs</title>
|
||||
<style>
|
||||
body {
|
||||
counter-reset: chapter;
|
||||
}
|
||||
|
||||
body > p, body > img, body > pre, body > table {
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: rgb(204,0,0);
|
||||
font-size: 130%;
|
||||
border-bottom: 1px solid rgb(204,0,0);
|
||||
}
|
||||
author {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 2em;
|
||||
top: 1em;
|
||||
font-size: 80%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 4em;
|
||||
color: rgb(204,0,0);
|
||||
counter-increment: chapter;
|
||||
counter-reset: section;
|
||||
}
|
||||
h2:before {
|
||||
font-size: 80%;
|
||||
color: #666;
|
||||
content: counter(chapter) " ... ";
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #fcfcfc;
|
||||
border-top: 1px dotted #eee;
|
||||
border-bottom: 1px dotted #eee;
|
||||
border-left: 2px solid rgb(204,0,0);
|
||||
padding: 5px;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
p.sourcelnk {
|
||||
text-align: left;
|
||||
font-size: 70%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Short introduction to libguestfs</h1>
|
||||
<author>by Richard W.M. Jones <rjones@redhat.com></author>
|
||||
|
||||
<h2>The Idea</h2>
|
||||
|
||||
<p><b>Reuse qemu, Linux kernel and userspace tools</b> to read and
|
||||
write disk images.</p>
|
||||
|
||||
<object type="image/svg+xml" data="overview.svg">
|
||||
<img src="overview.png"/> <!-- fallback for lame IE -->
|
||||
</object>
|
||||
|
||||
<h2>The Stable API</h2>
|
||||
|
||||
<pre>
|
||||
/* get the Linux VFS type corresponding to a mounted device */
|
||||
extern char *<b>guestfs_vfs_type</b> (guestfs_h *g, const char *device);
|
||||
</pre>
|
||||
|
||||
<table style="margin-bottom: 4em;" width="100%">
|
||||
<tr><td valign="top">Example using this API:</td><td>
|
||||
<pre>
|
||||
#include <guestfs.h>
|
||||
|
||||
char *fstype = <b>guestfs_vfs_type (g, "/dev/vda1")</b>;
|
||||
printf ("%s\n", fstype);
|
||||
free (fstype);
|
||||
→ <b>ntfs</b>
|
||||
</pre>
|
||||
<p class="sourcelnk"><a href="http://git.annexia.org/?p=libguestfs.git;a=blob;f=fish/inspect.c;h=2ca54d2296fce5370504c1085cbcd7ac1b51ad3a;hb=HEAD#l208">click to see a real example ...</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="100%">
|
||||
<tr><td valign="top">
|
||||
|
||||
<pre>
|
||||
("<b>vfs_type</b>",
|
||||
(RString "fstype",
|
||||
[Device "device"], []),
|
||||
198, [],
|
||||
[ (* tests *) ],
|
||||
"get the Linux VFS type corresponding to a mounted device",
|
||||
"\
|
||||
This command gets the filesystem type corresponding to
|
||||
the filesystem on C<device>.
|
||||
|
||||
For most filesystems, the result is the name of the Linux
|
||||
VFS module which would be used to mount this filesystem
|
||||
if you mounted it without specifying the filesystem type.
|
||||
For example a string such as C<ext3> or C<ntfs>.");
|
||||
</pre>
|
||||
<p class="sourcelnk"><a href="http://git.annexia.org/?p=libguestfs.git;a=blob;f=generator/generator_actions.ml;h=d3fa3e0b939eb047a5ff103a68f09c6898807748;hb=HEAD#l4775">full source ...</a></p>
|
||||
|
||||
</td>
|
||||
<td valign="top">
|
||||
|
||||
<pre>
|
||||
char *
|
||||
<b>do_vfs_type</b> (const char *device)
|
||||
{
|
||||
return get_blkid_tag (device, "TYPE");
|
||||
}
|
||||
|
||||
static char *
|
||||
get_blkid_tag (const char *device, const char *tag)
|
||||
{
|
||||
char *out, *err;
|
||||
int r;
|
||||
|
||||
r = commandr (&out, &err,
|
||||
"blkid",
|
||||
"-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;
|
||||
}
|
||||
|
||||
/* ... */
|
||||
|
||||
return out; /* caller frees */
|
||||
}
|
||||
</pre>
|
||||
<p class="sourcelnk"><a href="http://git.annexia.org/?p=libguestfs.git;a=blob;f=daemon/blkid.c;hb=HEAD">full source ...</a></p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
Just these two fragments generate:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> bindings in <a href="http://libguestfs.org/guestfs.3.html#api_overview">C</a>,
|
||||
<a href="http://libguestfs.org/guestfs-perl.3.html">Perl</a>,
|
||||
<a href="http://libguestfs.org/guestfs-python.3.html">Python</a>,
|
||||
<a href="http://libguestfs.org/guestfs-ruby.3.html">Ruby</a>,
|
||||
<a href="http://libguestfs.org/guestfs-java.3.html">Java</a>,
|
||||
<a href="http://libguestfs.org/guestfs-ocaml.3.html">OCaml</a>,
|
||||
PHP,
|
||||
Haskell,
|
||||
<a href="http://libguestfs.org/guestfs-erlang.3.html">Erlang</a>
|
||||
and C# </li>
|
||||
<li> <a href="http://libguestfs.org/guestfish.1.html">guestfish</a>
|
||||
(shell script) </li>
|
||||
<li> documentation in man pages and HTML </li>
|
||||
<li> internal RPC code </li>
|
||||
</ul>
|
||||
|
||||
<h2>Tools written around the API</h2>
|
||||
|
||||
<object type="image/svg+xml" data="tools.svg">
|
||||
<img src="tools.png"/> <!-- fallback for lame IE -->
|
||||
</object>
|
||||
|
||||
<table>
|
||||
<tr><td valign="top" style="padding-bottom: 1.5em;" colspan="2">
|
||||
<pre>
|
||||
<b>guestfish -N bootrootlv:/dev/VG/LV:ext4:ext4:10G:256M <<EOF</b>
|
||||
<font style="color: green;">mount-options "" /dev/VG/LV /
|
||||
mkdir /boot
|
||||
mount-options "" /dev/sda1 /boot
|
||||
txz-in filesystem.tar.xz /
|
||||
write /etc/HOSTNAME "test01.example.com\n"
|
||||
upload /etc/resolv.conf /etc/resolv.conf</font>
|
||||
<b>EOF</b>
|
||||
<b>guestmount -a test1.img -i mnt/</b>
|
||||
<b>ls mnt</b>
|
||||
bin dev home lib mnt proc sbin tmp var
|
||||
boot etc initrd.img lost+found old-root root sys usr vmlinuz
|
||||
<b>cat mnt/etc/HOSTNAME</b>
|
||||
test01.example.com
|
||||
<b>fusermount -u mnt</b>
|
||||
</pre>
|
||||
<p class="sourcelnk"><a href="http://libguestfs.org/guestfish.1.html">manual for guestfish ...</a> <br/>
|
||||
<a href="http://libguestfs.org/guestmount.1.html">manual for guestmount ...</a></p>
|
||||
</td></tr>
|
||||
<tr><td valign="top" style="padding-bottom: 1.5em;">
|
||||
<pre>
|
||||
<b>virt-df -a /dev/vg/F15x32 -h</b>
|
||||
Filesystem Size Used Available Use%
|
||||
F15x32:/dev/sda1 484M 31M 428M 7%
|
||||
F15x32:/dev/vg_f15x32/lv_root 5.5G 3.4G 1.8G 63%
|
||||
</pre>
|
||||
<p class="sourcelnk"><a href="http://libguestfs.org/virt-df.1.html">manual ...</a></p>
|
||||
</td>
|
||||
<td valign="top" style="padding-bottom: 1.5em;">
|
||||
<pre>
|
||||
<b>virt-cat -c qemu:///system -d WinXP 'c:\boot.ini'</b>
|
||||
[boot loader]
|
||||
timeout=30
|
||||
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
|
||||
[operating systems]
|
||||
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS=
|
||||
"Microsoft Windows XP Professional" /noexecute=optin
|
||||
/fastdetect
|
||||
</pre>
|
||||
<p class="sourcelnk"><a href="http://libguestfs.org/virt-cat.1.html">manual ...</a></p>
|
||||
</td></tr>
|
||||
<tr><td valign="top" style="padding-bottom: 1.5em;">
|
||||
<pre>
|
||||
<b>virt-edit -c qemu:///system -d F15x32 /etc/passwd</b>
|
||||
<i>(launches text editor to edit guest /etc/passwd)</i>
|
||||
|
||||
<b>virt-edit -c qemu:///system -d F15x32 /etc/passwd \
|
||||
-e 's/^root:.*?:/root::/'</b>
|
||||
</pre>
|
||||
<p class="sourcelnk"><a href="http://libguestfs.org/virt-edit.1.html">manual ...</a></p>
|
||||
</td><td valign="top" style="padding-bottom: 1.5em;">
|
||||
<pre>
|
||||
<b>virt-win-reg -c qemu:///system --unsafe-printable-strings \
|
||||
Win7x32 'HKLM\SYSTEM\ControlSet001\Services\Tcpip\Parameters' \
|
||||
| grep DhcpIPAddress</b>
|
||||
"DhcpIPAddress"=str(1):"192.168.122.178"
|
||||
</pre>
|
||||
<p class="sourcelnk"><a href="http://libguestfs.org/virt-win-reg.1.html">manual ...</a></p>
|
||||
</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>Inspection</h2>
|
||||
|
||||
<pre>
|
||||
$ <b>virt-filesystems -c qemu:///system -d Win7x32 --all --long -h --uuid</b>
|
||||
Name Type VFS Label MBR Size Parent UUID
|
||||
/dev/sda1 filesystem ntfs System Reserved - 100M - F81C92571C92112C
|
||||
/dev/sda2 filesystem ntfs - - 20G - F2E8996AE8992E3B
|
||||
/dev/sda1 partition - - 07 100M /dev/sda -
|
||||
/dev/sda2 partition - - 07 20G /dev/sda -
|
||||
/dev/sda device - - - 20G - -
|
||||
</pre>
|
||||
<p class="sourcelnk">
|
||||
<a href="http://libguestfs.org/virt-filesystems.1.html">manual ...</a>
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ <b>virt-inspector -c qemu:///system -d Win7x32</b>
|
||||
<font style="color: #888;"><?xml version="1.0"?></font>
|
||||
<font style="color: #888;"><operatingsystems></font>
|
||||
<font style="color: #888;"><operatingsystem></font>
|
||||
<font style="color: #888;"><root></font>/dev/sda2<font style="color: #888;"></root></font>
|
||||
<font style="color: #888;"><name></font>windows<font style="color: #888;"></name></font>
|
||||
<font style="color: #888;"><arch></font>i386<font style="color: #888;"></arch></font>
|
||||
<font style="color: #888;"><distro></font>windows<font style="color: #888;"></distro></font>
|
||||
<font style="color: #888;"><product_name></font>Windows 7 Enterprise<font style="color: #888;"></product_name></font>
|
||||
<font style="color: #888;"><product_variant></font>Client<font style="color: #888;"></product_variant></font>
|
||||
<font style="color: #888;"><major_version></font>6<font style="color: #888;"></major_version></font>
|
||||
<font style="color: #888;"><minor_version></font>1<font style="color: #888;"></minor_version></font>
|
||||
<font style="color: #888;"><windows_systemroot></font>/Windows<font style="color: #888;"></windows_systemroot></font>
|
||||
<font style="color: #888;"><windows_current_control_set></font>ControlSet001<font style="color: #888;"></windows_current_control_set></font>
|
||||
<font style="color: #888;"><hostname></font>win7x32<font style="color: #888;"></hostname></font>
|
||||
<i>... etc ...</i>
|
||||
</pre>
|
||||
<p class="sourcelnk">
|
||||
<a href="win7.xml">full XML ...</a> <br/>
|
||||
<a href="http://libguestfs.org/virt-inspector.1.html">manual ...</a>
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
char **roots;
|
||||
size_t i;
|
||||
char *type, *distro, *product_name;
|
||||
int major, minor;
|
||||
|
||||
roots = <b>guestfs_inspect_os</b> (g);
|
||||
|
||||
if (roots == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
if (roots[0] == NULL) {
|
||||
fprintf (stderr, "no operating systems found\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; roots[i] != NULL; ++i) {
|
||||
type = <b>guestfs_inspect_get_type</b> (g, roots[i]);
|
||||
distro = <b>guestfs_inspect_get_distro</b> (g, roots[i]);
|
||||
product_name = <b>guestfs_inspect_get_product_name</b> (g, roots[i]);
|
||||
major = <b>guestfs_inspect_get_major_version</b> (g, roots[i]);
|
||||
minor = <b>guestfs_inspect_get_minor_version</b> (g, roots[i]);
|
||||
|
||||
printf ("Root: %s\n"
|
||||
" Type: %s\n"
|
||||
" Distro: %s\n"
|
||||
" Version: %d.%d\n"
|
||||
" Product name: %s\n\n");
|
||||
roots[i],
|
||||
type ? : "unknown", distro ? : "unknown", major, minor,
|
||||
product_name ? : "");
|
||||
|
||||
free (type);
|
||||
free (distro);
|
||||
free (product_name);
|
||||
free (roots[i]);
|
||||
}
|
||||
|
||||
free (roots);
|
||||
</pre>
|
||||
<p class="sourcelnk"><a href="http://git.annexia.org/?p=libguestfs.git;a=blob;f=rescue/virt-rescue.c;h=0c0036460434f1365d9591d6b2b805d999b07056;hb=HEAD#l351">full source ...</a></p>
|
||||
|
||||
<table>
|
||||
<tr><td colspan="2" align="middle">
|
||||
<small><i>Click to enlarge the images</i></small>
|
||||
</td></tr>
|
||||
<tr><td width="50%">
|
||||
<a href="virt-manager.png"><img src="virt-manager-t.png"></a>
|
||||
</td><td width="50%" align="middle" valign="top">
|
||||
<a href="vmm-icons.png"><img src="vmm-icons-t.png"></a>
|
||||
</td></tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Graphical browsers</h2>
|
||||
|
||||
<p>
|
||||
<img src="https://rwmj.files.wordpress.com/2011/07/guestfs-browser1.png?w=438&h=450"/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="https://rwmj.files.wordpress.com/2011/07/guestfs-browser2.png?w=438&h=450"/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="https://rwmj.files.wordpress.com/2011/07/guestfs-browser3.png?w=366&h=450"/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="https://rwmj.files.wordpress.com/2011/07/guestfs-browser4.png?w=366&h=450"/>
|
||||
</p>
|
||||
<p class="sourcelnk"><a href="https://rwmj.wordpress.com/2011/07/29/some-screenshots-from-the-new-guest-filesystem-browser/">source ...</a></p>
|
||||
|
||||
<p>
|
||||
<img src="https://rwmj.files.wordpress.com/2009/11/file-browser.png?w=500"/>
|
||||
</p>
|
||||
<p class="sourcelnk"><a href="https://rwmj.wordpress.com/2009/11/03/browsing-guests-using-fuse/">source ...</a></p>
|
||||
|
||||
|
||||
|
||||
<h2>Find out more ...</h2>
|
||||
|
||||
<p>
|
||||
<a href="http://libguestfs.org/">libguestfs.org</a> is the
|
||||
main website.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="http://libguestfs.org/guestfs.3.html">guestfs(3)</a>
|
||||
is the manual page documenting the C API and the internals.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There are manual pages
|
||||
documenting <a href="http://libguestfs.org/guestfish.1.html">guestfish</a>, <a href="http://libguestfs.org/guestmount.1.html">guestmount</a>
|
||||
and each virt tool. See
|
||||
the <a href="http://libguestfs.org/">main website</a> or your
|
||||
local man command.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For information about virt-v2v and virt-p2v, see
|
||||
<a href="http://libguestfs.org/virt-v2v/">http://libguestfs.org/virt-v2v/</a>
|
||||
</p>
|
||||
|
||||
<hr/>
|
||||
|
||||
<p style="font-size: 70%;">
|
||||
This page © 2011 Red Hat Inc. and distributed
|
||||
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.
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
BIN
contrib/intro/overview.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
524
contrib/intro/overview.svg
Normal file
|
After Width: | Height: | Size: 281 KiB |
162
contrib/intro/talk.txt
Normal file
@@ -0,0 +1,162 @@
|
||||
This is a short (10-15 min) talk that I give to introduce the main
|
||||
features of libguestfs. The "slides" are in the form of a complete
|
||||
self-contained HTML page with a handful images that can be easily
|
||||
distributed before the talk.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
[1 The Idea]
|
||||
|
||||
The "big idea" behind libguestfs is to read and write disk
|
||||
images by reusing all the qemu, Linux kernel and userspace
|
||||
code.
|
||||
|
||||
This gives us tremendous power in a relatively small
|
||||
library: we can handle all Linux filesystems, all Windows
|
||||
filesystems, LVM, BSD, containers like raw and qcow, CD ISOs,
|
||||
USB keys, regular hard disks, and lots more.
|
||||
|
||||
If you give us a btrfs filesystem in a BSD partition wrapped
|
||||
in a qcow2 file -- that is something we can handle.
|
||||
|
||||
libguestfs -- as the name suggests -- is a plain, ordinary
|
||||
shared library written in C that you can link to C programs.
|
||||
You're all very smart people and you will have guessed
|
||||
already that we don't in fact run qemu as a library inside
|
||||
libguestfs as this diagram suggests. Instead we fork
|
||||
qemu or KVM, running a small "appliance" which has
|
||||
the usual kernel, a small Linux distribution with tools
|
||||
like mkfs, lvcreate and parted, and a libguestfs daemon.
|
||||
The library and the daemon talk to each other over a
|
||||
virtio-serial connection.
|
||||
|
||||
The qemu instance is connected to the disks we are
|
||||
examining using the ordinary qemu -drive option.
|
||||
|
||||
[2 The Stable API]
|
||||
|
||||
Consider how you might send commands to the daemon.
|
||||
Example: Create a filesystem (mkfs).
|
||||
|
||||
One thing you might do is to send shell commands over
|
||||
the virtio-serial connection. It would send "mkfs -t ..."
|
||||
|
||||
This is something that is possible using the libguestfs
|
||||
API, but we don't encourage it. There are three reasons
|
||||
why we don't encourage and support this: one is that
|
||||
because we're calling this from a C program, it's hard
|
||||
to construct shell commands.
|
||||
Secondly it's hard to parse the result from commands
|
||||
(think about parted or lvs which are two commands that
|
||||
produce quite complex output that is hard to parse).
|
||||
Thirdly the command line isn't very long-term stable,
|
||||
with some commands appearing and changing over time.
|
||||
|
||||
I'd emphasize again that we do let you send shell
|
||||
commands over to the daemon if that's what you want to do.
|
||||
|
||||
What we support, though, is a long-term stable API and ABI.
|
||||
It's slightly (but not very much) higher level than shell
|
||||
commands.
|
||||
|
||||
I've got an example on the page. This is the guestfs_vfs_type
|
||||
API which returns the name of the filesystem on a device.
|
||||
|
||||
Like libvirt, we are serious about the long term stability
|
||||
of the API and ABI, and if you write your program against
|
||||
this API, you'll never have to change the program or even
|
||||
recompile it.
|
||||
|
||||
Because there are 100s of commands that you might want to
|
||||
run, we made it exceptionally simple to add new APIs.
|
||||
Shown below is the actual code used to implement "vfs-type".
|
||||
|
||||
On the right is the code fragment that runs in the daemon.
|
||||
This is a short C function which handles constructing the
|
||||
command line and parsing out the result. Although there
|
||||
is parsing code here, the good thing is that it only exists
|
||||
in one place, and we can update it from time to time if
|
||||
the underlying shell commands change.
|
||||
|
||||
On the left is the metadata for this API function. It
|
||||
has a description of the parameters and return value,
|
||||
some tests (not shown), and a fragment of documentation.
|
||||
|
||||
That's ALL you have to write. From that, we generate
|
||||
header files, bindings in all the different languages,
|
||||
RPC for the virtio-serial connection, documentation, etc.
|
||||
Currently we generate about a quarter of a million lines
|
||||
of code and documentation.
|
||||
|
||||
[3 Tools written around the API]
|
||||
|
||||
Around this stable API, myself and the libguestfs team
|
||||
have written a number of tools. There are also people
|
||||
in the community writing other tools.
|
||||
|
||||
A few of them are shown on this diagram, in fact there
|
||||
are many more than are shown here.
|
||||
|
||||
Starting at the top, "guestfish" is a shell for the API,
|
||||
letting you write simple shell scripts. If you look at
|
||||
the code examples below, you can see a small guestfish
|
||||
script that creates a complete guest. Then we mount it on
|
||||
the host using guestmount (FUSE) and browse around.
|
||||
|
||||
Going round clockwise:
|
||||
|
||||
The libguestfs API is a mix of high-level calls like
|
||||
mkfs, lvremove, vfs-type; and also low level POSIX calls
|
||||
like mkdir and writing to files.
|
||||
"guestmount" lets you mount an existing filesystem from
|
||||
a guest and access it as a regular mountpoint on the host.
|
||||
guestmount intelligently caches and prefetches data so it's
|
||||
quite usable and fast from the command line or graphical
|
||||
programs like the GNOME Nautilus file browser.
|
||||
|
||||
"virt-rescue" lets you use the appliance directly, and
|
||||
it's a useful way to rescue guests by hand.
|
||||
|
||||
"virt-win-reg" lets you read and write Windows Registry
|
||||
entries. There is a rather complex example below right.
|
||||
|
||||
Now we come round to the "inspection" tools, and these
|
||||
three tools let you inspect an unknown guest to find out
|
||||
what operating system it contains, what applications are
|
||||
installed, what filesystems, how the filesystems are used
|
||||
and much more. I cover that in the next section, but if
|
||||
you look below you'll see an example of running "virt-df".
|
||||
|
||||
Finally there are now tools to resize guests, make them
|
||||
sparse, align them, and check their alignment. These
|
||||
last tools are ones that we eventually hope will become
|
||||
obsolete.
|
||||
|
||||
[4 Inspection]
|
||||
|
||||
Next I want to look at another aspect of the API which is
|
||||
called "inspection".
|
||||
|
||||
Inspection means taking arbitrary disk images and finding
|
||||
out what they contain, from just what partitions and filesystems
|
||||
are in a disk image, to whether and what operating system(s)
|
||||
it contains, to what applications are installed.
|
||||
|
||||
The two main command-line tools are virt-filesystems and
|
||||
virt-inspector, and you can see the output from these tools.
|
||||
However this information is also available through the
|
||||
API. The example there shows getting operating system
|
||||
inspection data from a C program. Programs can also get
|
||||
inspection information, as you can see in the screenshots
|
||||
from the latest virt-manager.
|
||||
|
||||
[5 Graphical browsers]
|
||||
|
||||
I've concentrated a lot on command line tools, but you can
|
||||
also use libguestfs from graphical programs. I wrote an
|
||||
experimental program called guestfs-browser, and there are
|
||||
screenshots shown. But many people will simply want to mount
|
||||
a filesystem on the host using guestmount, and then use
|
||||
ordinary tools. At the bottom is a screenshot of GNOME
|
||||
Nautilus browsing into a guest filesystem.
|
||||
|
||||
BIN
contrib/intro/tools.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
711
contrib/intro/tools.svg
Normal file
@@ -0,0 +1,711 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="629.526"
|
||||
height="475.37674"
|
||||
preserveAspectRatio="xMinYMin meet"
|
||||
viewBox="0 0 630.14339 474.34607"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.1 r9760"
|
||||
sodipodi:docname="libguestfs-tools.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="305.93218"
|
||||
inkscape:cy="244.25314"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1400"
|
||||
inkscape:window-height="833"
|
||||
inkscape:window-x="26"
|
||||
inkscape:window-y="31"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="10"
|
||||
fit-margin-left="10"
|
||||
fit-margin-right="10"
|
||||
fit-margin-bottom="10">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3046"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow1Mend"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1Mend">
|
||||
<path
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
id="path4254"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow1Lend"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1Lend">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
id="path4149" />
|
||||
</marker>
|
||||
<inkscape:perspective
|
||||
id="perspective3761"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow1LendR"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1LendR">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
style="fill:#8c8989;fill-rule:evenodd;stroke:#8c8989;stroke-width:1pt;marker-start:none"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
id="path4924" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow1LendH"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1LendH">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
style="fill:#888888;fill-rule:evenodd;stroke:#888888;stroke-width:1pt;marker-start:none"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
id="path5584" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow1Lendi"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1Lendi">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
style="fill:#888888;fill-rule:evenodd;stroke:#888888;stroke-width:1pt;marker-start:none"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
id="path5587" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow1Lendn"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1Lendn">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
id="path5590" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow1LendnS"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1LendnS">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
id="path5709" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow1LendnS4"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1LendnS4">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
style="fill:#888888;fill-rule:evenodd;stroke:#888888;stroke-width:1pt;marker-start:none"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
id="path5832" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow1MendG"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1MendG">
|
||||
<path
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;marker-start:none"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
id="path4721"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(-61.579184,-78.961745)"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3793"
|
||||
y="269.36218"
|
||||
x="306"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="269.36218"
|
||||
x="306"
|
||||
id="tspan3795"
|
||||
sodipodi:role="line" /></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3797"
|
||||
y="267.36218"
|
||||
x="304"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="267.36218"
|
||||
x="304"
|
||||
id="tspan3799"
|
||||
sodipodi:role="line" /></text>
|
||||
<g
|
||||
id="g3942"
|
||||
transform="matrix(0.72385693,0,0,0.72385693,134.30682,108.78183)">
|
||||
<rect
|
||||
style="fill:#ffdcdc;fill-opacity:1;stroke:#190000;stroke-width:2.94564199;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect2985"
|
||||
width="294.189"
|
||||
height="237.99187"
|
||||
x="190.705"
|
||||
y="154.46817" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="239"
|
||||
y="201.36218"
|
||||
id="text3757"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3759"
|
||||
x="239"
|
||||
y="201.36218">libguestfs</tspan></text>
|
||||
<g
|
||||
id="g4614"
|
||||
transform="matrix(0.88003385,0,0,0.86189263,26.891233,24.839975)">
|
||||
<rect
|
||||
y="219.36218"
|
||||
x="218"
|
||||
height="40"
|
||||
width="58"
|
||||
id="rect3779"
|
||||
style="fill:#fff6f6;fill-opacity:1;stroke:#190000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3789"
|
||||
y="247.36218"
|
||||
x="223"
|
||||
style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="247.36218"
|
||||
x="223"
|
||||
id="tspan3791"
|
||||
sodipodi:role="line">mkfs</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.87343177,0,0,0.83132964,36.681547,40.720104)"
|
||||
id="g3077">
|
||||
<rect
|
||||
style="fill:#fff6f6;fill-opacity:1;stroke:#190000;stroke-width:1.2677021;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect3781"
|
||||
width="96.596542"
|
||||
height="38.597645"
|
||||
x="279.26575"
|
||||
y="246.24846" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3801"
|
||||
y="271.77777"
|
||||
x="287.50287"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="271.77777"
|
||||
x="287.50287"
|
||||
id="tspan3803"
|
||||
sodipodi:role="line">lvcreate</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.9731636,0,0,0.89682062,-4.7939037,17.840053)"
|
||||
id="g3072">
|
||||
<rect
|
||||
y="228.36218"
|
||||
x="389"
|
||||
height="40"
|
||||
width="77.964508"
|
||||
id="rect3783"
|
||||
style="fill:#fff6f6;fill-opacity:1;stroke:#190000;stroke-width:1.15940309;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3805"
|
||||
y="256.36218"
|
||||
x="396"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="256.36218"
|
||||
x="396"
|
||||
id="tspan3807"
|
||||
sodipodi:role="line">parted</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3931">
|
||||
<rect
|
||||
style="fill:#fff6f6;fill-opacity:1;stroke:#190000;stroke-width:0.74572152;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect3048"
|
||||
width="264"
|
||||
height="30.02943"
|
||||
x="200.91432"
|
||||
y="352.42081" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="220.93394"
|
||||
y="372.44043"
|
||||
id="text3050"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3052"
|
||||
x="220.93394"
|
||||
y="372.44043">qemu</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14.01373005px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans Narrow;-inkscape-font-specification:Sans"
|
||||
x="371.08105"
|
||||
y="372.44043"
|
||||
id="text3054"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3056"
|
||||
x="371.08105"
|
||||
y="372.44043">raw</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14.01373005px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans Narrow;-inkscape-font-specification:Sans"
|
||||
x="421.1301"
|
||||
y="372.44043"
|
||||
id="text3058"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3060"
|
||||
x="421.1301"
|
||||
y="372.44043">qcow2</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14.01373005px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans Narrow;-inkscape-font-specification:Sans"
|
||||
x="323.02417"
|
||||
y="372.91223"
|
||||
id="text3062"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3064"
|
||||
x="323.02417"
|
||||
y="372.91223">vmdk</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3922">
|
||||
<rect
|
||||
y="292.36197"
|
||||
x="200.91432"
|
||||
height="54"
|
||||
width="264"
|
||||
id="rect3777"
|
||||
style="fill:#fff6f6;fill-opacity:1;stroke:#190000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3785"
|
||||
y="326.63818"
|
||||
x="220.52794"
|
||||
style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="326.63818"
|
||||
x="220.52794"
|
||||
id="tspan3787"
|
||||
sodipodi:role="line">Linux kernel</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14.01373005px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans Narrow;-inkscape-font-specification:Sans"
|
||||
x="391.51471"
|
||||
y="315.46762"
|
||||
id="text3082"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3084"
|
||||
x="391.51471"
|
||||
y="315.46762">ext4</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14.01373005px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans Narrow;-inkscape-font-specification:Sans"
|
||||
x="426.90472"
|
||||
y="333.87045"
|
||||
id="text3086"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3088"
|
||||
x="426.90472"
|
||||
y="333.87045">btrfs</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g3888"
|
||||
transform="translate(-85.64383,133.06644)">
|
||||
<rect
|
||||
ry="9.1923885"
|
||||
transform="matrix(1.0009807,0,0,1.0009807,10.718182,61.430592)"
|
||||
y="19.7358"
|
||||
x="163.34166"
|
||||
height="31.819805"
|
||||
width="145.66399"
|
||||
id="rect3060"
|
||||
style="fill:#cc0000;fill-opacity:1;stroke:none" />
|
||||
<text
|
||||
transform="matrix(1.0009807,0,0,1.0009807,10.718182,61.430592)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3884"
|
||||
y="40.241898"
|
||||
x="178.89801"
|
||||
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
|
||||
xml:space="preserve"><tspan
|
||||
y="40.241898"
|
||||
x="178.89801"
|
||||
id="tspan3886"
|
||||
sodipodi:role="line">virt-resize</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(268.25631,31.143212)"
|
||||
id="g3901">
|
||||
<rect
|
||||
style="fill:#cc0000;fill-opacity:1;stroke:none"
|
||||
id="rect3895"
|
||||
width="145.66399"
|
||||
height="31.819805"
|
||||
x="163.34166"
|
||||
y="19.7358"
|
||||
ry="9.1923885"
|
||||
transform="matrix(1.0009807,0,0,1.0009807,10.718182,61.430592)" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
|
||||
x="178.89801"
|
||||
y="40.241898"
|
||||
id="text3897"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(1.0009807,0,0,1.0009807,10.718182,61.430592)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3899"
|
||||
x="178.89801"
|
||||
y="40.241898">guestmount</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(94.845234,16.279406)"
|
||||
id="g3917">
|
||||
<rect
|
||||
ry="9.2014036"
|
||||
y="72.692146"
|
||||
x="110.51801"
|
||||
height="31.851011"
|
||||
width="145.80684"
|
||||
id="rect3908"
|
||||
style="fill:#cc0000;fill-opacity:1;stroke:none" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3910"
|
||||
y="93.218353"
|
||||
x="126.08962"
|
||||
style="font-size:16.01569176px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
|
||||
xml:space="preserve"><tspan
|
||||
y="93.218353"
|
||||
x="126.08962"
|
||||
id="tspan3912"
|
||||
sodipodi:role="line">guestfish</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g4006"
|
||||
transform="translate(12.032604,19.818407)">
|
||||
<rect
|
||||
style="fill:#cc0000;fill-opacity:1;stroke:none"
|
||||
id="rect3997"
|
||||
width="145.80684"
|
||||
height="31.851011"
|
||||
x="523.87335"
|
||||
y="229.11598"
|
||||
ry="9.2014036" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:16.01569176px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
|
||||
x="539.44495"
|
||||
y="249.6422"
|
||||
id="text3999"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4001"
|
||||
x="539.44495"
|
||||
y="249.6422">virt-rescue</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-102.63104,181.19685)"
|
||||
id="g4011">
|
||||
<rect
|
||||
style="fill:#cc0000;fill-opacity:1;stroke:none"
|
||||
id="rect4013"
|
||||
width="145.66399"
|
||||
height="31.819805"
|
||||
x="163.34166"
|
||||
y="19.7358"
|
||||
transform="matrix(1.0009807,0,0,1.0009807,10.718182,61.430592)"
|
||||
ry="9.1923885" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
|
||||
x="178.89801"
|
||||
y="40.241898"
|
||||
id="text4015"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(1.0009807,0,0,1.0009807,10.718182,61.430592)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4017"
|
||||
x="178.89801"
|
||||
y="40.241898">virt-sparsify</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g4081"
|
||||
transform="translate(-5.6624019,-29.72761)">
|
||||
<rect
|
||||
ry="9.2014036"
|
||||
y="341.65622"
|
||||
x="82.206001"
|
||||
height="31.851011"
|
||||
width="145.80684"
|
||||
id="rect4021"
|
||||
style="fill:#cc0000;fill-opacity:1;stroke:none" />
|
||||
<text
|
||||
transform="scale(0.97311457,1.0276282)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4023"
|
||||
y="352.44501"
|
||||
x="87.536247"
|
||||
style="font-size:15.58510303px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
|
||||
xml:space="preserve"><tspan
|
||||
y="352.44501"
|
||||
x="87.536247"
|
||||
id="tspan4025"
|
||||
sodipodi:role="line">virt-alignment-scan</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g4038"
|
||||
transform="translate(-7.7858026,8.4936029)">
|
||||
<rect
|
||||
style="fill:#cc0000;fill-opacity:1;stroke:none"
|
||||
id="rect4029"
|
||||
width="145.80684"
|
||||
height="31.851011"
|
||||
x="134.58322"
|
||||
y="428.71567"
|
||||
ry="9.2014036" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:16.01569176px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
|
||||
x="150.15482"
|
||||
y="449.24185"
|
||||
id="text4031"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4033"
|
||||
x="150.15482"
|
||||
y="449.24185">virt-inspector</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(75.026826,46.714815)"
|
||||
id="g4043">
|
||||
<rect
|
||||
ry="9.2014036"
|
||||
y="428.71567"
|
||||
x="134.58322"
|
||||
height="31.851011"
|
||||
width="145.80684"
|
||||
id="rect4045"
|
||||
style="fill:#cc0000;fill-opacity:1;stroke:none" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4047"
|
||||
y="449.24185"
|
||||
x="150.15482"
|
||||
style="font-size:16.01569176px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
|
||||
xml:space="preserve"><tspan
|
||||
y="449.24185"
|
||||
x="150.15482"
|
||||
id="tspan4049"
|
||||
sodipodi:role="line">virt-filesystems</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g4076"
|
||||
transform="translate(38.929013,4.2468014)">
|
||||
<rect
|
||||
style="fill:#cc0000;fill-opacity:1;stroke:none"
|
||||
id="rect4053"
|
||||
width="102.63103"
|
||||
height="31.851011"
|
||||
x="265.52628"
|
||||
y="508.69708"
|
||||
ry="9.2014036" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:16.01569176px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
|
||||
x="281.09787"
|
||||
y="529.22327"
|
||||
id="text4055"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4057"
|
||||
x="281.09787"
|
||||
y="529.22327">virt-df</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g4108"
|
||||
transform="translate(-7.0780024,24.773008)">
|
||||
<rect
|
||||
ry="9.2014036"
|
||||
y="411.72845"
|
||||
x="496.97693"
|
||||
height="31.851011"
|
||||
width="145.80684"
|
||||
id="rect4061"
|
||||
style="fill:#cc0000;fill-opacity:1;stroke:none" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4063"
|
||||
y="432.25464"
|
||||
x="512.54852"
|
||||
style="font-size:16.01569176px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
|
||||
xml:space="preserve"><tspan
|
||||
y="432.25464"
|
||||
x="512.54852"
|
||||
id="tspan4065"
|
||||
sodipodi:role="line">virt-win-reg</tspan></text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
x="380.42343"
|
||||
y="96.660439"
|
||||
id="text4086"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(1.0009807,0,0,1.0009807,64.410388,68.552031)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4088"
|
||||
x="380.42343"
|
||||
y="96.660439">FUSE / POSIX</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
x="180.31223"
|
||||
y="81.811195"
|
||||
id="text4090"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(1.0009807,0,0,1.0009807,64.410388,68.552031)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4092"
|
||||
x="180.31223"
|
||||
y="81.811195">shell scripts</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
x="105.35891"
|
||||
y="291.11481"
|
||||
id="text4094"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(1.0009807,0,0,1.0009807,64.410388,68.552031)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4096"
|
||||
x="105.35891"
|
||||
y="291.11481">align & resize</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
x="247.48737"
|
||||
y="384.45288"
|
||||
id="text4098"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(1.0009807,0,0,1.0009807,64.410388,68.552031)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4100"
|
||||
x="247.48737"
|
||||
y="384.45288">inspection</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:14.01373005px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
x="500.41534"
|
||||
y="405.25153"
|
||||
id="text4102"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4104"
|
||||
x="500.41534"
|
||||
y="405.25153">Windows</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="500.41534"
|
||||
y="422.76868"
|
||||
id="tspan4106">guests</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 28 KiB |
BIN
contrib/intro/virt-manager-t.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
contrib/intro/virt-manager.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
contrib/intro/vmm-icons-t.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
contrib/intro/vmm-icons.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
164
contrib/intro/win7.xml
Normal file
@@ -0,0 +1,164 @@
|
||||
<?xml version="1.0"?>
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/sda2</root>
|
||||
<name>windows</name>
|
||||
<arch>i386</arch>
|
||||
<distro>windows</distro>
|
||||
<product_name>Windows 7 Enterprise</product_name>
|
||||
<product_variant>Client</product_variant>
|
||||
<major_version>6</major_version>
|
||||
<minor_version>1</minor_version>
|
||||
<windows_systemroot>/Windows</windows_systemroot>
|
||||
<windows_current_control_set>ControlSet001</windows_current_control_set>
|
||||
<hostname>win7x32</hostname>
|
||||
<format>installed</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda2">/</mountpoint>
|
||||
</mountpoints>
|
||||
<filesystems>
|
||||
<filesystem dev="/dev/sda2">
|
||||
<type>ntfs</type>
|
||||
<uuid>F2E8996AE8992E3B</uuid>
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
<drive_mappings>
|
||||
<drive_mapping name="C">/dev/sda2</drive_mapping>
|
||||
</drive_mappings>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Microsoft .NET Framework 4 Client Profile</name>
|
||||
<display_name>Microsoft .NET Framework 4 Client Profile</display_name>
|
||||
<version>4.0.30319</version>
|
||||
<install_path>C:\Windows\Microsoft.NET\Framework\v4.0.30319\SetupCache\Client</install_path>
|
||||
<publisher>Microsoft Corporation</publisher>
|
||||
<url>http://go.microsoft.com/fwlink/?LinkId=164164</url>
|
||||
</application>
|
||||
<application>
|
||||
<name>Mozilla Firefox (3.6.12)</name>
|
||||
<display_name>Mozilla Firefox (3.6.12)</display_name>
|
||||
<version>3.6.12 (en-GB)</version>
|
||||
<install_path>C:\Program Files\Mozilla Firefox</install_path>
|
||||
<publisher>Mozilla</publisher>
|
||||
<url>http://www.mozilla.com/en-GB/</url>
|
||||
<description>Mozilla Firefox</description>
|
||||
</application>
|
||||
<application>
|
||||
<name>VLC media player</name>
|
||||
<display_name>VLC media player 1.1.5</display_name>
|
||||
<version>1.1.5</version>
|
||||
<install_path>C:\Program Files\VideoLAN\VLC</install_path>
|
||||
<publisher>VideoLAN</publisher>
|
||||
<url>http://www.videolan.org/</url>
|
||||
</application>
|
||||
<application>
|
||||
<name>{3C3901C5-3455-3E0A-A214-0B093A5070A6}</name>
|
||||
<display_name>Microsoft .NET Framework 4 Client Profile</display_name>
|
||||
<version>4.0.30319</version>
|
||||
<publisher>Microsoft Corporation</publisher>
|
||||
<url>http://go.microsoft.com/fwlink/?LinkId=164164</url>
|
||||
</application>
|
||||
<application>
|
||||
<name>{3C3901C5-3455-3E0A-A214-0B093A5070A6}.KB2468871</name>
|
||||
<display_name>Update for Microsoft .NET Framework 4 Client Profile (KB2468871)</display_name>
|
||||
<version>1</version>
|
||||
<publisher>Microsoft Corporation</publisher>
|
||||
<url>http://support.microsoft.com</url>
|
||||
<description>This update is for Microsoft .NET Framework 4 Client Profile.
|
||||
If you later install a more recent service pack, this update will be uninstalled automatically.
|
||||
For more information, visit http://support.microsoft.com/kb/2468871.</description>
|
||||
</application>
|
||||
<application>
|
||||
<name>{3C3901C5-3455-3E0A-A214-0B093A5070A6}.KB2518870</name>
|
||||
<display_name>Security Update for Microsoft .NET Framework 4 Client Profile (KB2518870)</display_name>
|
||||
<version>1</version>
|
||||
<publisher>Microsoft Corporation</publisher>
|
||||
<url>http://support.microsoft.com</url>
|
||||
<description>This security update is for Microsoft .NET Framework 4 Client Profile.
|
||||
If you later install a more recent service pack, this security update will be uninstalled automatically.
|
||||
For more information, visit http://support.microsoft.com/kb/2518870.</description>
|
||||
</application>
|
||||
<application>
|
||||
<name>{3C3901C5-3455-3E0A-A214-0B093A5070A6}.KB2533523</name>
|
||||
<display_name>Update for Microsoft .NET Framework 4 Client Profile (KB2533523)</display_name>
|
||||
<version>1</version>
|
||||
<publisher>Microsoft Corporation</publisher>
|
||||
<url>http://support.microsoft.com</url>
|
||||
<description>This update is for Microsoft .NET Framework 4 Client Profile.
|
||||
If you later install a more recent service pack, this update will be uninstalled automatically.
|
||||
For more information, visit http://support.microsoft.com/kb/2533523.</description>
|
||||
</application>
|
||||
<application>
|
||||
<name>{3C3901C5-3455-3E0A-A214-0B093A5070A6}.KB2539636</name>
|
||||
<display_name>Security Update for Microsoft .NET Framework 4 Client Profile (KB2539636)</display_name>
|
||||
<version>1</version>
|
||||
<publisher>Microsoft Corporation</publisher>
|
||||
<url>http://support.microsoft.com</url>
|
||||
<description>This security update is for Microsoft .NET Framework 4 Client Profile.
|
||||
If you later install a more recent service pack, this security update will be uninstalled automatically.
|
||||
For more information, visit http://support.microsoft.com/kb/2539636.</description>
|
||||
</application>
|
||||
</applications>
|
||||
<icon>iVBORw0KGgoAAAANSUhEUgAAADYAAAA3CAIAAADIey4vAAAMo0lEQVRoge2YaViTVxbHMQlb
|
||||
CCGCW6lVNinIYpURbQcqiiRAWILIIgLKLmEnkAQJa4CELYAJqwIadgFBVkHZEVAQQXZEwQVL
|
||||
rdpxaVWgdY4ynQ/zzMwzIm0/DOc5H9577/n//ue5yXvfNxEQWI3VWI3VWI3/t0CJIDYqIZXw
|
||||
KE07oW8cRPQCIOEChkhlPCxBwZ/WG2K9AkrD6ovD4eYR+ZzKntobd9pGHnZNzkHCBQwTK7oP
|
||||
heVtPhwGZVD8hza3BrtJeK+9If109bXbE7NP7z56MjbzaPD2gxvj9/rGpiHhAoYweWf2ydjD
|
||||
J5XdE/rULJCA8I9oD6l4YMdxVkPf5O2Hj6Gb1v6Jxt6x+p6R2q7hmq6hmqsfsmsIhjAJS1AA
|
||||
ZZMPHtf3ToAQ5AD53dpDCglpWPmnVgzfne0YmKi+Olje1l/SdKPwcm9+4/W8hmv8Sz3/TBjC
|
||||
JCxBAZRBMUhACHKACCAFf5f+MNouZ+t7rg1Plbf05Tf05NRezarqTK9sT7vQlnqhlVf+rwmT
|
||||
sAQFUAbFIAEhyAECKACuWG+ioqJ4PEEaT85vvNbQPZhb3Z5a3pxcciWhsJHFr4s4UxGSWhyU
|
||||
kk9LzjvJLQjNKIvKrWHlXWLnN0DGQhY0xBU0JhZdBgkIQQ4QQEkT3AEL8E/tb82aNd9++608
|
||||
3pGdf+liay+3pDEur5aZUx2WXUXnFvsxuawAymknC/6hA3wjrRxrfZanm184JyApn5FZEXqm
|
||||
+resCjtTHZ5TDUKQAwRQsQWXAAtwsPikFuXk5LQMLfB+py62XI87Vx2WWU5PLQ3glnon5lMo
|
||||
YVV7dzYqS7fs2typvaX74NYegkw3fstlM3WOv/sJVo5vynk/bpk/70Nyyyjc90KQAwRQAAQs
|
||||
wMFi+f2hUCh9ff3Nhj6ll7ujz1wITCn0jOe7x/Ld4vLsQ9MTbCyadmzp0pHpNZa7aaUwZKc4
|
||||
4qg06qw0fEyh6YSBLZ3lEs2xDUt3YvNd4wvdIGPzXVhnnSIyncNTfWKzmVmlgAU4WIDR8rdQ
|
||||
0+CIQ9RZTl6Vd2yOU2SWXVjm0fCso+FnSP7xJSZaXQdk+g8rjDgoTXptn6Kq3GWo3g1RmQne
|
||||
Hu3n7ptI49Qf9ub4HaYyTSgJJEqiqV+siXeYsZeHGd3KISyIHJUBWICDxfI3UkdH53ND76zy
|
||||
y+4xWUeDuebUZDMa1zQozTgoneQS1GG0vf+w/Jib8hRNZSZK9X6i2kOu2kOe6lzSTksPGvu8
|
||||
b3a7aXIDIaKU6JthcTzOyjKGhGfq7ozQNjplQPTwtaZxAAtwsACj5fSHxWIPEs32eSSGphZZ
|
||||
0ThGPnEE73i8XzI+MHW/b7KX7bE+823wsd4JUrkXqzabrj53Tv37IvXHpaoDSbp495NFPQHn
|
||||
rzvyOy3Tmg2jqvA+BXjbLD2jFN2v2TqkaEttexrRmw1YgOt4JoIR2H10i7D56vpHvRLzHUO5
|
||||
RC+WzolobXKslhdHy4+3243NtSIM2ipOUbbPsFRnM94396RK7ekltR+bVNIYNocC6Y3D4bU3
|
||||
KWXXXc51WnKvGIRdIJDPESxTdfFJB/ABx/ccZwAQsAD35uSD0XI+aw0NjS8IbjRekTklfv+J
|
||||
qL3OzN2ubA13zk5yyi47RrPlrlEXpekI1Udp6o9L1J81qv/YofZjl8rLDjVrd+/ANEbXZELT
|
||||
UHhtv39Jj0N2GymulhBQSLDL0jXnETQdPXY5RAAQsACn8YrBCOw+usV9+/ZJG/kH8gqNfWK1
|
||||
XJkajswdzmw1N46SK8fCynncRuGOs1zDCc0cd3wO+WAL7asn+TIvhxRnazUVbOj5HfF9d9I6
|
||||
xmIbbzEqesl5V625lw0YpQSXHD3zRDPlI4HqjtEABCzAweJzY3+w++gW4SzAGVIdos6QKAna
|
||||
J2LUjjPl7KKkbdlrrWK0zVzNzWzlTX2/sAyRs4uWOxa1/nCwvHlggptuNl1f4Ri1dyb75nRW
|
||||
z2RSyzCzpt+/uNs+o8UospJA5uO/pR3daEaXs2MCELAABwswAruPbpFIJKJ0KVtJ/qrW9A1E
|
||||
XxG8L8qAhjAJQxgzJCyi1nvzZZKum5TO+DQ8iu99nj70glp5U/UEB3uUrR9BH3mYNz7Lvz7F
|
||||
axtl1d0MLLnmcLrVhFWDpxQbKhx3RhjQAAVAwAIcLMAI7JbVoh5VYI+9gKadgJYLQtcHRTyJ
|
||||
MosUIYVsiO4QT+rdkX3LtmT8ZP1MRs/cxdFnLdMvWr9bkCbz1jvGaDG8c1qZ3be53ZNxV4aC
|
||||
ynqd0lpIXgUG+0NI4uYBAAEUAAH7Hr7HHoyW0yLsvBCeioDmvnFA6rgj8RSUSSjKLGK9bezG
|
||||
qDYcp2f76UGrojFqzfSpzkdlw0+b777gtN1XIEc3N3H/Qonf4MhU8qIdCPPRZ5K/prlucybL
|
||||
2nhtsKSgLNkoq1hAARCwAAcLMFrOBw3fX3G8P0LHE/FXR+R+T6Q+FfpDkULlvHIlw5pw8V0y
|
||||
GTeN8kc8K6dimh/k3nhcM/nS4lQ1MSjgl8el774/33TlVEByFDEoVD+Q7hzikRJnOXZ6Z3Cs
|
||||
B+ooB2WTCCgAAhbgYAFGy7ld4BT4jEBG4AMRWk5IXW8kkY46FClIYsjQK9cGN0iyOtZz+77O
|
||||
HbIrmaDWTie0z5658eKrQF5atuub7yp/vs9/PZ26MBX5btzz3YjZuwGNX9sVnxRLawVECx7j
|
||||
oWxTUOZRAAQswMFCWp+8nEPnw9FtizCJRGi7IPV8kEbwRQyXtGZK0WpxtPp1kS1rE3tgI/H8
|
||||
EcfSCVrddMDFB7LenOkuj9f3sl7fSXgzGf52zG9hxHbx1r7Fa6rz9dtaMvdscE0Rcs0WtOeh
|
||||
LGIACFiAgwUYLefoXnoAIk2jEbpeCLwv0jgYZcJQcOchvSowlOr1jEapmA6plN5tWQN4/rBd
|
||||
6W3D5JadtJh3k/5vJxhvxwPnR90Xhm0Wbuku9qm/bVZ+dX4LK8FJ1C1bhMwXPJ4G30gAAhbg
|
||||
YLHMB6DAh9cIHDEAQWIi9LyRxgwUkaYSVLqGXC4cUC1Or8OFNGKj29Ym98pkDu4+O7GDcdYv
|
||||
yf3Xcef5kWPzw0cWhowXB7UWe9XnW5ReX/zyae5nh0KZYr4lol6FQo4ZglZxSJMQwAIcRwzc
|
||||
v3//cvqDkJeX1zQ8grRKRujD7czAWYVvpZULO2aKOKaLuZ7GkHNEPc8J+RSJhF/ZxBuVo2c2
|
||||
Vxr8Mnxg8Zb2wsDexRtfLXRvf3tF6eeLiq8K5AbTlBQDMrHUKrRPiYhzpuCROJRpCGCR1slg
|
||||
AUbLbHHplVbSiIqwSUIR6aIWTJEjbDHHVAm/4rUh9djoFgyrDRPViDl5YV3wReXwjHc9Kotd
|
||||
ygtXt8+3K79tUnpd++Wrsm0v8uSeZ3yez9Ff61+EO1mH8T0v6pIlBC0aBQEWZ0T9pFfapY2E
|
||||
d3eULU/QMkbYioV2zhT3LcYF1+Ni2sU5vRLcAVzakETqAJrXKxtfVJ6q97JKcb5m25sKhZ/P
|
||||
y78qkH2Zu/V55pY53mZ3FlUiuBqE4r4laJcsYWs2AAEL8OVv4VL84+eVgasguUDEJh5axPqW
|
||||
4Bj14uxObHIfLvUWLmtULHdSJG9K5NyoGK9Njx2TmGTRkaE5dFqtP31HXdI3kUxLAp2xLqxC
|
||||
PKoFhCAHCKAEyYXyhq4r8PNK4LcfqRuMKaKB5WLOGVifIonQS5jYq9iUflz6sHj2OLrgLvrC
|
||||
A7HaObG6R+jKO+iiQWx2x8a0unUptWhOMyahTYLTjeVcx7A7QQhygABqg3EAYNFo9Kf2txSS
|
||||
kpIEojHONBgbUYejlonDLsZ3SXBvwhZi+FNiFx5gLn2PaX0mdvVvYl3P32fHM0zzD5i6R2Ll
|
||||
96EAyqAYJCAEOTayHmfKACBgV6a/pZCWlsYbGm8ypkhE1WJTOsXjunC8AVzOOKZkBlM3h2l7
|
||||
hrn2Qqz/FXrgJ0i4gOH7SVgqmYEyKAYJCEG+CfbP0BiAK9nfUkhJSR3UwysYOKN9z+IKbknl
|
||||
jK7NncCU3xe/8gOm+7nYwE+io2+EJ95CwgUMYfL9Uvl9KINikKD9zoEcIIBa+f6WAr6X8LyH
|
||||
21DKnIGNrpGsmMJdnpNofyre+xI9/Ebo9gJy+hdIuIAhTMISFEAZNqYWJCAE+Qr8SfLfA25A
|
||||
eJ7CYbbb8Mg6Ek3YL1c0pwvTeg89/Fzo3jziu18h4QKGMAlLwv5npcxoUAwSOF9W4P79HwMO
|
||||
2/f/pWhpweN1h76trIGbFCkQZx8p5MSBhAspMypMwhIUQBkUf9L5/CkhLCwsIyOjrq4OJxx8
|
||||
iMYfAi5gCJOysrJQ8Od0thqrsRqrsRr/Ltb851zB+DtwIBrFFstMPwAAAABJRU5ErkJggg==</icon>
|
||||
</operatingsystem>
|
||||
</operatingsystems>
|
||||
@@ -16,7 +16,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*)
|
||||
|
||||
(* Note that we use ordinary OCaml ints, which means this program is
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#
|
||||
# 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.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
include $(top_srcdir)/subdir-rules.mk
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#
|
||||
# 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.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
include $(top_srcdir)/subdir-rules.mk
|
||||
|
||||
@@ -94,6 +94,8 @@ guestfsd_SOURCES = \
|
||||
checksum.c \
|
||||
cmp.c \
|
||||
command.c \
|
||||
compress.c \
|
||||
copy.c \
|
||||
cpmv.c \
|
||||
daemon.h \
|
||||
dd.c \
|
||||
@@ -127,6 +129,7 @@ guestfsd_SOURCES = \
|
||||
luks.c \
|
||||
lvm.c \
|
||||
lvm-filter.c \
|
||||
md.c \
|
||||
mkfs.c \
|
||||
mknod.c \
|
||||
modprobe.c \
|
||||
@@ -163,7 +166,7 @@ guestfsd_LDADD = \
|
||||
liberrnostring.a \
|
||||
libprotocol.a \
|
||||
$(SELINUX_LIB) \
|
||||
$(AUGEAS_LIB) \
|
||||
$(AUGEAS_LIBS) \
|
||||
$(top_builddir)/gnulib/lib/.libs/libgnu.a \
|
||||
$(GETADDRINFO_LIB) \
|
||||
$(HOSTENT_LIB) \
|
||||
@@ -173,7 +176,7 @@ guestfsd_LDADD = \
|
||||
$(LIBINTL) \
|
||||
$(SERVENT_LIB)
|
||||
|
||||
guestfsd_CPPFLAGS = -I$(top_srcdir)/gnulib/lib
|
||||
guestfsd_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS)
|
||||
guestfsd_CPPFLAGS = -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib
|
||||
guestfsd_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS) $(AUGEAS_CFLAGS)
|
||||
|
||||
.PHONY: force
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
143
daemon/blkid.c
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -83,3 +83,144 @@ do_vfs_uuid (const char *device)
|
||||
{
|
||||
return get_blkid_tag (device, "UUID");
|
||||
}
|
||||
|
||||
/* RHEL5 blkid doesn't have the -p(partition info) option and the
|
||||
* -i(I/O limits) option so we must test for these options the first
|
||||
* time the function is called.
|
||||
*/
|
||||
static int
|
||||
test_blkid_p_opt(void)
|
||||
{
|
||||
static int result;
|
||||
char *err = NULL;
|
||||
|
||||
int r = commandr(NULL, &err, "blkid", "-p", "/dev/null", NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error("could not run 'blkid' command: %s", err);
|
||||
free(err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strstr(err, "invalid option --"))
|
||||
result = 0;
|
||||
else
|
||||
result = 1;
|
||||
free(err);
|
||||
return result;
|
||||
}
|
||||
|
||||
static char **
|
||||
blkid_with_p_opt(const char *device)
|
||||
{
|
||||
int r;
|
||||
char *out = NULL, *err = NULL;
|
||||
char **lines = NULL;
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
|
||||
r = command(&out, &err, "blkid", "-c", "/dev/null",
|
||||
"-p", "-i", "-o", "export", device, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error("%s", err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Split the command output into lines */
|
||||
lines = split_lines(out);
|
||||
if (lines == NULL) {
|
||||
reply_with_perror("malloc");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Parse the output of blkid -p -i -o export:
|
||||
* UUID=b6d83437-c6b4-4bf0-8381-ef3fc3578590
|
||||
* VERSION=1.0
|
||||
* TYPE=ext2
|
||||
* USAGE=filesystem
|
||||
* MINIMUM_IO_SIZE=512
|
||||
* PHYSICAL_SECTOR_SIZE=512
|
||||
* LOGICAL_SECTOR_SIZE=512
|
||||
* PART_ENTRY_SCHEME=dos
|
||||
* PART_ENTRY_TYPE=0x83
|
||||
* PART_ENTRY_NUMBER=6
|
||||
* PART_ENTRY_OFFSET=642875153
|
||||
* PART_ENTRY_SIZE=104857600
|
||||
* PART_ENTRY_DISK=8:0
|
||||
*/
|
||||
for (char **i = lines; *i != NULL; i++) {
|
||||
char *line = *i;
|
||||
|
||||
/* Skip blank lines (shouldn't happen) */
|
||||
if (line[0] == '\0') continue;
|
||||
|
||||
/* Split the line in 2 at the equals sign */
|
||||
char *eq = strchr(line, '=');
|
||||
if (eq) {
|
||||
*eq = '\0'; eq++;
|
||||
|
||||
/* Add the key/value pair to the output */
|
||||
if (add_string(&ret, &size, &alloc, line) == -1 ||
|
||||
add_string(&ret, &size, &alloc, eq) == -1) goto error;
|
||||
} else {
|
||||
fprintf(stderr, "blkid: unexpected blkid output ignored: %s", line);
|
||||
}
|
||||
}
|
||||
|
||||
if (add_string(&ret, &size, &alloc, NULL) == -1) goto error;
|
||||
|
||||
free(out);
|
||||
free(err);
|
||||
free(lines);
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
free(out);
|
||||
free(err);
|
||||
if (lines) free(lines);
|
||||
if (ret) free_strings(ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char **
|
||||
blkid_without_p_opt(const char *device)
|
||||
{
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
|
||||
if (add_string(&ret, &size, &alloc, "TYPE") == -1) goto error;
|
||||
if (add_string(&ret, &size, &alloc, get_blkid_tag(device, "TYPE")) == -1)
|
||||
goto error;
|
||||
if (add_string(&ret, &size, &alloc, "LABEL") == -1) goto error;
|
||||
if (add_string(&ret, &size, &alloc, get_blkid_tag(device, "LABEL")) == -1)
|
||||
goto error;
|
||||
if (add_string(&ret, &size, &alloc, "UUID") == -1) goto error;
|
||||
if (add_string(&ret, &size, &alloc, get_blkid_tag(device, "UUID")) == -1)
|
||||
goto error;
|
||||
if (add_string_nodup(&ret, &size, &alloc, NULL) == -1) goto error;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
if (ret) free_strings(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char **
|
||||
do_blkid(const char *device)
|
||||
{
|
||||
int r;
|
||||
char *out = NULL, *err = NULL;
|
||||
char **lines = NULL;
|
||||
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
int blkid_has_p_opt;
|
||||
|
||||
if ((blkid_has_p_opt = test_blkid_p_opt()) == -1)
|
||||
return NULL;
|
||||
else if (blkid_has_p_opt)
|
||||
return blkid_with_p_opt(device);
|
||||
else
|
||||
return blkid_without_p_opt(device);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "actions.h"
|
||||
#include "optgroups.h"
|
||||
|
||||
#define MAX_ARGS 64
|
||||
|
||||
int
|
||||
optgroup_btrfs_available (void)
|
||||
{
|
||||
@@ -41,13 +43,13 @@ do_btrfs_filesystem_resize (const char *filesystem, int64_t size)
|
||||
char *buf;
|
||||
char *err;
|
||||
int r;
|
||||
const char *argv[16];
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0;
|
||||
char size_str[32];
|
||||
|
||||
argv[i++] = "btrfs";
|
||||
argv[i++] = "filesystem";
|
||||
argv[i++] = "resize";
|
||||
ADD_ARG (argv, i, "btrfs");
|
||||
ADD_ARG (argv, i, "filesystem");
|
||||
ADD_ARG (argv, i, "resize");
|
||||
|
||||
if (optargs_bitmask & GUESTFS_BTRFS_FILESYSTEM_RESIZE_SIZE_BITMASK) {
|
||||
if (size <= 0) {
|
||||
@@ -56,10 +58,10 @@ do_btrfs_filesystem_resize (const char *filesystem, int64_t size)
|
||||
}
|
||||
|
||||
snprintf (size_str, sizeof size_str, "%" PRIi64, size);
|
||||
argv[i++] = size_str;
|
||||
ADD_ARG (argv, i, size_str);
|
||||
}
|
||||
else
|
||||
argv[i++] = "max";
|
||||
ADD_ARG (argv, i, "max");
|
||||
|
||||
buf = sysroot_path (filesystem);
|
||||
if (!buf) {
|
||||
@@ -67,8 +69,8 @@ do_btrfs_filesystem_resize (const char *filesystem, int64_t size)
|
||||
return -1;
|
||||
}
|
||||
|
||||
argv[i++] = buf;
|
||||
argv[i++] = NULL;
|
||||
ADD_ARG (argv, i, buf);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
free (buf);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
207
daemon/compress.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "guestfs_protocol.h"
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
|
||||
/* Has one FileOut parameter. */
|
||||
static int
|
||||
do_compressX_out (const char *file, const char *filter, int is_device)
|
||||
{
|
||||
int r;
|
||||
FILE *fp;
|
||||
char *cmd;
|
||||
char buf[GUESTFS_MAX_CHUNK_SIZE];
|
||||
|
||||
/* The command will look something like:
|
||||
* gzip -c /sysroot%s # file
|
||||
* or:
|
||||
* gzip -c < %s # device
|
||||
*
|
||||
* We have to quote the file or device name.
|
||||
*
|
||||
* The unnecessary redirect for devices is there because lzop
|
||||
* unhelpfully refuses to compress anything that isn't a regular
|
||||
* file.
|
||||
*/
|
||||
if (!is_device) {
|
||||
if (asprintf_nowarn (&cmd, "%s %R", filter, file) == -1) {
|
||||
reply_with_perror ("asprintf");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (asprintf_nowarn (&cmd, "%s < %Q", filter, file) == -1) {
|
||||
reply_with_perror ("asprintf");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
fprintf (stderr, "%s\n", cmd);
|
||||
|
||||
fp = popen (cmd, "r");
|
||||
if (fp == NULL) {
|
||||
reply_with_perror ("%s", cmd);
|
||||
free (cmd);
|
||||
return -1;
|
||||
}
|
||||
free (cmd);
|
||||
|
||||
/* Now we must send the reply message, before the file contents. After
|
||||
* this there is no opportunity in the protocol to send any error
|
||||
* message back. Instead we can only cancel the transfer.
|
||||
*/
|
||||
reply (NULL, NULL);
|
||||
|
||||
while ((r = fread (buf, 1, sizeof buf, fp)) > 0) {
|
||||
if (send_file_write (buf, r) < 0) {
|
||||
pclose (fp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ferror (fp)) {
|
||||
perror (file);
|
||||
send_file_end (1); /* Cancel. */
|
||||
pclose (fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pclose (fp) != 0) {
|
||||
perror (file);
|
||||
send_file_end (1); /* Cancel. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (send_file_end (0)) /* Normal end of file. */
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CHECK_SUPPORTED(prog) \
|
||||
if (!prog_exists (prog)) { \
|
||||
/* note: substring "not supported" must appear in this error */ \
|
||||
reply_with_error ("compression type %s is not supported", prog); \
|
||||
return -1; \
|
||||
}
|
||||
|
||||
static int
|
||||
get_filter (const char *ctype, int level, char *ret, size_t n)
|
||||
{
|
||||
if (STREQ (ctype, "compress")) {
|
||||
CHECK_SUPPORTED ("compress");
|
||||
if (level != -1) {
|
||||
reply_with_error ("compress: cannot use optional level parameter with this compression type");
|
||||
return -1;
|
||||
}
|
||||
snprintf (ret, n, "compress -c");
|
||||
return 0;
|
||||
}
|
||||
else if (STREQ (ctype, "gzip")) {
|
||||
CHECK_SUPPORTED ("gzip");
|
||||
if (level == -1)
|
||||
snprintf (ret, n, "gzip -c");
|
||||
else if (level >= 1 && level <= 9)
|
||||
snprintf (ret, n, "gzip -c -%d", level);
|
||||
else {
|
||||
reply_with_error ("gzip: incorrect value for level parameter");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (STREQ (ctype, "bzip2")) {
|
||||
CHECK_SUPPORTED ("bzip2");
|
||||
if (level == -1)
|
||||
snprintf (ret, n, "bzip2 -c");
|
||||
else if (level >= 1 && level <= 9)
|
||||
snprintf (ret, n, "bzip2 -c -%d", level);
|
||||
else {
|
||||
reply_with_error ("bzip2: incorrect value for level parameter");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (STREQ (ctype, "xz")) {
|
||||
CHECK_SUPPORTED ("xz");
|
||||
if (level == -1)
|
||||
snprintf (ret, n, "xz -c");
|
||||
else if (level >= 0 && level <= 9)
|
||||
snprintf (ret, n, "xz -c -%d", level);
|
||||
else {
|
||||
reply_with_error ("xz: incorrect value for level parameter");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (STREQ (ctype, "lzop")) {
|
||||
CHECK_SUPPORTED ("lzop");
|
||||
if (level == -1)
|
||||
snprintf (ret, n, "lzop -c");
|
||||
else if (level >= 1 && level <= 9)
|
||||
snprintf (ret, n, "lzop -c -%d", level);
|
||||
else {
|
||||
reply_with_error ("lzop: incorrect value for level parameter");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
reply_with_error ("unknown compression type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Has one FileOut parameter. */
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_compress_out (const char *ctype, const char *file, int level)
|
||||
{
|
||||
char filter[64];
|
||||
|
||||
if (!(optargs_bitmask & GUESTFS_COMPRESS_OUT_LEVEL_BITMASK))
|
||||
level = -1;
|
||||
|
||||
if (get_filter (ctype, level, filter, sizeof filter) == -1)
|
||||
return -1;
|
||||
|
||||
return do_compressX_out (file, filter, 0);
|
||||
}
|
||||
|
||||
/* Has one FileOut parameter. */
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_compress_device_out (const char *ctype, const char *file, int level)
|
||||
{
|
||||
char filter[64];
|
||||
|
||||
if (!(optargs_bitmask & GUESTFS_COMPRESS_DEVICE_OUT_LEVEL_BITMASK))
|
||||
level = -1;
|
||||
|
||||
if (get_filter (ctype, level, filter, sizeof filter) == -1)
|
||||
return -1;
|
||||
|
||||
return do_compressX_out (file, filter, 1);
|
||||
}
|
||||
242
daemon/copy.c
Normal file
@@ -0,0 +1,242 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "guestfs_protocol.h"
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
|
||||
#define DEST_FILE_FLAGS O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666
|
||||
#define DEST_DEVICE_FLAGS O_WRONLY, 0
|
||||
|
||||
/* NB: We cheat slightly by assuming that optargs_bitmask is
|
||||
* compatible for all four of the calls. This is true provided they
|
||||
* all take the same set of optional arguments.
|
||||
*/
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
static int
|
||||
copy (const char *src, const char *src_display,
|
||||
const char *dest, const char *dest_display,
|
||||
int wrflags, int wrmode,
|
||||
int64_t srcoffset, int64_t destoffset, int64_t size)
|
||||
{
|
||||
int64_t saved_size = size;
|
||||
int src_fd, dest_fd;
|
||||
char buf[BUFSIZ];
|
||||
size_t n;
|
||||
ssize_t r;
|
||||
|
||||
if ((optargs_bitmask & GUESTFS_COPY_DEVICE_TO_DEVICE_SRCOFFSET_BITMASK)) {
|
||||
if (srcoffset < 0) {
|
||||
reply_with_error ("srcoffset is negative");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
srcoffset = 0;
|
||||
|
||||
if ((optargs_bitmask & GUESTFS_COPY_DEVICE_TO_DEVICE_DESTOFFSET_BITMASK)) {
|
||||
if (destoffset < 0) {
|
||||
reply_with_error ("destoffset is negative");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
destoffset = 0;
|
||||
|
||||
if ((optargs_bitmask & GUESTFS_COPY_DEVICE_TO_DEVICE_SIZE_BITMASK)) {
|
||||
if (size < 0) {
|
||||
reply_with_error ("size is negative");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
size = -1;
|
||||
|
||||
/* Open source and destination. */
|
||||
src_fd = open (src, O_RDONLY);
|
||||
if (src_fd == -1) {
|
||||
reply_with_perror ("%s", src_display);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (srcoffset > 0 && lseek (src_fd, srcoffset, SEEK_SET) == (off_t) -1) {
|
||||
reply_with_perror ("lseek: %s", src_display);
|
||||
close (src_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dest_fd = open (dest, wrflags, wrmode);
|
||||
if (dest_fd == -1) {
|
||||
reply_with_perror ("%s", dest_display);
|
||||
close (src_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (destoffset > 0 && lseek (dest_fd, destoffset, SEEK_SET) == (off_t) -1) {
|
||||
reply_with_perror ("lseek: %s", dest_display);
|
||||
close (src_fd);
|
||||
close (dest_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (size == -1)
|
||||
pulse_mode_start ();
|
||||
|
||||
while (size != 0) {
|
||||
/* Calculate bytes to copy. */
|
||||
if (size == -1 || size > (int64_t) sizeof buf)
|
||||
n = sizeof buf;
|
||||
else
|
||||
n = size;
|
||||
|
||||
r = read (src_fd, buf, n);
|
||||
if (r == -1) {
|
||||
if (size == -1)
|
||||
pulse_mode_cancel ();
|
||||
reply_with_perror ("read: %s", src_display);
|
||||
close (src_fd);
|
||||
close (dest_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (r == 0) {
|
||||
if (size == -1) /* if size == -1, this is normal end of loop */
|
||||
break;
|
||||
reply_with_error ("%s: input too short", src_display);
|
||||
close (src_fd);
|
||||
close (dest_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (xwrite (dest_fd, buf, r) == -1) {
|
||||
if (size == -1)
|
||||
pulse_mode_cancel ();
|
||||
reply_with_perror ("%s: write", dest_display);
|
||||
close (src_fd);
|
||||
close (dest_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (size != -1) {
|
||||
size -= r;
|
||||
notify_progress ((uint64_t) (saved_size - size), (uint64_t) saved_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (size == -1)
|
||||
pulse_mode_end ();
|
||||
|
||||
if (close (src_fd) == -1) {
|
||||
reply_with_perror ("close: %s", src_display);
|
||||
close (dest_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (close (dest_fd) == -1) {
|
||||
reply_with_perror ("close: %s", dest_display);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_copy_device_to_device (const char *src, const char *dest,
|
||||
int64_t srcoffset, int64_t destoffset, int64_t size)
|
||||
{
|
||||
return copy (src, src, dest, dest, DEST_DEVICE_FLAGS,
|
||||
srcoffset, destoffset, size);
|
||||
}
|
||||
|
||||
int
|
||||
do_copy_device_to_file (const char *src, const char *dest,
|
||||
int64_t srcoffset, int64_t destoffset, int64_t size)
|
||||
{
|
||||
char *dest_buf;
|
||||
int r;
|
||||
|
||||
dest_buf = sysroot_path (dest);
|
||||
if (!dest_buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = copy (src, src, dest_buf, dest, DEST_FILE_FLAGS,
|
||||
srcoffset, destoffset, size);
|
||||
free (dest_buf);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
do_copy_file_to_device (const char *src, const char *dest,
|
||||
int64_t srcoffset, int64_t destoffset, int64_t size)
|
||||
{
|
||||
char *src_buf;
|
||||
int r;
|
||||
|
||||
src_buf = sysroot_path (src);
|
||||
if (!src_buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = copy (src_buf, src, dest, dest, DEST_DEVICE_FLAGS,
|
||||
srcoffset, destoffset, size);
|
||||
free (src_buf);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
do_copy_file_to_file (const char *src, const char *dest,
|
||||
int64_t srcoffset, int64_t destoffset, int64_t size)
|
||||
{
|
||||
char *src_buf, *dest_buf;
|
||||
int r;
|
||||
|
||||
src_buf = sysroot_path (src);
|
||||
if (!src_buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dest_buf = sysroot_path (dest);
|
||||
if (!dest_buf) {
|
||||
reply_with_perror ("malloc");
|
||||
free (src_buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = copy (src_buf, src, dest_buf, dest, DEST_FILE_FLAGS,
|
||||
srcoffset, destoffset, size);
|
||||
free (src_buf);
|
||||
free (dest_buf);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -47,6 +47,7 @@ extern int xwrite (int sock, const void *buf, size_t len)
|
||||
extern int xread (int sock, void *buf, size_t len)
|
||||
__attribute__((__warn_unused_result__));
|
||||
|
||||
extern int add_string_nodup (char ***argv, int *size, int *alloc, char *str);
|
||||
extern int add_string (char ***argv, int *size, int *alloc, const char *str);
|
||||
extern size_t count_strings (char *const *argv);
|
||||
extern void sort_strings (char **argv, int len);
|
||||
@@ -134,6 +135,9 @@ extern int e2prog (char *name); /* Massive hack for RHEL 5. */
|
||||
/*-- in lvm.c --*/
|
||||
extern int lv_canonical (const char *device, char **ret);
|
||||
|
||||
/*-- in lvm-filter.c --*/
|
||||
extern void copy_lvm (void);
|
||||
|
||||
/*-- in proto.c --*/
|
||||
extern void main_loop (int sock) __attribute__((noreturn));
|
||||
|
||||
@@ -191,6 +195,36 @@ extern void pulse_mode_start (void);
|
||||
extern void pulse_mode_end (void);
|
||||
extern void pulse_mode_cancel (void);
|
||||
|
||||
/* Return true iff the buffer is all zero bytes.
|
||||
*
|
||||
* Note that gcc is smart enough to optimize this properly:
|
||||
* http://stackoverflow.com/questions/1493936/faster-means-of-checking-for-an-empty-buffer-in-c/1493989#1493989
|
||||
*/
|
||||
static inline int
|
||||
is_zero (const char *buffer, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
if (buffer[i] != 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Helper for building up short lists of arguments. Your code has to
|
||||
* define MAX_ARGS to a suitable value.
|
||||
*/
|
||||
#define ADD_ARG(argv,i,v) \
|
||||
do { \
|
||||
if ((i) >= MAX_ARGS) { \
|
||||
fprintf (stderr, "%s: %d: internal error: exceeded MAX_ARGS (%zu) when constructing the command line\n", __FILE__, __LINE__, (size_t) MAX_ARGS); \
|
||||
abort (); \
|
||||
} \
|
||||
(argv)[(i)++] = (v); \
|
||||
} while (0)
|
||||
|
||||
/* Helper for functions that need a root filesystem mounted.
|
||||
* NB. Cannot be used for FileIn functions.
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -92,7 +92,7 @@ do_debug (const char *subcmd, char *const *argv)
|
||||
return cmds[i].f (subcmd, argc, argv);
|
||||
}
|
||||
|
||||
reply_with_error ("use 'debug help' to list the supported commands");
|
||||
reply_with_error ("use 'debug help 0' to list the supported commands");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -198,7 +198,13 @@ debug_fds (const char *subcmd, int argc, char *const *const argv)
|
||||
static char *
|
||||
debug_segv (const char *subcmd, int argc, char *const *const argv)
|
||||
{
|
||||
*(int*)0 = 0;
|
||||
/* http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
|
||||
* "Dereferencing a NULL Pointer: contrary to popular belief,
|
||||
* dereferencing a null pointer in C is undefined. It is not defined
|
||||
* to trap [...]"
|
||||
*/
|
||||
volatile int *ptr = NULL;
|
||||
*ptr = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -280,7 +286,9 @@ debug_env (const char *subcmd, int argc, char *const *const argv)
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Return binaries in the appliance. See regressions/rhbz727178.sh */
|
||||
/* Return binaries in the appliance.
|
||||
* See tests/regressions/rhbz727178.sh
|
||||
*/
|
||||
static char *
|
||||
debug_binaries (const char *subcmd, int argc, char *const *const argv)
|
||||
{
|
||||
@@ -306,7 +314,9 @@ debug_binaries (const char *subcmd, int argc, char *const *const argv)
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Run 'ldd' on a file from the appliance. See regressions/rhbz727178.sh */
|
||||
/* Run 'ldd' on a file from the appliance.
|
||||
* See tests/regressions/rhbz727178.sh
|
||||
*/
|
||||
static char *
|
||||
debug_ldd (const char *subcmd, int argc, char *const *const argv)
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -220,3 +220,28 @@ do_part_to_dev (const char *part)
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
do_part_to_partnum (const char *part)
|
||||
{
|
||||
int err = 1;
|
||||
size_t n = strlen (part);
|
||||
|
||||
while (n >= 1 && c_isdigit (part[n-1])) {
|
||||
err = 0;
|
||||
n--;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
reply_with_error ("device name is not a partition");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int r;
|
||||
if (sscanf (&part[n], "%d", &r) != 1) {
|
||||
reply_with_error ("could not parse number");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
237
daemon/ext2.c
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -32,6 +32,8 @@
|
||||
/* Confirmed this is true up to ext4 from the Linux sources. */
|
||||
#define EXT2_LABEL_MAX 16
|
||||
|
||||
#define MAX_ARGS 64
|
||||
|
||||
/* Choose which tools like mke2fs to use. For RHEL 5 (only) there
|
||||
* is a special set of tools which support ext2/3/4. eg. On RHEL 5,
|
||||
* mke2fs only supports ext2/3, but mke4fs supports ext2/3/4.
|
||||
@@ -275,8 +277,67 @@ do_resize2fs_M (const char *device)
|
||||
if (e2prog (prog) == -1)
|
||||
return -1;
|
||||
|
||||
r = command (NULL, &err, prog, "-M" , device, NULL);
|
||||
r = command (NULL, &err, prog, "-M", device, NULL);
|
||||
if (r == -1) {
|
||||
if (strstr (err, "e2fsck -f"))
|
||||
reply_with_error ("you need to run e2fsck with the correct and/or forceall options first");
|
||||
else
|
||||
reply_with_error ("%s", err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_e2fsck (const char *device,
|
||||
int correct,
|
||||
int forceall)
|
||||
{
|
||||
const char *argv[MAX_ARGS];
|
||||
char *err;
|
||||
size_t i = 0;
|
||||
int r;
|
||||
char prog[] = "e2fsck";
|
||||
|
||||
if (e2prog (prog) == -1)
|
||||
return -1;
|
||||
|
||||
/* Default if not selected. */
|
||||
if (!(optargs_bitmask & GUESTFS_E2FSCK_CORRECT_BITMASK))
|
||||
correct = 0;
|
||||
if (!(optargs_bitmask & GUESTFS_E2FSCK_FORCEALL_BITMASK))
|
||||
forceall = 0;
|
||||
|
||||
if (correct && forceall) {
|
||||
reply_with_error("Only one of the options may be specified");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ADD_ARG (argv, i, prog);
|
||||
ADD_ARG (argv, i, "-f");
|
||||
|
||||
if (correct)
|
||||
ADD_ARG (argv, i, "-p");
|
||||
|
||||
if (forceall)
|
||||
ADD_ARG (argv, i, "-y");
|
||||
|
||||
ADD_ARG (argv, i, device);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
/* 0 = no errors, 1 = errors corrected.
|
||||
*
|
||||
* >= 4 means uncorrected or other errors.
|
||||
*
|
||||
* 2, 3 means errors were corrected and we require a reboot. This is
|
||||
* a difficult corner case.
|
||||
*/
|
||||
if (r == -1 || r >= 2) {
|
||||
reply_with_error ("%s", err);
|
||||
free (err);
|
||||
return -1;
|
||||
@@ -289,29 +350,8 @@ do_resize2fs_M (const char *device)
|
||||
int
|
||||
do_e2fsck_f (const char *device)
|
||||
{
|
||||
char *err;
|
||||
int r;
|
||||
|
||||
char prog[] = "e2fsck";
|
||||
if (e2prog (prog) == -1)
|
||||
return -1;
|
||||
|
||||
/* 0 = no errors, 1 = errors corrected.
|
||||
*
|
||||
* >= 4 means uncorrected or other errors.
|
||||
*
|
||||
* 2, 3 means errors were corrected and we require a reboot. This is
|
||||
* a difficult corner case.
|
||||
*/
|
||||
r = commandr (NULL, &err, prog, "-p", "-f", device, NULL);
|
||||
if (r == -1 || r >= 2) {
|
||||
reply_with_error ("%s", err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return 0;
|
||||
optargs_bitmask = GUESTFS_E2FSCK_CORRECT_BITMASK;
|
||||
return do_e2fsck (device, 1, 0);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -498,3 +538,150 @@ do_mke2fs_JU (const char *fstype, int blocksize, const char *device,
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_tune2fs (const char *device, /* only required parameter */
|
||||
int force,
|
||||
int maxmountcount,
|
||||
int mountcount,
|
||||
const char *errorbehavior,
|
||||
int64_t group,
|
||||
int intervalbetweenchecks,
|
||||
int reservedblockspercentage,
|
||||
const char *lastmounteddirectory,
|
||||
int64_t reservedblockscount,
|
||||
int64_t user)
|
||||
{
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0;
|
||||
int r;
|
||||
char *err;
|
||||
char prog[] = "tune2fs";
|
||||
char maxmountcount_s[64];
|
||||
char mountcount_s[64];
|
||||
char group_s[64];
|
||||
char intervalbetweenchecks_s[64];
|
||||
char reservedblockspercentage_s[64];
|
||||
char reservedblockscount_s[64];
|
||||
char user_s[64];
|
||||
|
||||
if (e2prog (prog) == -1)
|
||||
return -1;
|
||||
|
||||
ADD_ARG (argv, i, prog);
|
||||
|
||||
if (optargs_bitmask & GUESTFS_TUNE2FS_FORCE_BITMASK) {
|
||||
if (force)
|
||||
ADD_ARG (argv, i, "-f");
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_TUNE2FS_MAXMOUNTCOUNT_BITMASK) {
|
||||
if (maxmountcount < 0) {
|
||||
reply_with_error ("maxmountcount cannot be negative");
|
||||
return -1;
|
||||
}
|
||||
ADD_ARG (argv, i, "-c");
|
||||
snprintf (maxmountcount_s, sizeof maxmountcount_s, "%d", maxmountcount);
|
||||
ADD_ARG (argv, i, maxmountcount_s);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_TUNE2FS_MOUNTCOUNT_BITMASK) {
|
||||
if (mountcount < 0) {
|
||||
reply_with_error ("mountcount cannot be negative");
|
||||
return -1;
|
||||
}
|
||||
ADD_ARG (argv, i, "-C");
|
||||
snprintf (mountcount_s, sizeof mountcount_s, "%d", mountcount);
|
||||
ADD_ARG (argv, i, mountcount_s);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_TUNE2FS_ERRORBEHAVIOR_BITMASK) {
|
||||
if (STRNEQ (errorbehavior, "continue") &&
|
||||
STRNEQ (errorbehavior, "remount-ro") &&
|
||||
STRNEQ (errorbehavior, "panic")) {
|
||||
reply_with_error ("invalid errorbehavior parameter: %s", errorbehavior);
|
||||
return -1;
|
||||
}
|
||||
ADD_ARG (argv, i, "-e");
|
||||
ADD_ARG (argv, i, errorbehavior);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_TUNE2FS_GROUP_BITMASK) {
|
||||
if (group < 0) {
|
||||
reply_with_error ("group cannot be negative");
|
||||
return -1;
|
||||
}
|
||||
ADD_ARG (argv, i, "-g");
|
||||
snprintf (group_s, sizeof group_s, "%" PRIi64, group);
|
||||
ADD_ARG (argv, i, group_s);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_TUNE2FS_INTERVALBETWEENCHECKS_BITMASK) {
|
||||
if (intervalbetweenchecks < 0) {
|
||||
reply_with_error ("intervalbetweenchecks cannot be negative");
|
||||
return -1;
|
||||
}
|
||||
ADD_ARG (argv, i, "-i");
|
||||
if (intervalbetweenchecks > 0) {
|
||||
/* -i <NN>s is not documented in the man page, but has been
|
||||
* supported in tune2fs for several years.
|
||||
*/
|
||||
snprintf (intervalbetweenchecks_s, sizeof intervalbetweenchecks_s,
|
||||
"%ds", intervalbetweenchecks);
|
||||
ADD_ARG (argv, i, intervalbetweenchecks_s);
|
||||
}
|
||||
else
|
||||
ADD_ARG (argv, i, "0");
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_TUNE2FS_RESERVEDBLOCKSPERCENTAGE_BITMASK) {
|
||||
if (reservedblockspercentage < 0) {
|
||||
reply_with_error ("reservedblockspercentage cannot be negative");
|
||||
return -1;
|
||||
}
|
||||
ADD_ARG (argv, i, "-m");
|
||||
snprintf (reservedblockspercentage_s, sizeof reservedblockspercentage_s,
|
||||
"%d", reservedblockspercentage);
|
||||
ADD_ARG (argv, i, reservedblockspercentage_s);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_TUNE2FS_LASTMOUNTEDDIRECTORY_BITMASK) {
|
||||
ADD_ARG (argv, i, "-M");
|
||||
ADD_ARG (argv, i, lastmounteddirectory);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_TUNE2FS_RESERVEDBLOCKSCOUNT_BITMASK) {
|
||||
if (reservedblockscount < 0) {
|
||||
reply_with_error ("reservedblockscount cannot be negative");
|
||||
return -1;
|
||||
}
|
||||
ADD_ARG (argv, i, "-r");
|
||||
snprintf (reservedblockscount_s, sizeof reservedblockscount_s,
|
||||
"%" PRIi64, reservedblockscount);
|
||||
ADD_ARG (argv, i, reservedblockscount_s);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_TUNE2FS_USER_BITMASK) {
|
||||
if (user < 0) {
|
||||
reply_with_error ("user cannot be negative");
|
||||
return -1;
|
||||
}
|
||||
ADD_ARG (argv, i, "-u");
|
||||
snprintf (user_s, sizeof user_s, "%" PRIi64, user);
|
||||
ADD_ARG (argv, i, user_s);
|
||||
}
|
||||
|
||||
ADD_ARG (argv, i, device);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s: %s", prog, device, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -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
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -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)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -111,6 +111,9 @@ int autosync_umount = 1;
|
||||
/* Not used explicitly, but required by the gnulib 'error' module. */
|
||||
const char *program_name = "guestfsd";
|
||||
|
||||
/* Name of the virtio-serial channel. */
|
||||
#define VIRTIO_SERIAL_CHANNEL "/dev/virtio-ports/org.libguestfs.channel.0"
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
@@ -236,9 +239,13 @@ main (int argc, char *argv[])
|
||||
_umask (0);
|
||||
#endif
|
||||
|
||||
/* Make a private copy of /etc/lvm so we can change the config (see
|
||||
* daemon/lvm-filter.c).
|
||||
*/
|
||||
copy_lvm ();
|
||||
|
||||
/* Connect to virtio-serial channel. */
|
||||
int sock = open ("/dev/virtio-ports/org.libguestfs.channel.0",
|
||||
O_RDWR | O_CLOEXEC);
|
||||
int sock = open (VIRTIO_SERIAL_CHANNEL, O_RDWR | O_CLOEXEC);
|
||||
if (sock == -1) {
|
||||
fprintf (stderr,
|
||||
"\n"
|
||||
@@ -253,7 +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");
|
||||
perror (VIRTIO_SERIAL_CHANNEL);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@@ -408,10 +415,9 @@ xread (int sock, void *v_buf, size_t len)
|
||||
}
|
||||
|
||||
int
|
||||
add_string (char ***argv, int *size, int *alloc, const char *str)
|
||||
add_string_nodup (char ***argv, int *size, int *alloc, char *str)
|
||||
{
|
||||
char **new_argv;
|
||||
char *new_str;
|
||||
|
||||
if (*size >= *alloc) {
|
||||
*alloc += 64;
|
||||
@@ -419,25 +425,36 @@ add_string (char ***argv, int *size, int *alloc, const char *str)
|
||||
if (new_argv == NULL) {
|
||||
reply_with_perror ("realloc");
|
||||
free_strings (*argv);
|
||||
*argv = NULL;
|
||||
return -1;
|
||||
}
|
||||
*argv = new_argv;
|
||||
}
|
||||
|
||||
(*argv)[*size] = str;
|
||||
|
||||
(*size)++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
add_string (char ***argv, int *size, int *alloc, const char *str)
|
||||
{
|
||||
char *new_str;
|
||||
|
||||
if (str) {
|
||||
new_str = strdup (str);
|
||||
if (new_str == NULL) {
|
||||
reply_with_perror ("strdup");
|
||||
free_strings (*argv);
|
||||
*argv = NULL;
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
new_str = NULL;
|
||||
}
|
||||
|
||||
(*argv)[*size] = new_str;
|
||||
|
||||
(*size)++;
|
||||
return 0;
|
||||
return add_string_nodup (argv, size, alloc, new_str);
|
||||
}
|
||||
|
||||
size_t
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -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
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -317,10 +317,21 @@ do_inotify_files (void)
|
||||
FILE *fp = NULL;
|
||||
guestfs_int_inotify_event_list *events;
|
||||
char buf[PATH_MAX];
|
||||
char tempfile[] = "/tmp/inotifyXXXXXX";
|
||||
int fd;
|
||||
char cmd[64];
|
||||
|
||||
NEED_INOTIFY (NULL);
|
||||
|
||||
fp = popen ("sort -u > /tmp/inotify", "w");
|
||||
fd = mkstemp (tempfile);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("mkstemp");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf (cmd, sizeof cmd, "sort -u > %s", tempfile);
|
||||
|
||||
fp = popen (cmd, "w");
|
||||
if (fp == NULL) {
|
||||
reply_with_perror ("sort");
|
||||
return NULL;
|
||||
@@ -349,9 +360,11 @@ do_inotify_files (void)
|
||||
|
||||
pclose (fp);
|
||||
|
||||
fp = fopen ("/tmp/inotify", "r");
|
||||
fp = fdopen (fd, "r");
|
||||
if (fp == NULL) {
|
||||
reply_with_perror ("/tmp/inotify");
|
||||
reply_with_perror ("%s", tempfile);
|
||||
unlink (tempfile);
|
||||
close (fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -365,20 +378,20 @@ do_inotify_files (void)
|
||||
goto error;
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
fclose (fp); /* implicitly closes fd */
|
||||
fp = NULL;
|
||||
|
||||
if (add_string (&ret, &size, &alloc, NULL) == -1)
|
||||
goto error;
|
||||
|
||||
unlink ("/tmp/inotify");
|
||||
unlink (tempfile);
|
||||
return ret;
|
||||
|
||||
error:
|
||||
if (fp != NULL)
|
||||
fclose (fp);
|
||||
|
||||
unlink ("/tmp/inotify");
|
||||
unlink (tempfile);
|
||||
return NULL;
|
||||
#else
|
||||
NOT_AVAILABLE (NULL);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "actions.h"
|
||||
#include "optgroups.h"
|
||||
|
||||
#define MAX_ARGS 64
|
||||
|
||||
int
|
||||
optgroup_luks_available (void)
|
||||
{
|
||||
@@ -95,17 +97,17 @@ luks_open (const char *device, const char *key, const char *mapname,
|
||||
if (!tempfile)
|
||||
return -1;
|
||||
|
||||
const char *argv[16];
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0;
|
||||
|
||||
argv[i++] = "cryptsetup";
|
||||
argv[i++] = "-d";
|
||||
argv[i++] = tempfile;
|
||||
if (readonly) argv[i++] = "--readonly";
|
||||
argv[i++] = "luksOpen";
|
||||
argv[i++] = device;
|
||||
argv[i++] = mapname;
|
||||
argv[i++] = NULL;
|
||||
ADD_ARG (argv, i, "cryptsetup");
|
||||
ADD_ARG (argv, i, "-d");
|
||||
ADD_ARG (argv, i, tempfile);
|
||||
if (readonly) ADD_ARG (argv, i, "--readonly");
|
||||
ADD_ARG (argv, i, "luksOpen");
|
||||
ADD_ARG (argv, i, device);
|
||||
ADD_ARG (argv, i, mapname);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
char *err;
|
||||
int r = commandv (NULL, &err, (const char * const *) argv);
|
||||
@@ -170,23 +172,23 @@ luks_format (const char *device, const char *key, int keyslot,
|
||||
if (!tempfile)
|
||||
return -1;
|
||||
|
||||
const char *argv[16];
|
||||
const char *argv[MAX_ARGS];
|
||||
char keyslot_s[16];
|
||||
size_t i = 0;
|
||||
|
||||
argv[i++] = "cryptsetup";
|
||||
argv[i++] = "-q";
|
||||
ADD_ARG (argv, i, "cryptsetup");
|
||||
ADD_ARG (argv, i, "-q");
|
||||
if (cipher) {
|
||||
argv[i++] = "--cipher";
|
||||
argv[i++] = cipher;
|
||||
ADD_ARG (argv, i, "--cipher");
|
||||
ADD_ARG (argv, i, cipher);
|
||||
}
|
||||
argv[i++] = "--key-slot";
|
||||
ADD_ARG (argv, i, "--key-slot");
|
||||
snprintf (keyslot_s, sizeof keyslot_s, "%d", keyslot);
|
||||
argv[i++] = keyslot_s;
|
||||
argv[i++] = "luksFormat";
|
||||
argv[i++] = device;
|
||||
argv[i++] = tempfile;
|
||||
argv[i++] = NULL;
|
||||
ADD_ARG (argv, i, keyslot_s);
|
||||
ADD_ARG (argv, i, "luksFormat");
|
||||
ADD_ARG (argv, i, device);
|
||||
ADD_ARG (argv, i, tempfile);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
char *err;
|
||||
int r = commandv (NULL, &err, (const char * const *) argv);
|
||||
@@ -232,21 +234,21 @@ do_luks_add_key (const char *device, const char *key, const char *newkey,
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *argv[16];
|
||||
const char *argv[MAX_ARGS];
|
||||
char keyslot_s[16];
|
||||
size_t i = 0;
|
||||
|
||||
argv[i++] = "cryptsetup";
|
||||
argv[i++] = "-q";
|
||||
argv[i++] = "-d";
|
||||
argv[i++] = keyfile;
|
||||
argv[i++] = "--key-slot";
|
||||
ADD_ARG (argv, i, "cryptsetup");
|
||||
ADD_ARG (argv, i, "-q");
|
||||
ADD_ARG (argv, i, "-d");
|
||||
ADD_ARG (argv, i, keyfile);
|
||||
ADD_ARG (argv, i, "--key-slot");
|
||||
snprintf (keyslot_s, sizeof keyslot_s, "%d", keyslot);
|
||||
argv[i++] = keyslot_s;
|
||||
argv[i++] = "luksAddKey";
|
||||
argv[i++] = device;
|
||||
argv[i++] = newkeyfile;
|
||||
argv[i++] = NULL;
|
||||
ADD_ARG (argv, i, keyslot_s);
|
||||
ADD_ARG (argv, i, "luksAddKey");
|
||||
ADD_ARG (argv, i, device);
|
||||
ADD_ARG (argv, i, newkeyfile);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
char *err;
|
||||
int r = commandv (NULL, &err, (const char * const *) argv);
|
||||
@@ -271,19 +273,19 @@ do_luks_kill_slot (const char *device, const char *key, int keyslot)
|
||||
if (!tempfile)
|
||||
return -1;
|
||||
|
||||
const char *argv[16];
|
||||
const char *argv[MAX_ARGS];
|
||||
char keyslot_s[16];
|
||||
size_t i = 0;
|
||||
|
||||
argv[i++] = "cryptsetup";
|
||||
argv[i++] = "-q";
|
||||
argv[i++] = "-d";
|
||||
argv[i++] = tempfile;
|
||||
argv[i++] = "luksKillSlot";
|
||||
argv[i++] = device;
|
||||
ADD_ARG (argv, i, "cryptsetup");
|
||||
ADD_ARG (argv, i, "-q");
|
||||
ADD_ARG (argv, i, "-d");
|
||||
ADD_ARG (argv, i, tempfile);
|
||||
ADD_ARG (argv, i, "luksKillSlot");
|
||||
ADD_ARG (argv, i, device);
|
||||
snprintf (keyslot_s, sizeof keyslot_s, "%d", keyslot);
|
||||
argv[i++] = keyslot_s;
|
||||
argv[i++] = NULL;
|
||||
ADD_ARG (argv, i, keyslot_s);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
char *err;
|
||||
int r = commandv (NULL, &err, (const char * const *) argv);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -23,11 +23,79 @@
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "c-ctype.h"
|
||||
#include "ignore-value.h"
|
||||
|
||||
#include "daemon.h"
|
||||
#include "c-ctype.h"
|
||||
#include "actions.h"
|
||||
|
||||
/* This runs during daemon start up and creates a complete copy of
|
||||
* /etc/lvm so that we can modify it as we desire. We set
|
||||
* LVM_SYSTEM_DIR to point to the copy.
|
||||
*/
|
||||
static char lvm_system_dir[] = "/tmp/lvmXXXXXX";
|
||||
|
||||
static void rm_lvm_system_dir (void);
|
||||
|
||||
void
|
||||
copy_lvm (void)
|
||||
{
|
||||
struct stat statbuf;
|
||||
char cmd[64];
|
||||
int r;
|
||||
|
||||
/* If /etc/lvm directory doesn't exist (or isn't a directory) assume
|
||||
* that this system doesn't support LVM and do nothing.
|
||||
*/
|
||||
r = stat ("/etc/lvm", &statbuf);
|
||||
if (r == -1) {
|
||||
perror ("copy_lvm: stat: /etc/lvm");
|
||||
return;
|
||||
}
|
||||
if (! S_ISDIR (statbuf.st_mode)) {
|
||||
fprintf (stderr, "copy_lvm: warning: /etc/lvm is not a directory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mkdtemp (lvm_system_dir) == NULL) {
|
||||
perror (lvm_system_dir);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Hopefully no dotfiles in there ... XXX */
|
||||
snprintf (cmd, sizeof cmd, "cp -a /etc/lvm/* %s", lvm_system_dir);
|
||||
r = system (cmd);
|
||||
if (r == -1) {
|
||||
perror (cmd);
|
||||
rmdir (lvm_system_dir);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (WEXITSTATUS (r) != 0) {
|
||||
fprintf (stderr, "cp command failed with return code %d\n",
|
||||
WEXITSTATUS (r));
|
||||
rmdir (lvm_system_dir);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Set environment variable so we use the copy. */
|
||||
setenv ("LVM_SYSTEM_DIR", lvm_system_dir, 1);
|
||||
|
||||
/* Set a handler to remove the temporary directory at exit. */
|
||||
atexit (rm_lvm_system_dir);
|
||||
}
|
||||
|
||||
static void
|
||||
rm_lvm_system_dir (void)
|
||||
{
|
||||
char cmd[64];
|
||||
|
||||
snprintf (cmd, sizeof cmd, "rm -rf %s", lvm_system_dir);
|
||||
ignore_value (system (cmd));
|
||||
}
|
||||
|
||||
/* Does the current line match the regexp /^\s*filter\s*=/ */
|
||||
static int
|
||||
is_filter_line (const char *line)
|
||||
@@ -52,18 +120,24 @@ is_filter_line (const char *line)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Rewrite the 'filter = [ ... ]' line in /etc/lvm/lvm.conf. */
|
||||
/* Rewrite the 'filter = [ ... ]' line in lvm.conf. */
|
||||
static int
|
||||
set_filter (const char *filter)
|
||||
{
|
||||
FILE *ifp = fopen ("/etc/lvm/lvm.conf", "r");
|
||||
char lvm_conf[64];
|
||||
snprintf (lvm_conf, sizeof lvm_conf, "%s/lvm.conf", lvm_system_dir);
|
||||
|
||||
char lvm_conf_new[64];
|
||||
snprintf (lvm_conf_new, sizeof lvm_conf, "%s/lvm.conf.new", lvm_system_dir);
|
||||
|
||||
FILE *ifp = fopen (lvm_conf, "r");
|
||||
if (ifp == NULL) {
|
||||
reply_with_perror ("open: /etc/lvm/lvm.conf");
|
||||
reply_with_perror ("open: %s", lvm_conf);
|
||||
return -1;
|
||||
}
|
||||
FILE *ofp = fopen ("/etc/lvm/lvm.conf.new", "w");
|
||||
FILE *ofp = fopen (lvm_conf_new, "w");
|
||||
if (ofp == NULL) {
|
||||
reply_with_perror ("open: /etc/lvm/lvm.conf.new");
|
||||
reply_with_perror ("open: %s", lvm_conf_new);
|
||||
fclose (ifp);
|
||||
return -1;
|
||||
}
|
||||
@@ -79,11 +153,11 @@ set_filter (const char *filter)
|
||||
}
|
||||
if (r < 0) {
|
||||
/* NB. fprintf doesn't set errno on error. */
|
||||
reply_with_error ("/etc/lvm/lvm.conf.new: write failed");
|
||||
reply_with_error ("%s: write failed", lvm_conf_new);
|
||||
fclose (ifp);
|
||||
fclose (ofp);
|
||||
free (line);
|
||||
unlink ("/etc/lvm/lvm.conf.new");
|
||||
unlink (lvm_conf_new);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -91,20 +165,20 @@ set_filter (const char *filter)
|
||||
free (line);
|
||||
|
||||
if (fclose (ifp) == EOF) {
|
||||
reply_with_perror ("/etc/lvm/lvm.conf.new");
|
||||
unlink ("/etc/lvm/lvm.conf.new");
|
||||
reply_with_perror ("close: %s", lvm_conf);
|
||||
unlink (lvm_conf_new);
|
||||
fclose (ofp);
|
||||
return -1;
|
||||
}
|
||||
if (fclose (ofp) == EOF) {
|
||||
reply_with_perror ("/etc/lvm/lvm.conf.new");
|
||||
unlink ("/etc/lvm/lvm.conf.new");
|
||||
reply_with_perror ("close: %s", lvm_conf_new);
|
||||
unlink (lvm_conf_new);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rename ("/etc/lvm/lvm.conf.new", "/etc/lvm/lvm.conf") == -1) {
|
||||
reply_with_perror ("rename: /etc/lvm/lvm.conf");
|
||||
unlink ("/etc/lvm/lvm.conf.new");
|
||||
if (rename (lvm_conf_new, lvm_conf) == -1) {
|
||||
reply_with_perror ("rename: %s", lvm_conf);
|
||||
unlink (lvm_conf_new);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -144,7 +218,10 @@ reactivate (void)
|
||||
static int
|
||||
rescan (void)
|
||||
{
|
||||
unlink ("/etc/lvm/cache/.cache");
|
||||
char lvm_cache[64];
|
||||
snprintf (lvm_cache, sizeof lvm_cache, "%s/cache/.cache", lvm_system_dir);
|
||||
|
||||
unlink (lvm_cache);
|
||||
|
||||
char *err;
|
||||
int r = command (NULL, &err, "lvm", "vgscan", NULL);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
328
daemon/md.c
Normal file
@@ -0,0 +1,328 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <glob.h>
|
||||
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
#include "optgroups.h"
|
||||
#include "c-ctype.h"
|
||||
|
||||
int
|
||||
optgroup_mdadm_available (void)
|
||||
{
|
||||
return prog_exists ("mdadm");
|
||||
}
|
||||
|
||||
static size_t
|
||||
count_bits (uint64_t bitmap)
|
||||
{
|
||||
size_t c;
|
||||
|
||||
if (bitmap == 0)
|
||||
return 0;
|
||||
|
||||
c = bitmap & 1 ? 1 : 0;
|
||||
bitmap >>= 1;
|
||||
return c + count_bits (bitmap);
|
||||
}
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_md_create (const char *name, char *const *devices,
|
||||
int64_t missingbitmap, int nrdevices, int spare,
|
||||
int64_t chunk, const char *level)
|
||||
{
|
||||
char nrdevices_s[32];
|
||||
char spare_s[32];
|
||||
char chunk_s[32];
|
||||
size_t j;
|
||||
int r;
|
||||
char *err;
|
||||
uint64_t umissingbitmap = (uint64_t) missingbitmap;
|
||||
|
||||
/* Check the optional parameters and set defaults where appropriate. */
|
||||
if (!(optargs_bitmask & GUESTFS_MD_CREATE_MISSINGBITMAP_BITMASK))
|
||||
umissingbitmap = 0;
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MD_CREATE_SPARE_BITMASK) {
|
||||
if (spare < 0) {
|
||||
reply_with_error ("spare must not be negative");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
spare = 0;
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MD_CREATE_NRDEVICES_BITMASK) {
|
||||
if (nrdevices < 2) {
|
||||
reply_with_error ("nrdevices is less than 2");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
nrdevices = count_strings (devices) + count_bits (umissingbitmap);
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MD_CREATE_LEVEL_BITMASK) {
|
||||
if (STRNEQ (level, "linear") && STRNEQ (level, "raid0") &&
|
||||
STRNEQ (level, "0") && STRNEQ (level, "stripe") &&
|
||||
STRNEQ (level, "raid1") && STRNEQ (level, "1") &&
|
||||
STRNEQ (level, "mirror") &&
|
||||
STRNEQ (level, "raid4") && STRNEQ (level, "4") &&
|
||||
STRNEQ (level, "raid5") && STRNEQ (level, "5") &&
|
||||
STRNEQ (level, "raid6") && STRNEQ (level, "6") &&
|
||||
STRNEQ (level, "raid10") && STRNEQ (level, "10")) {
|
||||
reply_with_error ("unknown level parameter: %s", level);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
level = "raid1";
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MD_CREATE_CHUNK_BITMASK) {
|
||||
/* chunk is bytes in the libguestfs API, but K when we pass it to mdadm */
|
||||
if ((chunk & 1023) != 0) {
|
||||
reply_with_error ("chunk size must be a multiple of 1024 bytes");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check invariant. */
|
||||
if (count_strings (devices) + count_bits (umissingbitmap) !=
|
||||
(size_t) (nrdevices + spare)) {
|
||||
reply_with_error ("devices (%zu) + bits set in missingbitmap (%zu) is not equal to nrdevices (%d) + spare (%d)",
|
||||
count_strings (devices), count_bits (umissingbitmap),
|
||||
nrdevices, spare);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t MAX_ARGS = nrdevices + 16;
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0;
|
||||
|
||||
ADD_ARG (argv, i, "mdadm");
|
||||
ADD_ARG (argv, i, "--create");
|
||||
/* --run suppresses "Continue creating array" question */
|
||||
ADD_ARG (argv, i, "--run");
|
||||
ADD_ARG (argv, i, name);
|
||||
ADD_ARG (argv, i, "--level");
|
||||
ADD_ARG (argv, i, level);
|
||||
ADD_ARG (argv, i, "--raid-devices");
|
||||
snprintf (nrdevices_s, sizeof nrdevices_s, "%d", nrdevices);
|
||||
ADD_ARG (argv, i, nrdevices_s);
|
||||
if (optargs_bitmask & GUESTFS_MD_CREATE_SPARE_BITMASK) {
|
||||
ADD_ARG (argv, i, "--spare-devices");
|
||||
snprintf (spare_s, sizeof spare_s, "%d", spare);
|
||||
ADD_ARG (argv, i, spare_s);
|
||||
}
|
||||
if (optargs_bitmask & GUESTFS_MD_CREATE_CHUNK_BITMASK) {
|
||||
ADD_ARG (argv, i, "--chunk");
|
||||
snprintf (chunk_s, sizeof chunk_s, "%" PRIi64, chunk / 1024);
|
||||
ADD_ARG (argv, i, chunk_s);
|
||||
}
|
||||
|
||||
/* Add devices and "missing". */
|
||||
j = 0;
|
||||
while (devices[j] != NULL || umissingbitmap != 0) {
|
||||
if (umissingbitmap & 1)
|
||||
ADD_ARG (argv, i, "missing");
|
||||
else {
|
||||
ADD_ARG (argv, i, devices[j]);
|
||||
j++;
|
||||
}
|
||||
umissingbitmap >>= 1;
|
||||
}
|
||||
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
if (r == -1) {
|
||||
reply_with_error ("mdadm: %s: %s", name, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
|
||||
udev_settle ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
glob_errfunc (const char *epath, int eerrno)
|
||||
{
|
||||
fprintf (stderr, "glob: failure reading %s: %s\n", epath, strerror (eerrno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
char **
|
||||
do_list_md_devices (void)
|
||||
{
|
||||
char **r = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
glob_t mds;
|
||||
|
||||
memset(&mds, 0, sizeof(mds));
|
||||
|
||||
#define PREFIX "/sys/block/md"
|
||||
#define SUFFIX "/md"
|
||||
|
||||
/* Look for directories under /sys/block matching md[0-9]*
|
||||
* As an additional check, we also make sure they have a md subdirectory.
|
||||
*/
|
||||
int err = glob (PREFIX "[0-9]*" SUFFIX, GLOB_ERR, glob_errfunc, &mds);
|
||||
if (err == GLOB_NOSPACE) {
|
||||
reply_with_error ("glob: returned GLOB_NOSPACE: "
|
||||
"rerun with LIBGUESTFS_DEBUG=1");
|
||||
goto error;
|
||||
} else if (err == GLOB_ABORTED) {
|
||||
reply_with_error ("glob: returned GLOB_ABORTED: "
|
||||
"rerun with LIBGUESTFS_DEBUG=1");
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mds.gl_pathc; i++) {
|
||||
size_t len = strlen (mds.gl_pathv[i]) - strlen (PREFIX) - strlen (SUFFIX);
|
||||
|
||||
#define DEV "/dev/md"
|
||||
char *dev = malloc (strlen(DEV) + len + 1);
|
||||
if (NULL == dev) {
|
||||
reply_with_perror("malloc");
|
||||
goto error;
|
||||
}
|
||||
|
||||
char *n = dev;
|
||||
n = mempcpy(n, DEV, strlen(DEV));
|
||||
n = mempcpy(n, &mds.gl_pathv[i][strlen(PREFIX)], len);
|
||||
*n = '\0';
|
||||
|
||||
if (add_string_nodup (&r, &size, &alloc, dev) == -1) goto error;
|
||||
}
|
||||
|
||||
if (add_string_nodup (&r, &size, &alloc, NULL) == -1) goto error;
|
||||
globfree (&mds);
|
||||
|
||||
return r;
|
||||
|
||||
error:
|
||||
globfree (&mds);
|
||||
if (r != NULL) free_strings (r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char **
|
||||
do_md_detail(const char *md)
|
||||
{
|
||||
int r;
|
||||
|
||||
char *out = NULL, *err = NULL;
|
||||
char **lines = NULL;
|
||||
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
|
||||
const char *mdadm[] = { "mdadm", "-D", "--export", md, NULL };
|
||||
r = commandv(&out, &err, mdadm);
|
||||
if (r == -1) {
|
||||
reply_with_error("%s", err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Split the command output into lines */
|
||||
lines = split_lines(out);
|
||||
if (lines == NULL) {
|
||||
reply_with_perror("malloc");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Parse the output of mdadm -D --export:
|
||||
* MD_LEVEL=raid1
|
||||
* MD_DEVICES=2
|
||||
* MD_METADATA=1.0
|
||||
* MD_UUID=cfa81b59:b6cfbd53:3f02085b:58f4a2e1
|
||||
* MD_NAME=localhost.localdomain:0
|
||||
*/
|
||||
for (char **i = lines; *i != NULL; i++) {
|
||||
char *line = *i;
|
||||
|
||||
/* Skip blank lines (shouldn't happen) */
|
||||
if (line[0] == '\0') continue;
|
||||
|
||||
/* Split the line in 2 at the equals sign */
|
||||
char *eq = strchr(line, '=');
|
||||
if (eq) {
|
||||
*eq = '\0'; eq++;
|
||||
|
||||
/* Remove the MD_ prefix from the key and translate the remainder to lower
|
||||
* case */
|
||||
if (STRPREFIX(line, "MD_")) {
|
||||
line += 3;
|
||||
for (char *j = line; *j != '\0'; j++) {
|
||||
*j = c_tolower(*j);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the key/value pair to the output */
|
||||
if (add_string(&ret, &size, &alloc, line) == -1 ||
|
||||
add_string(&ret, &size, &alloc, eq) == -1) goto error;
|
||||
} else {
|
||||
/* Ignore lines with no equals sign (shouldn't happen). Log to stderr so
|
||||
* it will show up in LIBGUESTFS_DEBUG. */
|
||||
fprintf(stderr, "md-detail: unexpected mdadm output ignored: %s", line);
|
||||
}
|
||||
}
|
||||
|
||||
free(out);
|
||||
free(err);
|
||||
free(lines); /* We freed the contained strings when we freed out */
|
||||
|
||||
if (add_string(&ret, &size, &alloc, NULL) == -1) return NULL;
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
free(out);
|
||||
free(err);
|
||||
if (lines) free(lines);
|
||||
if (ret) free_strings(ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
do_md_stop(const char *md)
|
||||
{
|
||||
int r;
|
||||
char *err = NULL;
|
||||
|
||||
const char *mdadm[] = { "mdadm", "--stop", md, NULL};
|
||||
r = commandv(NULL, &err, mdadm);
|
||||
if (r == -1) {
|
||||
reply_with_error("%s", err);
|
||||
free(err);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
|
||||
#define MAX_ARGS 16
|
||||
#define MAX_ARGS 64
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
@@ -44,56 +44,59 @@ do_mkfs_opts (const char *fstype, const char *device, int blocksize,
|
||||
int r;
|
||||
char *err;
|
||||
char mke2fs[] = "mke2fs";
|
||||
int extfs = 0;
|
||||
|
||||
if (STREQ (fstype, "ext2") || STREQ (fstype, "ext3") ||
|
||||
STREQ (fstype, "ext4"))
|
||||
extfs = 1;
|
||||
|
||||
/* 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 (extfs) {
|
||||
if (e2prog (mke2fs) == -1)
|
||||
return -1;
|
||||
argv[i++] = mke2fs;
|
||||
ADD_ARG (argv, i, mke2fs);
|
||||
}
|
||||
else
|
||||
argv[i++] = "mkfs";
|
||||
ADD_ARG (argv, i, "mkfs");
|
||||
|
||||
argv[i++] = "-t";
|
||||
argv[i++] = fstype;
|
||||
ADD_ARG (argv, i, "-t");
|
||||
ADD_ARG (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";
|
||||
if (extfs)
|
||||
ADD_ARG (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.
|
||||
*/
|
||||
if (STREQ (fstype, "ntfs"))
|
||||
argv[i++] = "-Q";
|
||||
ADD_ARG (argv, i, "-Q");
|
||||
|
||||
/* mkfs.reiserfs produces annoying interactive prompts unless you
|
||||
* tell it to be quiet.
|
||||
* mkfs.jfs is the same
|
||||
* mkfs.xfs must force to make xfs filesystem when the device already
|
||||
* has a filesystem on it
|
||||
*/
|
||||
if (STREQ (fstype, "reiserfs"))
|
||||
argv[i++] = "-f";
|
||||
|
||||
/* Same for JFS. */
|
||||
if (STREQ (fstype, "jfs"))
|
||||
argv[i++] = "-f";
|
||||
if (STREQ (fstype, "reiserfs") || STREQ (fstype, "jfs") ||
|
||||
STREQ (fstype, "xfs"))
|
||||
ADD_ARG(argv, i, "-f");
|
||||
|
||||
/* For GFS, GFS2, assume a single node. */
|
||||
if (STREQ (fstype, "gfs") || STREQ (fstype, "gfs2")) {
|
||||
argv[i++] = "-p";
|
||||
argv[i++] = "lock_nolock";
|
||||
ADD_ARG (argv, i, "-p");
|
||||
ADD_ARG (argv, i, "lock_nolock");
|
||||
/* The man page says this is default, but it doesn't seem to be: */
|
||||
argv[i++] = "-j";
|
||||
argv[i++] = "1";
|
||||
ADD_ARG (argv, i, "-j");
|
||||
ADD_ARG (argv, i, "1");
|
||||
/* Don't ask questions: */
|
||||
argv[i++] = "-O";
|
||||
ADD_ARG (argv, i, "-O");
|
||||
}
|
||||
|
||||
/* Process blocksize parameter if set. */
|
||||
@@ -121,31 +124,30 @@ do_mkfs_opts (const char *fstype, const char *device, int blocksize,
|
||||
}
|
||||
|
||||
snprintf (blocksize_str, sizeof blocksize_str, "%d", sectors_per_cluster);
|
||||
argv[i++] = "-s";
|
||||
argv[i++] = blocksize_str;
|
||||
ADD_ARG (argv, i, "-s");
|
||||
ADD_ARG (argv, i, blocksize_str);
|
||||
}
|
||||
else if (STREQ (fstype, "ntfs")) {
|
||||
/* For NTFS map the blocksize into a cluster size. */
|
||||
snprintf (blocksize_str, sizeof blocksize_str, "%d", blocksize);
|
||||
argv[i++] = "-c";
|
||||
argv[i++] = blocksize_str;
|
||||
ADD_ARG (argv, i, "-c");
|
||||
ADD_ARG (argv, i, blocksize_str);
|
||||
}
|
||||
else {
|
||||
/* For all other filesystem types, try the -b option. */
|
||||
snprintf (blocksize_str, sizeof blocksize_str, "%d", blocksize);
|
||||
argv[i++] = "-b";
|
||||
argv[i++] = blocksize_str;
|
||||
ADD_ARG (argv, i, "-b");
|
||||
ADD_ARG (argv, i, blocksize_str);
|
||||
}
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MKFS_OPTS_FEATURES_BITMASK) {
|
||||
argv[i++] = "-O";
|
||||
argv[i++] = features;
|
||||
ADD_ARG (argv, i, "-O");
|
||||
ADD_ARG (argv, i, features);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MKFS_OPTS_INODE_BITMASK) {
|
||||
if (!STREQ (fstype, "ext2") && !STREQ (fstype, "ext3") &&
|
||||
!STREQ (fstype, "ext4")) {
|
||||
if (!extfs) {
|
||||
reply_with_error ("inode size (-I) can only be set on ext2/3/4 filesystems");
|
||||
return -1;
|
||||
}
|
||||
@@ -156,8 +158,8 @@ do_mkfs_opts (const char *fstype, const char *device, int blocksize,
|
||||
}
|
||||
|
||||
snprintf (inode_str, sizeof inode_str, "%d", inode);
|
||||
argv[i++] = "-I";
|
||||
argv[i++] = inode_str;
|
||||
ADD_ARG (argv, i, "-I");
|
||||
ADD_ARG (argv, i, inode_str);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MKFS_OPTS_SECTORSIZE_BITMASK) {
|
||||
@@ -172,15 +174,12 @@ do_mkfs_opts (const char *fstype, const char *device, int blocksize,
|
||||
}
|
||||
|
||||
snprintf (sectorsize_str, sizeof sectorsize_str, "%d", sectorsize);
|
||||
argv[i++] = "-S";
|
||||
argv[i++] = sectorsize_str;
|
||||
ADD_ARG (argv, i, "-S");
|
||||
ADD_ARG (argv, i, sectorsize_str);
|
||||
}
|
||||
|
||||
argv[i++] = device;
|
||||
argv[i++] = NULL;
|
||||
|
||||
if (i > MAX_ARGS)
|
||||
abort ();
|
||||
ADD_ARG (argv, i, device);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
if (r == -1) {
|
||||
|
||||