mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 16:26:17 +00:00
Compare commits
507 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eaa05ff012 | ||
|
|
e0f36898cb | ||
|
|
bd91bd76d1 | ||
|
|
9e2cdd309b | ||
|
|
a2cc317c03 | ||
|
|
c53ea071c6 | ||
|
|
0cc3525142 | ||
|
|
93734c78d8 | ||
|
|
e60556d927 | ||
|
|
00202b9c29 | ||
|
|
f072a21f3a | ||
|
|
66a525ce5a | ||
|
|
620ad8eb1a | ||
|
|
79bf966cea | ||
|
|
29c5e052e4 | ||
|
|
1304236c6c | ||
|
|
95a67b1e6a | ||
|
|
500cc67f29 | ||
|
|
e6bfb55f65 | ||
|
|
922052c70f | ||
|
|
51f43402f6 | ||
|
|
027fefd517 | ||
|
|
75514ab57a | ||
|
|
6aa95e87c1 | ||
|
|
ea74856d95 | ||
|
|
79822d46e3 | ||
|
|
bb73cf0941 | ||
|
|
a23e84ee02 | ||
|
|
cc79854037 | ||
|
|
d448ae0c2b | ||
|
|
1f0964536b | ||
|
|
23f8cab1e8 | ||
|
|
ac75e46c5a | ||
|
|
e493884a76 | ||
|
|
819cba54e6 | ||
|
|
a505423e58 | ||
|
|
eafefab937 | ||
|
|
d58cb029a3 | ||
|
|
317ba894b3 | ||
|
|
8fb67ee66a | ||
|
|
6c88c3758b | ||
|
|
a2dc83cf03 | ||
|
|
8cb30dc805 | ||
|
|
39d79e677b | ||
|
|
2cc4314ecc | ||
|
|
beaa528855 | ||
|
|
2d414112f7 | ||
|
|
12c5394d4c | ||
|
|
e188eb8268 | ||
|
|
87ea7a0409 | ||
|
|
3cc9703f90 | ||
|
|
bd1a699c15 | ||
|
|
046d6c20e7 | ||
|
|
303b159134 | ||
|
|
580ae3297a | ||
|
|
a98d9f4840 | ||
|
|
0e49186814 | ||
|
|
5fab4db8de | ||
|
|
d16868b938 | ||
|
|
37a3cdbc13 | ||
|
|
a2d30626cb | ||
|
|
7fc7c3aa5b | ||
|
|
95515c4576 | ||
|
|
148b51fe0b | ||
|
|
7916f5d43c | ||
|
|
8d41470b6f | ||
|
|
97ef9afca7 | ||
|
|
03d321d022 | ||
|
|
c844a38d6e | ||
|
|
2152affd30 | ||
|
|
36f1eb9225 | ||
|
|
e97b6a1bb1 | ||
|
|
c253c69d09 | ||
|
|
58a5b5bd94 | ||
|
|
5d6a323b93 | ||
|
|
b0b5fdc69f | ||
|
|
4542401fee | ||
|
|
158479ffc0 | ||
|
|
255882a3f6 | ||
|
|
7995c513ba | ||
|
|
6065f21b10 | ||
|
|
84d450210b | ||
|
|
8d3d5a52d2 | ||
|
|
fb401ebff8 | ||
|
|
5ec0fba56e | ||
|
|
3c843e2129 | ||
|
|
63cb25236b | ||
|
|
6c2b8340c3 | ||
|
|
8104b2dfab | ||
|
|
9ccde76f61 | ||
|
|
2a5a5e15e2 | ||
|
|
1f373aa246 | ||
|
|
ecdfd2c8cc | ||
|
|
b288f21e0c | ||
|
|
4b0e525d1d | ||
|
|
e14f545f81 | ||
|
|
a9bd90abfb | ||
|
|
d2183a62aa | ||
|
|
4be630edb3 | ||
|
|
4dba0e1e9d | ||
|
|
a97e9429ea | ||
|
|
5b414f581f | ||
|
|
681377f1b2 | ||
|
|
96b6504b09 | ||
|
|
a996f0d370 | ||
|
|
6c276606d7 | ||
|
|
ed2a06708c | ||
|
|
292664c3ac | ||
|
|
287d5a126e | ||
|
|
307e8bc51a | ||
|
|
3e164f15b7 | ||
|
|
c1fb89e7fc | ||
|
|
de2dc9f71d | ||
|
|
b6dd7e7250 | ||
|
|
0f7de2279a | ||
|
|
f237ae2ad6 | ||
|
|
4ee518508f | ||
|
|
16b2ffa97e | ||
|
|
a3d6629a0b | ||
|
|
edca57b49e | ||
|
|
b8fbbcf791 | ||
|
|
b10a3d718e | ||
|
|
7fe9905c4b | ||
|
|
5e054f8731 | ||
|
|
60b87d0a5c | ||
|
|
8ae322e5a7 | ||
|
|
669c0bd407 | ||
|
|
12a56dfc8a | ||
|
|
f2ac7c18a7 | ||
|
|
418a048215 | ||
|
|
d9f77f214b | ||
|
|
4b86f1ad03 | ||
|
|
ec162e7d58 | ||
|
|
19494b1988 | ||
|
|
465c97ebf4 | ||
|
|
999aac63eb | ||
|
|
5c8a241e5c | ||
|
|
04ddf3cfa2 | ||
|
|
25d156f262 | ||
|
|
a1d88b60e3 | ||
|
|
817cebe3ad | ||
|
|
50009403b3 | ||
|
|
77ac6b73cd | ||
|
|
f8a88def14 | ||
|
|
95123a9144 | ||
|
|
6282d92b1b | ||
|
|
9cb976ab5f | ||
|
|
b1f997164e | ||
|
|
de656448f7 | ||
|
|
6c88ae851f | ||
|
|
65e20e34dd | ||
|
|
64550dcad2 | ||
|
|
94e94550ed | ||
|
|
7ed21d9a5c | ||
|
|
3a58a00483 | ||
|
|
3b94cf5046 | ||
|
|
6e3de76278 | ||
|
|
ad43dde9c8 | ||
|
|
026f616650 | ||
|
|
d00596dfbb | ||
|
|
e430ce8908 | ||
|
|
dd126109e5 | ||
|
|
ed96872bd2 | ||
|
|
b2cddfe2f5 | ||
|
|
c6f09fac06 | ||
|
|
49fdba0ae9 | ||
|
|
1c5dc612bd | ||
|
|
b9cb387a10 | ||
|
|
d67da6419a | ||
|
|
0c9361a356 | ||
|
|
4db251048b | ||
|
|
17c828d995 | ||
|
|
2b9167540f | ||
|
|
3b0cb4dfdc | ||
|
|
3311e110c7 | ||
|
|
321748d3c2 | ||
|
|
e49bd34fb7 | ||
|
|
574d104b15 | ||
|
|
e3758fc430 | ||
|
|
6b13952657 | ||
|
|
ed5cc90ed5 | ||
|
|
9863dd387f | ||
|
|
1004b2ec25 | ||
|
|
b0ebf37a94 | ||
|
|
4d0aa08b00 | ||
|
|
5ea27d740e | ||
|
|
3d174b39bf | ||
|
|
f2fae5151f | ||
|
|
b169b03dd4 | ||
|
|
8111b108d2 | ||
|
|
f35aadcd86 | ||
|
|
a33ea71601 | ||
|
|
a138063acb | ||
|
|
e8ef35df26 | ||
|
|
13e5f1a3b1 | ||
|
|
09a4e7664b | ||
|
|
f5c31db5ed | ||
|
|
f1d10672c7 | ||
|
|
88b5ee9d95 | ||
|
|
fc198a3b9a | ||
|
|
a14021078b | ||
|
|
55c4e7a0d3 | ||
|
|
7d2027295f | ||
|
|
a8f8af950d | ||
|
|
3f6cc550ff | ||
|
|
65ebec4a7a | ||
|
|
f62db21d8b | ||
|
|
7526df547c | ||
|
|
c7dff02ccb | ||
|
|
b8fc61bd9b | ||
|
|
e1ffb10115 | ||
|
|
752bd8f632 | ||
|
|
7c2ebad357 | ||
|
|
a4fd393663 | ||
|
|
05461175c4 | ||
|
|
fd7a5a8bbd | ||
|
|
f9c4fdfeea | ||
|
|
a6f47c285f | ||
|
|
14938b46a7 | ||
|
|
a43f35f5bb | ||
|
|
d17218c210 | ||
|
|
6bee63beb4 | ||
|
|
c8630300b8 | ||
|
|
710ec49bac | ||
|
|
974dffc676 | ||
|
|
553e50c105 | ||
|
|
5749de39c2 | ||
|
|
5411f3fd45 | ||
|
|
85a701c10c | ||
|
|
98f066e274 | ||
|
|
1c1ecb2c41 | ||
|
|
7283a5a276 | ||
|
|
31c26be91f | ||
|
|
8c9f6a64be | ||
|
|
b05611d8ef | ||
|
|
79c4ecc0f3 | ||
|
|
03d4345c8c | ||
|
|
d9bdb9587b | ||
|
|
7934ea2395 | ||
|
|
91cede3465 | ||
|
|
2bc922dd8e | ||
|
|
c23f3b8e52 | ||
|
|
e743eb3984 | ||
|
|
606732d02e | ||
|
|
13e7a1b400 | ||
|
|
d042e56f2a | ||
|
|
6b233bd39e | ||
|
|
302309921a | ||
|
|
5da61d3052 | ||
|
|
9974c42a29 | ||
|
|
f876271521 | ||
|
|
7e32d892d7 | ||
|
|
f76a88011a | ||
|
|
14df5fa5d1 | ||
|
|
d66dd2260c | ||
|
|
17182af3a6 | ||
|
|
f7c744bbf8 | ||
|
|
b3a9e81868 | ||
|
|
1f603bfd6d | ||
|
|
2c8ead5aa0 | ||
|
|
100e30763e | ||
|
|
099e3dd9f1 | ||
|
|
5cad29043f | ||
|
|
6292e630da | ||
|
|
e9e0920c00 | ||
|
|
13c2db39ab | ||
|
|
46d1280100 | ||
|
|
4bcd0b3c17 | ||
|
|
cd3f2986ee | ||
|
|
1aa72017ca | ||
|
|
3d279d15c1 | ||
|
|
b8cdf6c2b9 | ||
|
|
24413ac4d8 | ||
|
|
e6f18c59d5 | ||
|
|
5b7b1c43ab | ||
|
|
2fb545b840 | ||
|
|
4c9218658e | ||
|
|
99923c7cd0 | ||
|
|
dfe30bdfe7 | ||
|
|
d0cf52b911 | ||
|
|
baa5e1ea51 | ||
|
|
f1f045adf8 | ||
|
|
99702fe443 | ||
|
|
f8e7a41e67 | ||
|
|
2912e4e117 | ||
|
|
0721464b83 | ||
|
|
270daae52b | ||
|
|
3f3b08a6bc | ||
|
|
b2c1d8be39 | ||
|
|
3345444ccc | ||
|
|
ae0f9f149b | ||
|
|
3b3d9ca4e1 | ||
|
|
4dd26c28a3 | ||
|
|
d0453c0254 | ||
|
|
fbf10d7f68 | ||
|
|
cba36e7305 | ||
|
|
855aaf414a | ||
|
|
618954a6b0 | ||
|
|
35d5be22b1 | ||
|
|
0ffa223a75 | ||
|
|
109d3ad34a | ||
|
|
07a8c3c0c2 | ||
|
|
10f240a07f | ||
|
|
5503d95e1b | ||
|
|
0fdcc76901 | ||
|
|
4504f424f5 | ||
|
|
2f126e07bb | ||
|
|
cfa0f9b381 | ||
|
|
a9510b7b22 | ||
|
|
518cdb596e | ||
|
|
4d8ae8f5a2 | ||
|
|
e40f408fae | ||
|
|
2c9c0525eb | ||
|
|
b9061ddf2d | ||
|
|
b106dda97c | ||
|
|
3bf5d0d0e4 | ||
|
|
deaae55072 | ||
|
|
715f7e2809 | ||
|
|
705971b509 | ||
|
|
49611f121f | ||
|
|
b11e9f4919 | ||
|
|
3b78b3a849 | ||
|
|
5e8a4627d9 | ||
|
|
49726b9269 | ||
|
|
ba468e9c5e | ||
|
|
d6f736ab18 | ||
|
|
48a5cb2a2c | ||
|
|
88ba4da4d6 | ||
|
|
a93d4a9dc1 | ||
|
|
d1711dae9d | ||
|
|
e567f064e2 | ||
|
|
51aa51884e | ||
|
|
2e788ca45e | ||
|
|
b5cc1fa049 | ||
|
|
9e5c0b39c6 | ||
|
|
db2cb21a85 | ||
|
|
5fa7aace20 | ||
|
|
afed7e493d | ||
|
|
c9ea94810e | ||
|
|
6a70cb337c | ||
|
|
84a4160fd3 | ||
|
|
cd06ddf442 | ||
|
|
1b15e543a8 | ||
|
|
07081591cf | ||
|
|
ba443ae048 | ||
|
|
c8a11468c4 | ||
|
|
9403c5516f | ||
|
|
badf2d6c4d | ||
|
|
7c21e49c2c | ||
|
|
ddae5abf80 | ||
|
|
ca80e44904 | ||
|
|
ac58ddcd1a | ||
|
|
39625b59ee | ||
|
|
df3c6acacd | ||
|
|
088546af9d | ||
|
|
a2b3e0900e | ||
|
|
6ca8a2db6d | ||
|
|
a915d78ef9 | ||
|
|
24d7889eba | ||
|
|
016ae77e6c | ||
|
|
2cbf5ea543 | ||
|
|
f504cb02e1 | ||
|
|
518edc506f | ||
|
|
0559f038ad | ||
|
|
825b5e65c0 | ||
|
|
21a9efcad5 | ||
|
|
a98170e0e2 | ||
|
|
3c9ef0e978 | ||
|
|
590d8c3c37 | ||
|
|
b7a7ad1d11 | ||
|
|
330fbea5b2 | ||
|
|
90d6386c13 | ||
|
|
d60d5c091f | ||
|
|
0042898880 | ||
|
|
e3f15780c8 | ||
|
|
6e703c1316 | ||
|
|
03684e7a61 | ||
|
|
a3ac2cc788 | ||
|
|
d33c70fd64 | ||
|
|
8fd5a377b8 | ||
|
|
eb68a31413 | ||
|
|
799852e646 | ||
|
|
7972b1da81 | ||
|
|
8f564ae7a2 | ||
|
|
d5bc69e545 | ||
|
|
93e443ccad | ||
|
|
de00aa84af | ||
|
|
3d0c9f3fc6 | ||
|
|
0a4d181063 | ||
|
|
09227c9d66 | ||
|
|
9f8e9dcc70 | ||
|
|
b1ace67381 | ||
|
|
dd25638fc1 | ||
|
|
8bad4d1c47 | ||
|
|
6568dd85f4 | ||
|
|
501561742b | ||
|
|
8ac5391935 | ||
|
|
a05ddcd2a7 | ||
|
|
9700708a19 | ||
|
|
86f64c37b9 | ||
|
|
94a7fb9fc5 | ||
|
|
ff2e685828 | ||
|
|
4c2101362e | ||
|
|
aa978b75ae | ||
|
|
43a6974cb3 | ||
|
|
f86c3a45ae | ||
|
|
9f8f1fd856 | ||
|
|
f65f653ab1 | ||
|
|
9cf7ecbe4f | ||
|
|
84242a8d0b | ||
|
|
d08806adfc | ||
|
|
b7122eaa58 | ||
|
|
22224254fa | ||
|
|
734b1f662f | ||
|
|
51c199ca6f | ||
|
|
b1f188e24b | ||
|
|
7caa81ab9d | ||
|
|
61dc072a8b | ||
|
|
fd3e3ca188 | ||
|
|
abc17351ad | ||
|
|
6edecdec59 | ||
|
|
37e07db159 | ||
|
|
3a754cc88f | ||
|
|
70070cf244 | ||
|
|
7fbf0cc499 | ||
|
|
d4f7958487 | ||
|
|
b6e0552ee5 | ||
|
|
7004fafc69 | ||
|
|
5cfd3e7b3e | ||
|
|
4f868b84d6 | ||
|
|
7178554332 | ||
|
|
17a599ef27 | ||
|
|
f81499fb64 | ||
|
|
4edd061975 | ||
|
|
de5d416fc7 | ||
|
|
93b0769ec7 | ||
|
|
02ccef7684 | ||
|
|
e99a6a8483 | ||
|
|
cce1bbb345 | ||
|
|
5c5babb40b | ||
|
|
eb58fa9978 | ||
|
|
b8720abfe5 | ||
|
|
251c6e994d | ||
|
|
762d1bbda1 | ||
|
|
3d80161d9c | ||
|
|
24f01a581b | ||
|
|
a20b88be83 | ||
|
|
7412bb3421 | ||
|
|
04cb1bb106 | ||
|
|
3f6ca541c7 | ||
|
|
1982779fa3 | ||
|
|
72c97e6607 | ||
|
|
a9c8123c72 | ||
|
|
ea3f16f6d9 | ||
|
|
61abcf71c0 | ||
|
|
08840bab44 | ||
|
|
d8a1389df3 | ||
|
|
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 |
750
.gitignore
vendored
750
.gitignore
vendored
@@ -1,369 +1,417 @@
|
||||
*~
|
||||
*.a
|
||||
test1.img
|
||||
test2.img
|
||||
test.err
|
||||
test.out
|
||||
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
|
||||
appliance/stamp-supermin
|
||||
appliance/supermin.d
|
||||
autom4te.cache
|
||||
*.bak
|
||||
bindtests.tmp
|
||||
cat/stamp-virt-*.pod
|
||||
cat/virt-cat
|
||||
cat/virt-cat.1
|
||||
cat/virt-filesystems
|
||||
cat/virt-filesystems.1
|
||||
cat/virt-ls
|
||||
cat/virt-ls.1
|
||||
ChangeLog
|
||||
*.class
|
||||
clone/stamp-virt-sysprep.pod
|
||||
clone/virt-sysprep
|
||||
clone/virt-sysprep.1
|
||||
*.cma
|
||||
*.cmi
|
||||
*.cmo
|
||||
*.cmx
|
||||
*.cmxa
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
cscope.out
|
||||
csharp/Libguestfs.cs
|
||||
daemon/actions.h
|
||||
daemon/errnostring_gperf.c
|
||||
daemon/errnostring_gperf.gperf
|
||||
daemon/errnostring.c
|
||||
daemon/errnostring.h
|
||||
daemon/guestfsd
|
||||
daemon/guestfsd.exe
|
||||
daemon/guestfs_protocol.c
|
||||
daemon/guestfs_protocol.h
|
||||
daemon/install-sh
|
||||
daemon/missing
|
||||
daemon/names.c
|
||||
daemon/optgroups.c
|
||||
daemon/optgroups.h
|
||||
daemon/stubs.c
|
||||
depcomp
|
||||
.deps
|
||||
df/stamp-virt-df.pod
|
||||
df/virt-df
|
||||
df/virt-df.1
|
||||
edit/stamp-virt-*.pod
|
||||
edit/virt-edit
|
||||
edit/virt-edit.1
|
||||
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
|
||||
fish/guestfish-actions.pod
|
||||
fish/guestfish-commands.pod
|
||||
fish/prepopts.c
|
||||
fish/prepopts.h
|
||||
fish/rc_protocol.c
|
||||
fish/rc_protocol.h
|
||||
fish/stamp-guestfish.pod
|
||||
fish/stamp-virt-copy-in.pod
|
||||
fish/stamp-virt-copy-out.pod
|
||||
fish/stamp-virt-tar-in.pod
|
||||
fish/stamp-virt-tar-out.pod
|
||||
fish/virt-copy-in.1
|
||||
fish/virt-copy-out.1
|
||||
fish/virt-tar-in.1
|
||||
fish/virt-tar-out.1
|
||||
fuse/guestmount
|
||||
fuse/guestmount.1
|
||||
fuse/stamp-guestmount.pod
|
||||
generator/.pod2text.data*
|
||||
generator/files-generated.txt
|
||||
generator/generator
|
||||
generator/stamp-generator
|
||||
guestfsd-in-wine.log
|
||||
haskell/Bindtests
|
||||
haskell/Bindtests.hs
|
||||
haskell/Guestfs005Load
|
||||
haskell/Guestfs010Basic
|
||||
haskell/Guestfs.hs
|
||||
*.diff
|
||||
*.eml
|
||||
*.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
|
||||
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-inspector.1.html
|
||||
html/virt-list-filesystems.1.html
|
||||
html/virt-list-partitions.1.html
|
||||
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
|
||||
inspector/stamp-virt-inspector.pod
|
||||
inspector/virt-inspector
|
||||
inspector/virt-inspector.1
|
||||
install-sh
|
||||
*.jar
|
||||
java/api
|
||||
java/Bindtests.java
|
||||
java/com/redhat/et/libguestfs/Application.java
|
||||
java/com/redhat/et/libguestfs/Dirent.java
|
||||
java/com_redhat_et_libguestfs_GuestFS.c
|
||||
java/com_redhat_et_libguestfs_GuestFS.h
|
||||
java/com/redhat/et/libguestfs/GuestFS.java
|
||||
java/com/redhat/et/libguestfs/INotifyEvent.java
|
||||
java/com/redhat/et/libguestfs/IntBool.java
|
||||
java/com/redhat/et/libguestfs/LV.java
|
||||
java/com/redhat/et/libguestfs/Partition.java
|
||||
java/com/redhat/et/libguestfs/PV.java
|
||||
java/com/redhat/et/libguestfs/Stat.java
|
||||
java/com/redhat/et/libguestfs/StatVFS.java
|
||||
java/com/redhat/et/libguestfs/Version.java
|
||||
java/com/redhat/et/libguestfs/VG.java
|
||||
java/com/redhat/et/libguestfs/XAttr.java
|
||||
java/doc-stamp
|
||||
java/examples/guestfs-java.3
|
||||
java/examples/stamp-guestfs-java.pod
|
||||
*.la
|
||||
libguestfs.pc
|
||||
libguestfs.spec
|
||||
libguestfs-*.tar.gz
|
||||
.libs
|
||||
libtool
|
||||
*.lo
|
||||
/local*
|
||||
ltmain.sh
|
||||
m4/gnulib-cache.m4
|
||||
m4/intmax.m4
|
||||
m4/libtool.m4
|
||||
m4/lt~obsolete.m4
|
||||
m4/ltoptions.m4
|
||||
m4/ltsugar.m4
|
||||
m4/ltversion.m4
|
||||
*.o
|
||||
*.orig
|
||||
*.patch
|
||||
*.rej
|
||||
*.swp
|
||||
|
||||
bindtests.tmp
|
||||
cscope.out
|
||||
.deps
|
||||
.libs
|
||||
Makefile
|
||||
Makefile.in
|
||||
missing
|
||||
*.o
|
||||
ocamlinit-stamp
|
||||
ocaml/bindtests
|
||||
ocaml/bindtests.ml
|
||||
ocaml/dllmlguestfs.so
|
||||
ocaml/examples/create_disk
|
||||
ocaml/examples/guestfs-ocaml.3
|
||||
ocaml/examples/inspect_vm
|
||||
ocaml/examples/stamp-guestfs-ocaml.pod
|
||||
ocaml/guestfs_c_actions.c
|
||||
ocaml/guestfs_inspector.ml
|
||||
ocaml/guestfs_inspector.mli
|
||||
ocaml/guestfs.ml
|
||||
ocaml/guestfs.mli
|
||||
ocaml/META
|
||||
ocaml/t/guestfs_005_load
|
||||
ocaml/t/guestfs_010_basic
|
||||
ocaml/t/guestfs_070_threads
|
||||
ocaml/t/guestfs_080_optargs
|
||||
ocaml/t/guestfs_400_events
|
||||
ocaml/t/guestfs_400_progress
|
||||
perl/bindtests.pl
|
||||
perl/blib
|
||||
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/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
|
||||
php/extension/configure.in
|
||||
php/extension/guestfs_php.c
|
||||
php/extension/guestfs_php_*.diff
|
||||
php/extension/guestfs_php_*.exp
|
||||
php/extension/guestfs_php_*.log
|
||||
php/extension/guestfs_php_*.out
|
||||
php/extension/guestfs_php_*.php
|
||||
php/extension/guestfs_php_*.sh
|
||||
php/extension/mkinstalldirs
|
||||
php/extension/modules/
|
||||
php/extension/php_guestfs_php.h
|
||||
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
|
||||
po-docs/*/*.1
|
||||
po-docs/*/*.3
|
||||
podwrapper.sh
|
||||
python/__pycache__
|
||||
python/bindtests.py
|
||||
python/examples/guestfs-python.3
|
||||
python/examples/stamp-guestfs-python.pod
|
||||
python/guestfs.py
|
||||
python/guestfs-py.c
|
||||
python/guestfs.pyc
|
||||
rescue/stamp-virt-rescue.pod
|
||||
rescue/virt-rescue
|
||||
rescue/virt-rescue.1
|
||||
resize/stamp-virt-resize.pod
|
||||
resize/utils_tests
|
||||
resize/virt-resize
|
||||
resize/virt-resize.1
|
||||
ruby/bindtests.rb
|
||||
ruby/doc/site/api
|
||||
ruby/examples/guestfs-ruby.3
|
||||
ruby/examples/stamp-guestfs-ruby.pod
|
||||
ruby/ext/guestfs/extconf.h
|
||||
ruby/ext/guestfs/_guestfs.bundle
|
||||
ruby/ext/guestfs/_guestfs.c
|
||||
ruby/ext/guestfs/_guestfs.so
|
||||
ruby/ext/guestfs/mkmf.log
|
||||
ruby/Rakefile
|
||||
run
|
||||
sparsify/stamp-virt-sparsify.pod
|
||||
sparsify/virt-sparsify
|
||||
sparsify/virt-sparsify.1
|
||||
src/actions.c
|
||||
src/bindtests.c
|
||||
src/errnostring_gperf.c
|
||||
src/errnostring_gperf.gperf
|
||||
src/errnostring.c
|
||||
src/errnostring.h
|
||||
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/stamp-guestfs.pod
|
||||
*.swp
|
||||
stamp-h1
|
||||
test-tool/libguestfs-test-tool
|
||||
test-tool/libguestfs-test-tool.1
|
||||
test-tool/libguestfs-test-tool-helper
|
||||
tests/c-api/test.log
|
||||
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-just-header
|
||||
tests/c-api/test-last-errno
|
||||
tests/c-api/test-private-data
|
||||
tests/c-api/test-user-cancel
|
||||
tests/c-api/test*.img
|
||||
tests/c-api/tests
|
||||
tests/c-api/tests.c
|
||||
tests/c-api/test*.tmp
|
||||
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.iso
|
||||
tests/data/test-grep.txt.gz
|
||||
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
|
||||
tools/test.img
|
||||
tools/virt-*.1
|
||||
tools/virt-*.pl
|
||||
/GNUmakefile
|
||||
/maint.mk
|
||||
|
||||
/ABOUT-NLS
|
||||
/aclocal.m4
|
||||
/align/stamp-virt-alignment-scan.pod
|
||||
/align/virt-alignment-scan
|
||||
/align/virt-alignment-scan.1
|
||||
/appliance/excludelist
|
||||
/appliance/libguestfs-make-fixed-appliance
|
||||
/appliance/libguestfs-make-fixed-appliance.1
|
||||
/appliance/make.sh
|
||||
/appliance/packagelist
|
||||
/appliance/stamp-libguestfs-make-fixed-appliance.pod
|
||||
/appliance/stamp-supermin
|
||||
/appliance/supermin.d
|
||||
/autom4te.cache
|
||||
/build-aux
|
||||
/cat/stamp-virt-*.pod
|
||||
/cat/virt-cat
|
||||
/cat/virt-cat.1
|
||||
/cat/virt-filesystems
|
||||
/cat/virt-filesystems.1
|
||||
/cat/virt-ls
|
||||
/cat/virt-ls.1
|
||||
/ChangeLog
|
||||
/compile
|
||||
/config.guess
|
||||
/config.h
|
||||
/config.h.in
|
||||
/config.log
|
||||
/config.status
|
||||
/config.sub
|
||||
/configure
|
||||
/csharp/Libguestfs.cs
|
||||
/daemon/actions.h
|
||||
/daemon/errnostring.c
|
||||
/daemon/errnostring_gperf.c
|
||||
/daemon/errnostring_gperf.gperf
|
||||
/daemon/errnostring.h
|
||||
/daemon/guestfsd
|
||||
/daemon/guestfsd.exe
|
||||
/daemon/guestfs_protocol.c
|
||||
/daemon/guestfs_protocol.h
|
||||
/daemon/install-sh
|
||||
/daemon/missing
|
||||
/daemon/names.c
|
||||
/daemon/optgroups.c
|
||||
/daemon/optgroups.h
|
||||
/daemon/stubs.c
|
||||
/depcomp
|
||||
/df/stamp-virt-df.pod
|
||||
/df/virt-df
|
||||
/df/virt-df.1
|
||||
/edit/stamp-virt-*.pod
|
||||
/edit/virt-edit
|
||||
/edit/virt-edit.1
|
||||
/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/copy_over
|
||||
/examples/create_disk
|
||||
/examples/display_icon
|
||||
/examples/guestfs-examples.3
|
||||
/examples/guestfs-faq.1
|
||||
/examples/guestfs-performance.1
|
||||
/examples/guestfs-recipes.1
|
||||
/examples/guestfs-testing.1
|
||||
/examples/inspect_vm
|
||||
/examples/stamp-guestfs-examples.pod
|
||||
/examples/stamp-guestfs-faq.pod
|
||||
/examples/stamp-guestfs-performance.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
|
||||
/fish/guestfish-actions.pod
|
||||
/fish/guestfish-commands.pod
|
||||
/fish/prepopts.c
|
||||
/fish/prepopts.h
|
||||
/fish/rc_protocol.c
|
||||
/fish/rc_protocol.h
|
||||
/fish/stamp-guestfish.pod
|
||||
/fish/stamp-virt-copy-in.pod
|
||||
/fish/stamp-virt-copy-out.pod
|
||||
/fish/stamp-virt-tar-in.pod
|
||||
/fish/stamp-virt-tar-out.pod
|
||||
/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/.depend
|
||||
/generator/files-generated.txt
|
||||
/generator/generator
|
||||
/generator/.pod2text.data*
|
||||
/generator/stamp-generator
|
||||
/.gitattributes
|
||||
/.git-module-status
|
||||
/gnulib
|
||||
.git-module-status
|
||||
.guestfs-*
|
||||
/GNUmakefile
|
||||
/gobject/bindtests.js
|
||||
/gobject/Guestfs-1.0.gir
|
||||
/gobject/Guestfs-1.0.typelib
|
||||
/gobject/guestfs-gobject*.c
|
||||
/gobject/guestfs-gobject*.h
|
||||
/.guestfs-*
|
||||
/guestfs.*
|
||||
/guestfsd-in-wine.log
|
||||
/haskell/Bindtests
|
||||
/haskell/Bindtests.hs
|
||||
/haskell/Guestfs005Load
|
||||
/haskell/Guestfs010Basic
|
||||
/haskell/Guestfs.hs
|
||||
/html/guestfish.1.html
|
||||
/html/guestfs.3.html
|
||||
/html/guestfs-erlang.3.html
|
||||
/html/guestfs-examples.3.html
|
||||
/html/guestfs-faq.1.html
|
||||
/html/guestfs-java.3.html
|
||||
/html/guestfs-ocaml.3.html
|
||||
/html/guestfs-performance.1.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/guestmount.1.html
|
||||
/html/libguestfs-make-fixed-appliance.1.html
|
||||
/html/libguestfs-test-tool.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
|
||||
/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
|
||||
/inspector/stamp-virt-inspector.pod
|
||||
/inspector/virt-inspector
|
||||
/inspector/virt-inspector.1
|
||||
/install-sh
|
||||
/java/api
|
||||
/java/Bindtests.java
|
||||
/java/com_redhat_et_libguestfs_GuestFS.c
|
||||
/java/com_redhat_et_libguestfs_GuestFS.h
|
||||
/java/com/redhat/et/libguestfs/GuestFS.java
|
||||
/java/doc-stamp
|
||||
/java/examples/guestfs-java.3
|
||||
/java/examples/stamp-guestfs-java.pod
|
||||
/libguestfs.spec
|
||||
/libguestfs-*.tar.gz
|
||||
/libtool
|
||||
/local*
|
||||
/ltmain.sh
|
||||
/m4/ChangeLog
|
||||
/m4/gnulib-cache.m4
|
||||
/m4/intmax.m4
|
||||
/m4/libtool.m4
|
||||
/m4/lt~obsolete.m4
|
||||
/m4/ltoptions.m4
|
||||
/m4/ltsugar.m4
|
||||
/m4/ltversion.m4
|
||||
/maint.mk
|
||||
/missing
|
||||
/ocaml/bindtests.bc
|
||||
/ocaml/bindtests.opt
|
||||
/ocaml/bindtests.ml
|
||||
/ocaml/.depend
|
||||
/ocaml/dllmlguestfs.so
|
||||
/ocaml/examples/create_disk
|
||||
/ocaml/examples/guestfs-ocaml.3
|
||||
/ocaml/examples/inspect_vm
|
||||
/ocaml/examples/stamp-guestfs-ocaml.pod
|
||||
/ocaml/guestfs_c_actions.c
|
||||
/ocaml/guestfs_inspector.ml
|
||||
/ocaml/guestfs_inspector.mli
|
||||
/ocaml/guestfs.ml
|
||||
/ocaml/guestfs.mli
|
||||
/ocamlinit-stamp
|
||||
/ocaml/META
|
||||
/ocaml/t/guestfs_005_load.bc
|
||||
/ocaml/t/guestfs_005_load.opt
|
||||
/ocaml/t/guestfs_010_basic.bc
|
||||
/ocaml/t/guestfs_010_basic.opt
|
||||
/ocaml/t/guestfs_070_threads.bc
|
||||
/ocaml/t/guestfs_070_threads.opt
|
||||
/ocaml/t/guestfs_080_optargs.bc
|
||||
/ocaml/t/guestfs_080_optargs.opt
|
||||
/ocaml/t/guestfs_400_events.bc
|
||||
/ocaml/t/guestfs_400_events.opt
|
||||
/ocaml/t/guestfs_400_progress.bc
|
||||
/ocaml/t/guestfs_400_progress.opt
|
||||
/ocaml/t/guestfs_500_parallel_mount_local.bc
|
||||
/ocaml/t/guestfs_500_parallel_mount_local.opt
|
||||
/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/lib/Sys/Guestfs.pm
|
||||
/perl/Makefile-pl
|
||||
/perl/Makefile.PL
|
||||
/perl/Makefile-pl.old
|
||||
/perl/MYMETA.json
|
||||
/perl/MYMETA.yml
|
||||
/perl/pm_to_blib
|
||||
/php/extension/acinclude.m4
|
||||
/php/extension/aclocal.m4
|
||||
/php/extension/autom4te.cache
|
||||
/php/extension/build/
|
||||
/php/extension/config.guess
|
||||
/php/extension/config.h
|
||||
/php/extension/config.h.in
|
||||
/php/extension/config.log
|
||||
/php/extension/config.nice
|
||||
/php/extension/config.status
|
||||
/php/extension/config.sub
|
||||
/php/extension/configure
|
||||
/php/extension/configure.in
|
||||
/php/extension/guestfs_php.c
|
||||
/php/extension/guestfs_php_*.diff
|
||||
/php/extension/guestfs_php_*.exp
|
||||
/php/extension/guestfs_php_*.log
|
||||
/php/extension/guestfs_php_*.out
|
||||
/php/extension/guestfs_php_*.php
|
||||
/php/extension/guestfs_php_*.sh
|
||||
/php/extension/install-sh
|
||||
/php/extension/libtool
|
||||
/php/extension/ltmain.sh
|
||||
/php/extension/Makefile.fragments
|
||||
/php/extension/Makefile.global
|
||||
/php/extension/Makefile.objects
|
||||
/php/extension/mkinstalldirs
|
||||
/php/extension/missing
|
||||
/php/extension/modules/
|
||||
/php/extension/php_guestfs_php.h
|
||||
/php/extension/run-tests.php
|
||||
/php/extension/tmp-php.ini
|
||||
/po-docs/*/*.1
|
||||
/po-docs/*/*.3
|
||||
/po-docs/*/*.pl
|
||||
/po-docs/po4a.conf
|
||||
/po-docs/*/*.pod
|
||||
/po-docs/*/stamp-update-po
|
||||
/podwrapper.sh
|
||||
/po/*.gmo
|
||||
/python/bindtests.py
|
||||
/python/examples/guestfs-python.3
|
||||
/python/examples/stamp-guestfs-python.pod
|
||||
/python/guestfs.py
|
||||
/python/guestfs-py.c
|
||||
/python/guestfs.pyc
|
||||
/python/guestfs.pyo
|
||||
/python/__pycache__
|
||||
/rescue/stamp-virt-rescue.pod
|
||||
/rescue/virt-rescue
|
||||
/rescue/virt-rescue.1
|
||||
/resize/.depend
|
||||
/resize/resize_gettext.ml
|
||||
/resize/stamp-virt-resize.pod
|
||||
/resize/utils_tests
|
||||
/resize/virt-resize
|
||||
/resize/virt-resize.1
|
||||
/ruby/bindtests.rb
|
||||
/ruby/doc/site/api
|
||||
/ruby/examples/guestfs-ruby.3
|
||||
/ruby/examples/stamp-guestfs-ruby.pod
|
||||
/ruby/ext/guestfs/extconf.h
|
||||
/ruby/ext/guestfs/_guestfs.bundle
|
||||
/ruby/ext/guestfs/_guestfs.c
|
||||
/ruby/ext/guestfs/_guestfs.so
|
||||
/ruby/ext/guestfs/mkmf.log
|
||||
/ruby/Rakefile
|
||||
/run
|
||||
/sparsify/.depend
|
||||
/sparsify/sparsify_gettext.ml
|
||||
/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.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-structs.pod
|
||||
/src/libguestfs.pc
|
||||
/src/libguestfs.syms
|
||||
/src/.libs/libguestfs.so
|
||||
/src/stamp-guestfs.pod
|
||||
/stamp-h1
|
||||
/sysprep/.depend
|
||||
/sysprep/stamp-script1.sh
|
||||
/sysprep/stamp-script2.sh
|
||||
/sysprep/stamp-virt-sysprep.pod
|
||||
/sysprep/sysprep-extra-options.pod
|
||||
/sysprep/sysprep_gettext.ml
|
||||
/sysprep/sysprep-operations.pod
|
||||
/sysprep/virt-sysprep
|
||||
/sysprep/virt-sysprep.1
|
||||
/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-just-header-cxx
|
||||
/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/stamp-fedora-md.img
|
||||
/tests/guests/ubuntu.img
|
||||
/tests/guests/windows.img
|
||||
/tests/regressions/rhbz501893
|
||||
/tests/regressions/rhbz790721
|
||||
/test-tool/libguestfs-test-tool
|
||||
/test-tool/libguestfs-test-tool.1
|
||||
/test-tool/libguestfs-test-tool-helper
|
||||
/test-tool/stamp-libguestfs-test-tool.pod
|
||||
/tools/test.img
|
||||
/tools/virt-*.1
|
||||
/tools/virt-*.pl
|
||||
/valgrind.log.*
|
||||
|
||||
2
.gnulib
2
.gnulib
Submodule .gnulib updated: 18eab914cd...b64318247b
@@ -1,4 +1,3 @@
|
||||
^appliance/debian/modules/
|
||||
^tests/data/
|
||||
^COPYING(.LIB)?$
|
||||
^\.gitmodules$
|
||||
|
||||
52
AUTHORS
52
AUTHORS
@@ -1,24 +1,28 @@
|
||||
Angus Salkeld
|
||||
Ani Peter
|
||||
Charles Duffy
|
||||
Daniel Berrange
|
||||
Daniel Cabrera
|
||||
Douglas Schilling Landgraf
|
||||
Erik Nolte
|
||||
Geert Warrink
|
||||
Guido Günther
|
||||
Hilko Bengen
|
||||
Jaswinder Singh
|
||||
Jim Meyering
|
||||
Karel Klíč
|
||||
Matthew Booth
|
||||
Maxim Koltsov
|
||||
Michael Scherer
|
||||
Nikita A Menkovich
|
||||
Piotr Drąg
|
||||
Rajesh Ranjan
|
||||
Richard W.M. Jones
|
||||
Sandeep Shedmake
|
||||
Shankar Prasad
|
||||
Thomas S Hatch
|
||||
Wanlong Gao
|
||||
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>
|
||||
Jiri Popelka <jpopelka@redhat.com>
|
||||
Karel Klíč <kklic@redhat.com>
|
||||
Marcin Gibula <m.gibula@e24cloud.com>
|
||||
Matthew Booth <mbooth@redhat.com>
|
||||
Maxim Koltsov <kolmax94@gmail.com>
|
||||
Michael Scherer <misc@zarb.org>
|
||||
Nikita A Menkovich <menkovich@gmail.com>
|
||||
Nikos Skalkotos <skalkoto@gmail.com>
|
||||
Piotr Drąg <piotrdrag@gmail.com>
|
||||
Qin Guan <qguan@redhat.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>
|
||||
|
||||
236
BUGS
236
BUGS
@@ -1,5 +1,5 @@
|
||||
NOTE: This file is automatically generated from "update-bugs.sh".
|
||||
Last updated: 2011-12-22
|
||||
Last updated: 2012-05-03
|
||||
|
||||
This contains a local list of the bugs that are open against
|
||||
libguestfs. Bugs are tracked in the Red Hat Bugzilla database
|
||||
@@ -26,62 +26,68 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
684486 NEW https://bugzilla.redhat.com/show_bug.cgi?id=684486
|
||||
Guest fails to boot after virt-resize
|
||||
|
||||
691659 NEW https://bugzilla.redhat.com/show_bug.cgi?id=691659
|
||||
libguestfs fails to run under JRuby 1.6.0
|
||||
|
||||
693064 NEW https://bugzilla.redhat.com/show_bug.cgi?id=693064
|
||||
Symbolic links on ntfs-3g are not followed correctly by some commands
|
||||
|
||||
701814 NEW https://bugzilla.redhat.com/show_bug.cgi?id=701814
|
||||
virt-win-reg fails on a libvirt guest that has no defined disk format: "format parameter is empty or contains disallowed characters"
|
||||
|
||||
709326 NEW https://bugzilla.redhat.com/show_bug.cgi?id=709326
|
||||
virt-inspector cannot detect ReactOS
|
||||
|
||||
719879 NEW https://bugzilla.redhat.com/show_bug.cgi?id=719879
|
||||
Rebase libguestfs in RHEL 6.3
|
||||
|
||||
728224 NEW https://bugzilla.redhat.com/show_bug.cgi?id=728224
|
||||
configure can't find qemu on PPC
|
||||
|
||||
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
|
||||
|
||||
755729 NEW https://bugzilla.redhat.com/show_bug.cgi?id=755729
|
||||
Error message for resize2fs-M needs tweaking
|
||||
|
||||
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
|
||||
|
||||
765814 NEW https://bugzilla.redhat.com/show_bug.cgi?id=765814
|
||||
root can't access user mounted images
|
||||
770075 NEW https://bugzilla.redhat.com/show_bug.cgi?id=770075
|
||||
FEBOOTSTRAP_MODULES fails if modules directory is not under /lib
|
||||
|
||||
767852 NEW https://bugzilla.redhat.com/show_bug.cgi?id=767852
|
||||
dependency on fuse suggested
|
||||
770076 NEW https://bugzilla.redhat.com/show_bug.cgi?id=770076
|
||||
FEBOOTSTRAP_KERNEL causes appliance build to fail
|
||||
|
||||
769304 NEW https://bugzilla.redhat.com/show_bug.cgi?id=769304
|
||||
virt-resize on RHEL 6 kernel fails to re-read the partition table
|
||||
782167 NEW https://bugzilla.redhat.com/show_bug.cgi?id=782167
|
||||
libguestfs doesn't recognize Windows Dynamic disks in some configurations, eg. spanned
|
||||
|
||||
769359 NEW https://bugzilla.redhat.com/show_bug.cgi?id=769359
|
||||
virt-resize on RHEL 6 kernel fails to re-read the partition table
|
||||
785603 NEW https://bugzilla.redhat.com/show_bug.cgi?id=785603
|
||||
copy-out can't find root directory
|
||||
|
||||
769680 NEW https://bugzilla.redhat.com/show_bug.cgi?id=769680
|
||||
temporary directories created during appliance builds are not cleaned up on error
|
||||
790837 NEW https://bugzilla.redhat.com/show_bug.cgi?id=790837
|
||||
Use of atexit to clean up handles is wrong in multithreaded programs
|
||||
|
||||
798979 NEW https://bugzilla.redhat.com/show_bug.cgi?id=798979
|
||||
Ubuntu install CDs from oneiric onwards are not recognized: "multi-boot operating systems are not supported"
|
||||
|
||||
801117 NEW https://bugzilla.redhat.com/show_bug.cgi?id=801117
|
||||
libguestfs cannot get icon for Windows 8 preview
|
||||
|
||||
808193 NEW https://bugzilla.redhat.com/show_bug.cgi?id=808193
|
||||
g.launch() crashes on RHEL 5
|
||||
|
||||
811265 NEW https://bugzilla.redhat.com/show_bug.cgi?id=811265
|
||||
the list-filesystems can detect the reiserFS,but can not mount it.and minix filesystem too.
|
||||
|
||||
811395 NEW https://bugzilla.redhat.com/show_bug.cgi?id=811395
|
||||
virt-inspector to detect ia64 Windows 2k3 install media
|
||||
|
||||
811398 NEW https://bugzilla.redhat.com/show_bug.cgi?id=811398
|
||||
virt-inspector fails to detect Win2k, Win2k8, Win2k8r2, WinVista, Win7 install media
|
||||
|
||||
812970 NEW https://bugzilla.redhat.com/show_bug.cgi?id=812970
|
||||
virt-rescue cannot set ><rescue> prompt, on Ubuntu 12.04
|
||||
|
||||
813271 NEW https://bugzilla.redhat.com/show_bug.cgi?id=813271
|
||||
intermittent appliance boot failures (divide_error)
|
||||
|
||||
813290 NEW https://bugzilla.redhat.com/show_bug.cgi?id=813290
|
||||
mdadm (md-detail) test occasionally fails with 'md device /dev/md125 does not appear to be active.'
|
||||
|
||||
815149 NEW https://bugzilla.redhat.com/show_bug.cgi?id=815149
|
||||
virt-alignment-scan gives error "part_list: could not parse row from output of parted print command: /dev/vda:4194304B:virtblk:512:512:msdos:Virtio Block Device"
|
||||
|
||||
563450 NEW https://bugzilla.redhat.com/show_bug.cgi?id=563450
|
||||
list-devices returns devices of different types out of order
|
||||
@@ -89,18 +95,42 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
696445 NEW https://bugzilla.redhat.com/show_bug.cgi?id=696445
|
||||
Backport virt-inspector for virt-v2v
|
||||
|
||||
806176 NEW https://bugzilla.redhat.com/show_bug.cgi?id=806176
|
||||
libguestfs doesn't use the external tools (wrestool ...) to get icon even these tools are installed
|
||||
|
||||
813329 NEW https://bugzilla.redhat.com/show_bug.cgi?id=813329
|
||||
virt-p2v can not convert physical host on MD device
|
||||
|
||||
547488 NEW https://bugzilla.redhat.com/show_bug.cgi?id=547488
|
||||
guestfish cannot tab complete filenames that contain spaces
|
||||
|
||||
672485 NEW https://bugzilla.redhat.com/show_bug.cgi?id=672485
|
||||
[RFE] virt-edit/tar/inspector do not support encrypted system
|
||||
|
||||
679737 NEW https://bugzilla.redhat.com/show_bug.cgi?id=679737
|
||||
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
|
||||
|
||||
801640 NEW https://bugzilla.redhat.com/show_bug.cgi?id=801640
|
||||
[RFE] the error reported by resize2fs-M need to be more clear
|
||||
|
||||
803643 NEW https://bugzilla.redhat.com/show_bug.cgi?id=803643
|
||||
inspect-is-multipart return false when inspection results should be true
|
||||
|
||||
803650 NEW https://bugzilla.redhat.com/show_bug.cgi?id=803650
|
||||
inspect-is-live return false when inspection results should be true
|
||||
|
||||
803657 NEW https://bugzilla.redhat.com/show_bug.cgi?id=803657
|
||||
[RFE] inspect-is-netinst : support more distributions
|
||||
|
||||
805417 NEW https://bugzilla.redhat.com/show_bug.cgi?id=805417
|
||||
RFE: support inspection of installation ISOs of WinVista, Win7, Win2008 & Win2008r2
|
||||
|
||||
806179 NEW https://bugzilla.redhat.com/show_bug.cgi?id=806179
|
||||
RFE: support inspection of icon for more Windows guests
|
||||
|
||||
816839 NEW https://bugzilla.redhat.com/show_bug.cgi?id=816839
|
||||
data overflow error when debug progress -1
|
||||
|
||||
507278 NEW https://bugzilla.redhat.com/show_bug.cgi?id=507278
|
||||
libguestfs fails to build on Fedora sparc64
|
||||
|
||||
@@ -116,18 +146,12 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
578103 NEW https://bugzilla.redhat.com/show_bug.cgi?id=578103
|
||||
[RFE] Tool to Compare Windows Registry Entries
|
||||
|
||||
592910 NEW https://bugzilla.redhat.com/show_bug.cgi?id=592910
|
||||
'guestfish --remote run' hangs in a shell command substitution context
|
||||
|
||||
593511 NEW https://bugzilla.redhat.com/show_bug.cgi?id=593511
|
||||
[RFE] function to get partition name
|
||||
|
||||
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
|
||||
|
||||
@@ -140,9 +164,6 @@ 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
|
||||
|
||||
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
|
||||
|
||||
@@ -161,8 +182,11 @@ 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
|
||||
802389 NEW https://bugzilla.redhat.com/show_bug.cgi?id=802389
|
||||
event handlers for 'close' event doesn't work in remote mode
|
||||
|
||||
691389 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=691389
|
||||
Extended attributes don't work over guestmount (FUSE)
|
||||
|
||||
713678 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=713678
|
||||
Not all febootstrap messages are redirected to log callbacks
|
||||
@@ -170,12 +194,6 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
721160 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=721160
|
||||
Missing btrfs support
|
||||
|
||||
583974 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=583974
|
||||
mount hangs there when you lack proper permission to guest image
|
||||
|
||||
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
|
||||
|
||||
@@ -188,23 +206,113 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
|
||||
619334 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=619334
|
||||
RFE: Enable coredump capture in the appliance
|
||||
|
||||
(62 bugs)
|
||||
|
||||
--------------------------------------------------
|
||||
Bugs in MODIFIED, POST or ON_QA state are fixed.
|
||||
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.
|
||||
|
||||
760000 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=760000
|
||||
libguestfs fails to compile with Ruby >= 1.9
|
||||
|
||||
657499 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=657499
|
||||
checksum: wrong check sum type causes umount to fail
|
||||
|
||||
719879 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=719879
|
||||
Rebase libguestfs in RHEL 6.3
|
||||
|
||||
729076 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=729076
|
||||
libguestfs confuses Hp_recovery partition with Windows root filesystem
|
||||
|
||||
749828 ON_QA https://bugzilla.redhat.com/show_bug.cgi?id=749828
|
||||
p2v does not support raid devices
|
||||
|
||||
741183 ON_QA 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
|
||||
|
||||
(5 bugs)
|
||||
|
||||
--------------------------------------------------
|
||||
These bugs are in the VERIFIED state.
|
||||
|
||||
731742 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=731742
|
||||
libguestfs should escape special/non-printing characters in debug output
|
||||
|
||||
760221 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=760221
|
||||
RFE: Support inspection of cciss devices
|
||||
|
||||
769359 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=769359
|
||||
virt-resize on RHEL 6 kernel fails to re-read the partition table
|
||||
|
||||
785305 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=785305
|
||||
ocaml (bytecode) bindings segfault in 'add_drive_opts'
|
||||
|
||||
788642 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=788642
|
||||
virt-edit doesn't preserve file permissions
|
||||
|
||||
790958 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=790958
|
||||
multiprovider build error: RuntimeError: link: /tmp/.guestfs-0/kernel /tmp/.guestfs-0/kernel.10139: File exists
|
||||
|
||||
797760 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=797760
|
||||
virt-resize on Windows XP in sysprep state causes "UNMOUNTABLE_BOOT_VOLUME" BSOD
|
||||
|
||||
798197 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=798197
|
||||
virt-resize confuses format and output_format variables; using --output-format sets the input format
|
||||
|
||||
798980 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=798980
|
||||
Libguestfs live support should be disabled in RHEL 6 packages
|
||||
|
||||
799695 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=799695
|
||||
guestfs.h fails to compile with c++ compiler
|
||||
|
||||
801788 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=801788
|
||||
libguestfs holds open file descriptors when handle is launched
|
||||
|
||||
803699 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=803699
|
||||
libguestfs inspection fails on Windows XP: libguestfs: error: hivex: could not locate HKLMSYSTEMMountedDevices
|
||||
|
||||
809401 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=809401
|
||||
inspection doesn't recognize Fedora 17+ (because of grub2 and UsrMove)
|
||||
|
||||
811673 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=811673
|
||||
guestfs_last_error not set when qemu fails early during launch
|
||||
|
||||
812092 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=812092
|
||||
libguestfs cannot open disk images which are symlinks to files that contain ':' (colon) character
|
||||
|
||||
647174 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=647174
|
||||
RHEL6: virt-clone should remove old udev rules when changing MAC address
|
||||
|
||||
789960 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=789960
|
||||
guestfsd crash when try to mount non-exist disk
|
||||
|
||||
799798 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=799798
|
||||
set_autosync: this function can only be called in the config state at /usr/share/perl5/vendor_perl/Sys/VirtConvert/GuestfsHandle.pm line 107
|
||||
|
||||
807557 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=807557
|
||||
virt-sysprep: wrong params are passed to virt-inspector
|
||||
|
||||
807905 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=807905
|
||||
mkfs blocksize option breaks when creating btrfs
|
||||
|
||||
811112 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=811112
|
||||
[RFE][virt-sysprep] hostname can not be changed on rhel system
|
||||
|
||||
811117 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=811117
|
||||
[RFE][virt-sysprep] net-hwaddr not removed from "ifcfg-*" files on rhel
|
||||
|
||||
679737 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=679737
|
||||
libguestfs: improve error message when zerofree is not available in the appliance
|
||||
|
||||
785668 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=785668
|
||||
aug-defnode: daemon crash
|
||||
|
||||
795322 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=795322
|
||||
add_ro should return error if not running in a config state
|
||||
|
||||
796520 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=796520
|
||||
[RFE] Prevent user from running some appliance configure commands after appliance boot up
|
||||
|
||||
801273 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=801273
|
||||
Document for set-pgroup need to be updated
|
||||
|
||||
(27 bugs)
|
||||
|
||||
End of BUGS file.
|
||||
|
||||
78
Makefile.am
78
Makefile.am
@@ -1,5 +1,5 @@
|
||||
# libguestfs
|
||||
# Copyright (C) 2009-2011 Red Hat Inc.
|
||||
# Copyright (C) 2009-2012 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
|
||||
@@ -33,6 +33,7 @@ SUBDIRS += appliance
|
||||
endif
|
||||
|
||||
# Tests - order is important.
|
||||
if ENABLE_APPLIANCE
|
||||
SUBDIRS += tests/qemu
|
||||
SUBDIRS += tests/guests
|
||||
SUBDIRS += tests/c-api
|
||||
@@ -40,7 +41,11 @@ SUBDIRS += tests/protocol
|
||||
SUBDIRS += tests/lvm
|
||||
SUBDIRS += tests/luks
|
||||
SUBDIRS += tests/md
|
||||
SUBDIRS += tests/ntfsclone
|
||||
SUBDIRS += tests/btrfs
|
||||
SUBDIRS += tests/xml
|
||||
SUBDIRS += tests/regressions
|
||||
endif
|
||||
|
||||
# Extra tests don't run by default. You have to do 'make extra-tests'.
|
||||
SUBDIRS += tests/extra
|
||||
@@ -52,7 +57,7 @@ SUBDIRS += test-tool
|
||||
SUBDIRS += fish
|
||||
|
||||
# virt-tools in C.
|
||||
SUBDIRS += align cat df edit inspector rescue
|
||||
SUBDIRS += align cat df edit format inspector rescue
|
||||
|
||||
# Language bindings.
|
||||
if HAVE_PERL
|
||||
@@ -79,13 +84,16 @@ endif
|
||||
if HAVE_ERLANG
|
||||
SUBDIRS += erlang erlang/examples
|
||||
endif
|
||||
if HAVE_GOBJECT
|
||||
SUBDIRS += gobject
|
||||
endif
|
||||
|
||||
# Unconditional because nothing is built yet.
|
||||
SUBDIRS += csharp
|
||||
|
||||
# virt-resize (new version) and virt-sparsify are written in OCaml.
|
||||
# OCaml tools.
|
||||
if HAVE_OCAML
|
||||
SUBDIRS += resize sparsify
|
||||
SUBDIRS += resize sparsify sysprep
|
||||
endif
|
||||
|
||||
# Perl tools.
|
||||
@@ -98,11 +106,6 @@ 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
|
||||
@@ -121,6 +124,7 @@ EXTRA_DIST = \
|
||||
contrib/intro/overview.svg \
|
||||
contrib/intro/talk.txt \
|
||||
contrib/intro/tools.svg \
|
||||
contrib/make-check-on-installed.pl \
|
||||
contrib/README \
|
||||
contrib/visualize-alignment/.gitignore \
|
||||
contrib/visualize-alignment/guestfish-add-mount.qtr \
|
||||
@@ -132,47 +136,21 @@ EXTRA_DIST = \
|
||||
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 \
|
||||
debian/control \
|
||||
debian/copyright \
|
||||
debian/docs \
|
||||
debian/guestfish.dirs \
|
||||
debian/guestfish.install \
|
||||
debian/guestfsd.dirs \
|
||||
debian/guestfsd.install \
|
||||
debian/guestmount.dirs \
|
||||
debian/guestmount.install \
|
||||
debian/libguestfs-dev.dirs \
|
||||
debian/libguestfs-dev.install \
|
||||
debian/libguestfs-doc.docs \
|
||||
debian/libguestfs-perl.examples \
|
||||
debian/libguestfs-perl.install \
|
||||
debian/libguestfs-tools.dirs \
|
||||
debian/libguestfs-tools.install \
|
||||
debian/libguestfs0.dirs \
|
||||
debian/libguestfs0.install \
|
||||
debian/patches/series \
|
||||
debian/python-guestfs.install \
|
||||
debian/pyversions \
|
||||
debian/rules \
|
||||
debian/shlibs.local \
|
||||
debian/watch \
|
||||
html/pod.css \
|
||||
libguestfs.pc libguestfs.pc.in \
|
||||
libtool-kill-dependency_libs.sh \
|
||||
logo/fish.svg logo/fish.png \
|
||||
m4/.gitignore \
|
||||
run \
|
||||
update-bugs.sh
|
||||
|
||||
# The website.
|
||||
HTMLFILES = \
|
||||
html/guestfs.3.html \
|
||||
html/guestfs-examples.3.html \
|
||||
html/guestfs-erlang.3.html \
|
||||
html/guestfs-faq.1.html \
|
||||
html/guestfs-java.3.html \
|
||||
html/guestfs-ocaml.3.html \
|
||||
html/guestfs-performance.1.html \
|
||||
html/guestfs-perl.3.html \
|
||||
html/guestfs-python.3.html \
|
||||
html/guestfs-recipes.1.html \
|
||||
@@ -180,6 +158,8 @@ HTMLFILES = \
|
||||
html/guestfs-testing.1.html \
|
||||
html/guestfish.1.html \
|
||||
html/guestmount.1.html \
|
||||
html/libguestfs-make-fixed-appliance.1.html \
|
||||
html/libguestfs-test-tool.1.html \
|
||||
html/virt-alignment-scan.1.html \
|
||||
html/virt-cat.1.html \
|
||||
html/virt-copy-in.1.html \
|
||||
@@ -187,6 +167,7 @@ HTMLFILES = \
|
||||
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 \
|
||||
@@ -205,7 +186,11 @@ TEXTFILES = BUGS README RELEASE-NOTES ROADMAP TODO
|
||||
|
||||
WEBSITEDIR = $(HOME)/d/redhat/websites/libguestfs
|
||||
|
||||
# For reasons not fully understood, we need to rebuild all the
|
||||
# man pages and HTMLFILES from scratch here.
|
||||
website: $(HTMLFILES) $(TEXTFILES)
|
||||
find -name 'stamp-*.pod' -delete
|
||||
$(MAKE)
|
||||
cp $(HTMLFILES) $(WEBSITEDIR)
|
||||
for f in $(TEXTFILES); do cp $$f $(WEBSITEDIR)/$$f.txt; done
|
||||
cd $(WEBSITEDIR) && \
|
||||
@@ -221,14 +206,16 @@ 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
|
||||
mv AUTHORS-t AUTHORS
|
||||
cp AUTHORS $(distdir)/AUTHORS
|
||||
|
||||
# Update the list of translatable files in po/POTFILES.in.
|
||||
# Update the list of translatable files (po/POTFILES po/POTFILES-ml).
|
||||
# This has to be in the top-level Makefile.am so that we have access
|
||||
# to DIST_SUBDIRS.
|
||||
all-local:
|
||||
cd $(srcdir); \
|
||||
find $(DIST_SUBDIRS) \
|
||||
@@ -242,16 +229,13 @@ all-local:
|
||||
grep -v '^perl/examples/' | \
|
||||
grep -v '/guestfs_protocol.c' | \
|
||||
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
|
||||
|
||||
# Pkgconfig.
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libguestfs.pc
|
||||
sed 's,^\./,,' > po/POTFILES
|
||||
cd $(srcdir); \
|
||||
find resize sparsify sysprep -name '*.ml' | \
|
||||
LC_ALL=C sort > po/POTFILES-ml
|
||||
|
||||
# Make clean.
|
||||
|
||||
|
||||
22
README
22
README
@@ -26,9 +26,18 @@ Fedora/RHEL users:
|
||||
|
||||
Debian/Ubuntu users:
|
||||
|
||||
Take a look at the debian/control file and install everything listed
|
||||
in "Build-Depends". If that is successful, you don't need to bother
|
||||
with the rest of this section.
|
||||
Use:
|
||||
|
||||
apt-get build-dep libguestfs
|
||||
|
||||
to install all build dependencies. If that doesn't work, take a
|
||||
look at the Debian source package:
|
||||
http://packages.debian.org/source/libguestfs
|
||||
at the list of 'build-depends' and 'build-depends-indep', and
|
||||
install everything listed there.
|
||||
|
||||
If either of those techniques is successful, you don't need to
|
||||
bother with the rest of this section.
|
||||
|
||||
The full requirements are described below.
|
||||
|
||||
@@ -91,12 +100,17 @@ For basic functionality and the C tools:
|
||||
- OCaml if you want to rebuild the generated files, and
|
||||
also to build the OCaml bindings (optional)
|
||||
|
||||
- ocaml-gettext if you want to translate OCaml tools (optional)
|
||||
|
||||
- po4a for translating manpages and POD files.
|
||||
This is optional when compiling from the tarball, but mandatory
|
||||
if you compile from git.
|
||||
|
||||
- getfacl, getfattr libraries and programs (optional)
|
||||
|
||||
- netpbm, icoutils (optional)
|
||||
These programs are used to render icons from guests.
|
||||
|
||||
To build FUSE support (guestmount):
|
||||
|
||||
- FUSE libraries and kernel module (optional)
|
||||
@@ -261,7 +275,7 @@ appliance. You will need to port the febootstrap first
|
||||
Copyright and license information
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2009-2011 Red Hat Inc.
|
||||
Copyright (C) 2009-2012 Red Hat Inc.
|
||||
|
||||
The library is distributed under the LGPLv2+. The programs are
|
||||
distributed under the GPLv2+. Please see the files COPYING and
|
||||
|
||||
338
RELEASE-NOTES
338
RELEASE-NOTES
@@ -1,3 +1,341 @@
|
||||
Release notes for libguestfs 1.18.0
|
||||
-----------------------------------
|
||||
|
||||
UPDATED TO COMMIT 500cc67f29b43ebb970f6f276967ee5e9959b140
|
||||
|
||||
These release notes only cover the differences from the previous
|
||||
stable/dev branch split (1.16.0). For detailed changelogs, please see
|
||||
the git repository, or the ChangeLog file distributed in the tarball.
|
||||
|
||||
New features
|
||||
|
||||
virt tools:
|
||||
|
||||
- virt-sysprep has been rewritten and expanded (thanks Wanlong Gao)
|
||||
|
||||
- virt-edit preserves permissions, UID, GID and SELinux context
|
||||
when editing files
|
||||
|
||||
- virt-sparsify --zero is a new option that zeroes the named
|
||||
partition or filesystem
|
||||
|
||||
- virt-sparsify can now safely sparsify Linux swap partitions
|
||||
|
||||
- virt-sparsify fixed so it cleans up after ^C
|
||||
|
||||
- a new tool 'libguestfs-make-fixed-appliance' is provided to build
|
||||
fixed appliances that can be copied to other machines that don't
|
||||
have febootstrap support
|
||||
|
||||
- virt-filesystems now displays the parents (containers) of MD
|
||||
devices and volume groups
|
||||
|
||||
- virt-alignment-scan, run with no args, displays alignment information
|
||||
for all libvirt domains
|
||||
|
||||
- virt-rescue new --scratch option to make scratch disks
|
||||
|
||||
- comma and colon characters in filenames now handled correctly by
|
||||
all virt tools
|
||||
|
||||
- guestfish passes the close event over stdout and remote correctly
|
||||
|
||||
inspection:
|
||||
|
||||
- added support for Fedora 17+
|
||||
|
||||
- added support for FreeDOS
|
||||
|
||||
- added support for Buildroot and Cirros
|
||||
|
||||
- inspection is now compatible with Windows guests that have been
|
||||
sysprepped (thanks Grant Williamson).
|
||||
|
||||
API:
|
||||
|
||||
- new man page: guestfs-performance(1), which contains performance
|
||||
tuning tips.
|
||||
|
||||
- new man page: guestfs-faq(1), Frequently Asked Questions
|
||||
|
||||
- ENOTSUP (from guestfs_last_errno) is now returned for APIs that
|
||||
are not supported
|
||||
|
||||
examples:
|
||||
|
||||
- 'copy_over' example showing how to copy between two handles
|
||||
|
||||
- 'display_icon' program displays the icon associated with a guest
|
||||
|
||||
Security
|
||||
|
||||
(no security problems were found or fixed in this release)
|
||||
|
||||
New APIs
|
||||
|
||||
btrfs-device-add: Add devices to a btrfs filesystem.
|
||||
btrfs-device-delete: Remove devices from a btrfs filesystem.
|
||||
btrfs-filesystem-sync: Sync a btrfs filesystem.
|
||||
btrfs-filesystem-balance: Balance a btrfs filesystem.
|
||||
btrfs-subvolume-create: Create a btrfs snapshot.
|
||||
btrfs-subvolume-delete: Delete a btrfs snapshot.
|
||||
btrfs-subvolume-list: List btrfs snapshots and subvolumes.
|
||||
btrfs-subvolume-set-default: Set default btrfs subvolume.
|
||||
btrfs-subvolume-snapshot: Create a writable btrfs snapshot.
|
||||
get-e2attrs: List ext2 file attributes of a file.
|
||||
get-e2generation: Get ext2 file generation of a file.
|
||||
isoinfo, isoinfo-device: Get information from the header of ISO files.
|
||||
llz: List files with SELinux information.
|
||||
lvcreate-free: Create an LVM logical volume in % remaining free space.
|
||||
md-stat: Return underlying devices from an MD device.
|
||||
mkfs-brtfs: Make btrfs filesystem, with all tunables.
|
||||
mount-local, mount-local-run, umount-local: FUSE support in the API.
|
||||
ntfsclone-in, ntfsclone-out: Save, restore NTFS from backup.
|
||||
ntfsfix: Fix common errors and force Windows to check NTFS.
|
||||
set-e2attrs: Set or clear ext2 file attributes of a file.
|
||||
set-e2generation: Set ext2 file generation of a file.
|
||||
set-label: Unified interface for setting filesystem label.
|
||||
vgmeta: Get volume group metadata.
|
||||
wipefs: Wipe filesystem signatures from a device.
|
||||
zero-free-space: Zero free space in a filesystem.
|
||||
|
||||
Internals
|
||||
|
||||
- The debian/ subdirectory has been removed. We recommend you use
|
||||
the official Debian packages made by Hilko Bengen.
|
||||
|
||||
- O_CLOEXEC / SOCK_CLOEXEC is now used for almost all file
|
||||
descriptors that the library opens.
|
||||
|
||||
- posix_fadvise is called when sequentially reading or writing large
|
||||
files.
|
||||
|
||||
- close all file descriptors and remove all signal handlers in the
|
||||
recovery process
|
||||
|
||||
- multiple gcc warnings and Coverity bugs have been fixed; many
|
||||
strict-overflow bugs have also been fixed
|
||||
|
||||
- use ./configure --enable-valgrind-daemon to use valgrind on the
|
||||
daemon; many errors have been fixed
|
||||
|
||||
- the daemon now has a growable strings buffer type (DECLARE_STRINGSBUF)
|
||||
|
||||
- the <guestfs.h> header file works with C++ and we have a regression
|
||||
test for this
|
||||
|
||||
- multiple APIs which should only be called in the CONFIG state now
|
||||
give an error if they are not
|
||||
|
||||
- .gitignore fixed to use absolute paths
|
||||
|
||||
- gobject bindings have been expanded, including mapping libguestfs
|
||||
events to gobject signals (thanks Matt Booth)
|
||||
|
||||
- gobject documentation is generated properly (thanks Matt Booth)
|
||||
|
||||
- gobject header files now live in a subdirectory
|
||||
|
||||
- CompareWithString test in the generator now works
|
||||
|
||||
- FUInt32, FUInt64 struct field types now use the correct XDR type
|
||||
|
||||
- OCaml tests are now run on bytecode and native code.
|
||||
|
||||
- java -Xlint:all is used, and all warnings have been fixed
|
||||
|
||||
- bmptopng, wrestool (etc) missing or failure no longer prints
|
||||
warning messages
|
||||
|
||||
- ruby: Use RbConfig instead of Config.
|
||||
|
||||
- PYTHONPATH is set by the ./run script.
|
||||
|
||||
- appliance building is now thread-safe.
|
||||
|
||||
- appliance now uses 'ip' instead of 'ifconfig' and 'netstat'
|
||||
commands
|
||||
|
||||
- several fixes to make parallel builds work properly
|
||||
|
||||
- guestfish --listen now cleans up properly
|
||||
|
||||
- the BUSY state has been removed
|
||||
|
||||
- gettextize has been removed, replaced by a simple Makefile.am
|
||||
|
||||
- gettext support now covers virt-resize, virt-sparsify and virt-sysprep
|
||||
|
||||
Bugs fixed
|
||||
|
||||
[./bugs-in-changelog.sh 1.16.0..]
|
||||
|
||||
- 811872 inspection fails on ubuntu 10.04 guest with encrypted swap
|
||||
- 811650 guestfs_last_error not set when qemu fails early during launch
|
||||
- 811649 libguestfs cannot open disk images which are symlinks to files that contain ':' (colon) character
|
||||
- 811117 [RFE][virt-sysprep] net-hwaddr not removed from "ifcfg-*" files on rhel
|
||||
- 811112 [RFE][virt-sysprep] hostname can not be changed on rhel system
|
||||
- 809361 inspection doesn't recognize Fedora 18 (grub2 + GPT)
|
||||
- 807905 mkfs blocksize option breaks when creating btrfs
|
||||
- 805070 virt-filesystems should show 'parents' of LV and RAID devices
|
||||
- 804464 libguestfs cannot be built when LINGUAS is different then ja or uk
|
||||
- 803664 libguestfs inspection fails on Windows XP: libguestfs: error: hivex: could not locate HKLM\SYSTEM\MountedDevices
|
||||
- 802109 libguestfs uses putc on stderr, results in many individual 1 byte writes of debug messages
|
||||
- 801273 Document for set-pgroup need to be updated
|
||||
- 798196 virt-resize confuses format and output_format variables; using --output-format sets the input format
|
||||
- 797986 virt-resize on Windows XP in sysprep state causes "UNMOUNTABLE_BOOT_VOLUME" BSOD
|
||||
- 796520 [RFE] Prevent user from running some appliance configure commands after appliance boot up
|
||||
- 790721 multiprovider build error: RuntimeError: link: /tmp/.guestfs-0/kernel /tmp/.guestfs-0/kernel.10139: File exists
|
||||
- 789960 guestfsd crash when try to mount non-exist disk
|
||||
- 788641 virt-edit doesn't preserve file permissions
|
||||
- 786215 libguestfs inspection does not recognize FreeDOS operating system
|
||||
- 786188 libguestfs inspection does not recognize FreeDOS install CD
|
||||
- 785668 aug-defnode: daemon crash
|
||||
- 784647 Libguestfs uses deprecated net-tools
|
||||
- 769304 virt-resize on RHEL 6 kernel fails to re-read the partition table
|
||||
- 679737 libguestfs: improve error message when zerofree is not available in the appliance
|
||||
|
||||
|
||||
Release notes for libguestfs 1.16.0
|
||||
-----------------------------------
|
||||
|
||||
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:
|
||||
|
||||
- Experimental GObject bindings, with support for GObject
|
||||
Introspection. You can now use libguestfs from Javascript.
|
||||
Please note these are not stable and final in this release.
|
||||
(Matthew Booth).
|
||||
|
||||
- support for Ruby >= 1.9
|
||||
|
||||
- Ruby bindings can be disabled individually (Hilko Bengen)
|
||||
|
||||
- support for Python 2.6, 3.x (Richard Jones, Hilko Bengen)
|
||||
|
||||
- support for PHP >= 5.4
|
||||
|
||||
- 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:
|
||||
|
||||
- New tool virt-format for erasing and making blank disks
|
||||
|
||||
- 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)
|
||||
e2fsck: access to more features of e2fsck (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).
|
||||
|
||||
With gcc -fvisibility=hidden is used for internal symbols, avoiding
|
||||
call indirection via the PLT.
|
||||
|
||||
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.
|
||||
|
||||
psmisc has been added to the appliance, allowing use of 'fuser',
|
||||
'killall' and 'pstree' for debugging.
|
||||
|
||||
bindtests now cover RBufferOut and optional arguments (Matthew Booth).
|
||||
|
||||
Bugs fixed
|
||||
|
||||
- 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
|
||||
- 755729 Error message for resize2fs-M needs tweaking
|
||||
- 750889 Python code incompatible with Python v3.
|
||||
- 596761 Ctrl-\ causes guestfish to abort
|
||||
|
||||
|
||||
Release notes for libguestfs 1.14.0
|
||||
-----------------------------------
|
||||
|
||||
|
||||
12
ROADMAP
12
ROADMAP
@@ -12,15 +12,19 @@ Before you read this:
|
||||
|
||||
(4) For general "might be good to have" items, see 'TODO'.
|
||||
|
||||
For next major stable release (1.16)
|
||||
For next major stable release (1.18)
|
||||
------------------------------------
|
||||
|
||||
Bugs assigned to 1.16 (put "1.16" in the Devel Whiteboard field in
|
||||
* Allow remote libvirt volumes to be accessed. This requires some
|
||||
enhancements to libvirt which have been agreed but not yet
|
||||
implemented.
|
||||
|
||||
Bugs assigned to 1.18 (put "1.18" 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.16&component=libguestfs&product=Virtualization%20Tools
|
||||
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.18&component=libguestfs&product=Virtualization%20Tools
|
||||
|
||||
Beyond 1.16
|
||||
Beyond 1.18
|
||||
-----------
|
||||
|
||||
* Make 'guestfish --ro' be the default, and get users to use
|
||||
|
||||
221
TODO
221
TODO
@@ -43,46 +43,6 @@ data, at least partially. This would be just another output type so:
|
||||
Note that recent versions of libvirt/virt-install allow guests to be
|
||||
imported, so this is not so useful any more.
|
||||
|
||||
"Standalone/local mode"
|
||||
-----------------------
|
||||
|
||||
Instead of running guestfsd (the daemon) inside qemu, there should be
|
||||
an option to just run guestfsd directly.
|
||||
|
||||
The architecture in this mode would look like:
|
||||
|
||||
+------------------+
|
||||
| main program |
|
||||
|------------------|
|
||||
| libguestfs |
|
||||
+--------^---------+
|
||||
| | reply
|
||||
cmd | |
|
||||
+----v-------------+
|
||||
| guestfsd |
|
||||
+------------------+
|
||||
|
||||
Notes:
|
||||
|
||||
(1) This only makes sense if we are running as root.
|
||||
|
||||
(2) There is no console / kernel messages in this configuration, but
|
||||
we might consider capturing stderr from the daemon.
|
||||
|
||||
(3) guestfs_config and guestfs_add_drive become no-ops.
|
||||
|
||||
Obviously in this configuration, commands are run directly on the
|
||||
local machine's disks. You could just run the commands themselves
|
||||
directly, but libguestfs provides a convenient API and language
|
||||
bindings. Also deals with tricky stuff like parsing the output of the
|
||||
LVM commands. Also we get to leverage other code such as
|
||||
virt-inspector.
|
||||
|
||||
This is mainly useful from live CDs, ie. virt-p2v.
|
||||
|
||||
Should we bother having the daemon at all and just link the guestfsd
|
||||
code directly into libguestfs?
|
||||
|
||||
Ideas for extra commands
|
||||
------------------------
|
||||
|
||||
@@ -91,16 +51,12 @@ Ideas for extra commands
|
||||
more mk*temp calls
|
||||
|
||||
ext2 properties:
|
||||
chattr
|
||||
lsattr
|
||||
badblocks
|
||||
debugfs
|
||||
dumpe2fs
|
||||
e2image
|
||||
e2undo
|
||||
filefrag
|
||||
findfs
|
||||
logsave
|
||||
mklost+found
|
||||
|
||||
SELinux:
|
||||
@@ -120,74 +76,6 @@ Such as:
|
||||
initrd-extract
|
||||
initrd-replace
|
||||
|
||||
Simple editing of configuration files
|
||||
-------------------------------------
|
||||
|
||||
Some easy non-Augeas methods to edit configuration files.
|
||||
I'm thinking:
|
||||
|
||||
replace /etc/file key value
|
||||
|
||||
which would look in /etc/file for any instances of
|
||||
|
||||
key=...
|
||||
key ...
|
||||
key:...
|
||||
|
||||
and replace them with
|
||||
|
||||
key=value
|
||||
key value
|
||||
key:value
|
||||
|
||||
That would solve about 50% of reconfiguration needs, and for the
|
||||
rest you'd use Augeas, 'download'+'upload' or 'edit'.
|
||||
|
||||
RWMJ: I had a go at implementing this, but it's quite error-prone to
|
||||
do this sort of editing inside the C-based daemon code. It's far
|
||||
better to do it with Augeas, or else to use an external language like
|
||||
Perl.
|
||||
|
||||
Quick Perl scripts
|
||||
------------------
|
||||
|
||||
Currently we can't do Perl "one-liners". ie. The current syntax for
|
||||
any short Perl one-liner would be:
|
||||
|
||||
perl -MSys::Guestfs -e '$g = Sys::Guestfs->new(); $g->add_drive ("foo"); $g->launch; $g->mount ("/dev/sda1", "/"); ....'
|
||||
|
||||
You can see we're well beyond a single line just getting to the point
|
||||
of adding drives and mounting.
|
||||
|
||||
First suggestion:
|
||||
|
||||
$h = create ($filename, \"/dev/sda1\" => \"/\");
|
||||
|
||||
$h = create ([$file1, $file2], \"/dev/sda1\" => \"/\");
|
||||
|
||||
To mount read-only, add C<ro =E<gt> 1> like this:
|
||||
|
||||
$h = create ($filename, \"/dev/sda1\" => \"/\", ro => 1);
|
||||
|
||||
which is equivalent to the following sequence of calls:
|
||||
|
||||
$h = Sys::Guestfs->new ();
|
||||
$h->add_drive_ro ($filename);
|
||||
$h->launch ();
|
||||
$h->mount_ro (\"/dev/sda1\", \"/\");
|
||||
|
||||
Command-line form would be:
|
||||
|
||||
perl -MSys::Guestfs=:all -e '$_=create("guest.img", "/dev/sda1" => "/"); $_->cat ("/etc/fstab");'
|
||||
|
||||
That's not brief enough for one-liners, so we could have an extra
|
||||
autogenerated module which creates a Sys::Guestfs handle singleton
|
||||
(the handle is an implicit global variable as in guestfish), eg:
|
||||
|
||||
perl -MSys::Guestfs::One -e 'inspect("guest.img"); cat ("/etc/fstab");'
|
||||
|
||||
How would editing files work?
|
||||
|
||||
virt-rescue pty
|
||||
---------------
|
||||
|
||||
@@ -208,14 +96,6 @@ Windows-based daemon/appliance
|
||||
See discussion on list:
|
||||
https://www.redhat.com/archives/libguestfs/2009-November/msg00165.html
|
||||
|
||||
qemu locking
|
||||
------------
|
||||
|
||||
Add -drive file=...,lock=exclusive and -drive file=...,lock=shared
|
||||
|
||||
Change libguestfs and libvirt to do the right thing, so that multiple
|
||||
instances of qemu cannot stomp on each other.
|
||||
|
||||
virt-disk-explore
|
||||
-----------------
|
||||
|
||||
@@ -256,12 +136,6 @@ http://sourceforge.net/projects/aide/
|
||||
http://osiris.shmoo.com/
|
||||
http://sourceforge.net/projects/tripwire/
|
||||
|
||||
Fix 'file'
|
||||
----------
|
||||
|
||||
https://www.redhat.com/archives/libguestfs/2010-June/msg00053.html
|
||||
https://www.redhat.com/archives/libguestfs/2010-June/msg00079.html
|
||||
|
||||
Freeze/thaw filesystems
|
||||
-----------------------
|
||||
|
||||
@@ -293,13 +167,6 @@ Could we make guestfish interactive if commands are used without params?
|
||||
Image name? disk.img
|
||||
Size of image? 10M
|
||||
|
||||
Common problems
|
||||
---------------
|
||||
|
||||
How can we solve these common user problems?
|
||||
|
||||
[space for common problems here]
|
||||
|
||||
Better support for encrypted devices
|
||||
------------------------------------
|
||||
|
||||
@@ -318,8 +185,6 @@ Display the structure of an image file as a PS.
|
||||
Greater use of blkid / libblkid
|
||||
-------------------------------
|
||||
|
||||
guestfs_zero should use wipefs. See wipefs(8).
|
||||
|
||||
There are various useful functions in libblkid for listing partitions,
|
||||
devices etc which we are essentially duplicating in the daemon. It
|
||||
would make more sense to just use libblkid for this.
|
||||
@@ -371,23 +236,13 @@ $EDITOR without any corresponding ability to set them.
|
||||
echo $EDITOR # or %{EDITOR}
|
||||
edit /etc/resolv.conf
|
||||
|
||||
live CD inspection for Windows 7
|
||||
--------------------------------
|
||||
|
||||
Windows 7 install CDs are quite different and pretty impenetrable.
|
||||
There are no obvious files to parse.
|
||||
|
||||
More ntfs tools
|
||||
---------------
|
||||
|
||||
ntfsprogs actually has a lot more useful tools than we currently
|
||||
use. Interesting ones are:
|
||||
|
||||
ntfslabel: display or change filesystem label (we should unify all
|
||||
set*label APIs into a single set_vfs_label which can deal with any
|
||||
filesystem)
|
||||
|
||||
ntfsclone: clone, image, restore, rescue NTFS
|
||||
ntfscluster: display file(s) that occupy a cluster or sector
|
||||
|
||||
ntfsinfo: print various information about NTFS volume and files
|
||||
|
||||
@@ -510,23 +365,6 @@ would be some sort of modified attach method (see link above).
|
||||
The complexity here is that we would no longer have access to
|
||||
stdin/stdout (or we'd have to direct that somewhere else).
|
||||
|
||||
GObject Introspection
|
||||
---------------------
|
||||
|
||||
We periodically get asked to implement gobject-introspection (it's a
|
||||
GNOME thing):
|
||||
|
||||
http://live.gnome.org/GObjectIntrospection
|
||||
|
||||
This would require a separate Gtk C API since the main guestfs handle
|
||||
would have to be encapsulated in a GObject. However the main
|
||||
difficulty is that the annotations supported to define types are not
|
||||
very rich. Notably missing are support for optional arguments
|
||||
(defined but not implemented), support for structs (unless mapped to
|
||||
other objects).
|
||||
|
||||
Also note that the libguestfs API is not "object oriented".
|
||||
|
||||
libosinfo mappings for virt-inspector
|
||||
-------------------------------------
|
||||
|
||||
@@ -535,21 +373,16 @@ 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
|
||||
@@ -560,17 +393,21 @@ virt-sysprep ideas
|
||||
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)
|
||||
|
||||
As well as 'virt-sysprep' there is a case for a 'virt-customize' tool
|
||||
which can customize templated guests. This would be useful within
|
||||
companies/organizations that want to offer multiple guests, but all
|
||||
customized with the organization logo etc. Some ideas:
|
||||
|
||||
- change the background image to some custom desktop
|
||||
- change the sign-on messages (/etc/issue.net etc)
|
||||
- firstboot script (as suggested by librarian above)
|
||||
- Windows login script/service
|
||||
|
||||
Launch remote sessions over ssh
|
||||
-------------------------------
|
||||
|
||||
@@ -601,3 +438,39 @@ 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.
|
||||
|
||||
Ongoing code cleanups
|
||||
---------------------
|
||||
|
||||
Examine every use of 'int' in C code for signed overflow problems.
|
||||
|
||||
All file descriptors in the library and daemon should normally be
|
||||
opened with O_CLOEXEC. Therefore we need to examine every call to:
|
||||
|
||||
- open, openat
|
||||
- creat
|
||||
- pipe (see also: pipe2)
|
||||
- dup, dup2 (see also: dup3)
|
||||
- socket, socketpair
|
||||
- accept (see also: accept4)
|
||||
- signalfd, timerfd, epoll_create
|
||||
|
||||
virt-sparsify enhancements
|
||||
--------------------------
|
||||
|
||||
TMPDIR should be checked to ensure that we won't run out of space
|
||||
during the conversion, since current behaviour is very bad when this
|
||||
happens (it usually causes virt-sparsify to hang). This requires
|
||||
writing a small C binding to statvfs for OCaml.
|
||||
|
||||
'virt-sparsify --whitelist' option to generate skeletons (for
|
||||
debugging, bug forensics, diagnosis). The whilelist option would
|
||||
specify a list of files to be *preserved*. All other files in the
|
||||
image would be replaced by equivalent files of zeroes, thus minimizing
|
||||
the size of the debug image that needs to be shipped to us by the
|
||||
customer.
|
||||
|
||||
Optimize the appliance
|
||||
----------------------
|
||||
|
||||
Pass -cpu host. Anything else?
|
||||
|
||||
@@ -34,7 +34,9 @@ SHARED_SOURCE_FILES = \
|
||||
|
||||
virt_alignment_scan_SOURCES = \
|
||||
$(SHARED_SOURCE_FILES) \
|
||||
scan.c
|
||||
domains.c \
|
||||
scan.c \
|
||||
scan.h
|
||||
|
||||
virt_alignment_scan_CFLAGS = \
|
||||
-DGUESTFS_WARN_DEPRECATED=1 \
|
||||
@@ -72,8 +74,6 @@ stamp-virt-alignment-scan.pod: virt-alignment-scan.pod
|
||||
|
||||
# TESTS_ENVIRONMENT = \
|
||||
# MALLOC_PERTURB_=$(random_val) \
|
||||
# LD_LIBRARY_PATH=$(top_builddir)/src/.libs \
|
||||
# LIBGUESTFS_PATH=$(top_builddir)/appliance \
|
||||
# TMPDIR=$(top_builddir)
|
||||
# $(top_builddir)/run
|
||||
|
||||
# TESTS = test-virt-alignment-scan.sh
|
||||
|
||||
360
align/domains.c
Normal file
360
align/domains.c
Normal file
@@ -0,0 +1,360 @@
|
||||
/* virt-alignment-scan
|
||||
* Copyright (C) 2012 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 <libintl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef HAVE_LIBVIRT
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#endif
|
||||
|
||||
#include "progname.h"
|
||||
|
||||
#if defined(HAVE_LIBVIRT) && defined(HAVE_LIBXML2)
|
||||
#define GUESTFS_PRIVATE_FOR_EACH_DISK 1
|
||||
#endif
|
||||
|
||||
#include "guestfs.h"
|
||||
#include "options.h"
|
||||
#include "scan.h"
|
||||
|
||||
#if defined(HAVE_LIBVIRT) && defined(HAVE_LIBXML2)
|
||||
|
||||
/* The list of domains and disks that we build up in
|
||||
* get_domains_from_libvirt.
|
||||
*/
|
||||
struct disk {
|
||||
struct disk *next;
|
||||
char *filename;
|
||||
char *format; /* could be NULL */
|
||||
};
|
||||
|
||||
struct domain {
|
||||
char *name;
|
||||
char *uuid;
|
||||
struct disk *disks;
|
||||
size_t nr_disks;
|
||||
};
|
||||
|
||||
struct domain *domains = NULL;
|
||||
size_t nr_domains;
|
||||
|
||||
static int
|
||||
compare_domain_names (const void *p1, const void *p2)
|
||||
{
|
||||
const struct domain *d1 = p1;
|
||||
const struct domain *d2 = p2;
|
||||
|
||||
return strcmp (d1->name, d2->name);
|
||||
}
|
||||
|
||||
static void
|
||||
free_domain (struct domain *domain)
|
||||
{
|
||||
struct disk *disk, *next;
|
||||
|
||||
for (disk = domain->disks; disk; disk = next) {
|
||||
next = disk->next;
|
||||
free (disk->filename);
|
||||
free (disk->format);
|
||||
free (disk);
|
||||
}
|
||||
|
||||
free (domain->name);
|
||||
free (domain->uuid);
|
||||
}
|
||||
|
||||
static void add_domains_by_id (virConnectPtr conn, int *ids, size_t n);
|
||||
static void add_domains_by_name (virConnectPtr conn, char **names, size_t n);
|
||||
static void add_domain (virDomainPtr dom);
|
||||
static int add_disk (guestfs_h *g, const char *filename, const char *format, int readonly, void *domain_vp);
|
||||
static size_t add_disks_to_handle_reverse (struct disk *disk, size_t *errors_r);
|
||||
static void reset_guestfs_handle (void);
|
||||
|
||||
void
|
||||
get_domains_from_libvirt (int uuid, size_t *worst_alignment_ptr)
|
||||
{
|
||||
virErrorPtr err;
|
||||
virConnectPtr conn;
|
||||
int n;
|
||||
size_t i, count, errors;
|
||||
const char *prefix;
|
||||
|
||||
nr_domains = 0;
|
||||
domains = NULL;
|
||||
|
||||
/* Get the list of all domains. */
|
||||
conn = virConnectOpenReadOnly (libvirt_uri);
|
||||
if (!conn) {
|
||||
err = virGetLastError ();
|
||||
fprintf (stderr,
|
||||
_("%s: could not connect to libvirt (code %d, domain %d): %s\n"),
|
||||
program_name, err->code, err->domain, err->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
n = virConnectNumOfDomains (conn);
|
||||
if (n == -1) {
|
||||
err = virGetLastError ();
|
||||
fprintf (stderr,
|
||||
_("%s: could not get number of running domains (code %d, domain %d): %s\n"),
|
||||
program_name, err->code, err->domain, err->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int ids[n];
|
||||
n = virConnectListDomains (conn, ids, n);
|
||||
if (n == -1) {
|
||||
err = virGetLastError ();
|
||||
fprintf (stderr,
|
||||
_("%s: could not list running domains (code %d, domain %d): %s\n"),
|
||||
program_name, err->code, err->domain, err->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
add_domains_by_id (conn, ids, n);
|
||||
|
||||
n = virConnectNumOfDefinedDomains (conn);
|
||||
if (n == -1) {
|
||||
err = virGetLastError ();
|
||||
fprintf (stderr,
|
||||
_("%s: could not get number of inactive domains (code %d, domain %d): %s\n"),
|
||||
program_name, err->code, err->domain, err->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char *names[n];
|
||||
n = virConnectListDefinedDomains (conn, names, n);
|
||||
if (n == -1) {
|
||||
err = virGetLastError ();
|
||||
fprintf (stderr,
|
||||
_("%s: could not list inactive domains (code %d, domain %d): %s\n"),
|
||||
program_name, err->code, err->domain, err->message);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
add_domains_by_name (conn, names, n);
|
||||
|
||||
/* You must free these even though the libvirt documentation doesn't
|
||||
* mention it.
|
||||
*/
|
||||
for (i = 0; i < (size_t) n; ++i)
|
||||
free (names[i]);
|
||||
|
||||
virConnectClose (conn);
|
||||
|
||||
/* No domains? */
|
||||
if (nr_domains == 0)
|
||||
return;
|
||||
|
||||
/* Sort the domains alphabetically by name for display. */
|
||||
qsort (domains, nr_domains, sizeof (struct domain), compare_domain_names);
|
||||
|
||||
errors = 0;
|
||||
for (i = 0; i < nr_domains; ++i) {
|
||||
if (domains[i].disks == NULL)
|
||||
continue;
|
||||
|
||||
count = add_disks_to_handle_reverse (domains[i].disks, &errors);
|
||||
if (count == 0)
|
||||
continue;
|
||||
|
||||
if (guestfs_launch (g) == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
prefix = !uuid ? domains[i].name : domains[i].uuid;
|
||||
|
||||
/* Perform the scan. */
|
||||
scan (worst_alignment_ptr, prefix);
|
||||
|
||||
if (i < nr_domains - 1)
|
||||
reset_guestfs_handle ();
|
||||
}
|
||||
|
||||
/* Free up domains structure. */
|
||||
for (i = 0; i < nr_domains; ++i)
|
||||
free_domain (&domains[i]);
|
||||
free (domains);
|
||||
|
||||
if (errors > 0) {
|
||||
fprintf (stderr, _("%s: failed to analyze a disk, see error(s) above\n"),
|
||||
program_name);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_domains_by_id (virConnectPtr conn, int *ids, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
virDomainPtr dom;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (ids[i] != 0) { /* RHBZ#538041 */
|
||||
dom = virDomainLookupByID (conn, ids[i]);
|
||||
if (dom) { /* transient errors are possible here, ignore them */
|
||||
add_domain (dom);
|
||||
virDomainFree (dom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_domains_by_name (virConnectPtr conn, char **names, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
virDomainPtr dom;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
dom = virDomainLookupByName (conn, names[i]);
|
||||
if (dom) { /* transient errors are possible here, ignore them */
|
||||
add_domain (dom);
|
||||
virDomainFree (dom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_domain (virDomainPtr dom)
|
||||
{
|
||||
struct domain *domain;
|
||||
|
||||
domains = realloc (domains, (nr_domains + 1) * sizeof (struct domain));
|
||||
if (domains == NULL) {
|
||||
perror ("realloc");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
domain = &domains[nr_domains];
|
||||
nr_domains++;
|
||||
|
||||
domain->name = strdup (virDomainGetName (dom));
|
||||
if (domain->name == NULL) {
|
||||
perror ("strdup");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char uuid[VIR_UUID_STRING_BUFLEN];
|
||||
if (virDomainGetUUIDString (dom, uuid) == 0) {
|
||||
domain->uuid = strdup (uuid);
|
||||
if (domain->uuid == NULL) {
|
||||
perror ("strdup");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
domain->uuid = NULL;
|
||||
|
||||
domain->disks = NULL;
|
||||
int n = guestfs___for_each_disk (g, dom, add_disk, domain);
|
||||
if (n == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
domain->nr_disks = n;
|
||||
}
|
||||
|
||||
static int
|
||||
add_disk (guestfs_h *g,
|
||||
const char *filename, const char *format, int readonly,
|
||||
void *domain_vp)
|
||||
{
|
||||
struct domain *domain = domain_vp;
|
||||
struct disk *disk;
|
||||
|
||||
disk = malloc (sizeof *disk);
|
||||
if (disk == NULL) {
|
||||
perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
disk->next = domain->disks;
|
||||
domain->disks = disk;
|
||||
|
||||
disk->filename = strdup (filename);
|
||||
if (disk->filename == NULL) {
|
||||
perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
if (format) {
|
||||
disk->format = strdup (format);
|
||||
if (disk->format == NULL) {
|
||||
perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
disk->format = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t
|
||||
add_disks_to_handle_reverse (struct disk *disk, size_t *errors_r)
|
||||
{
|
||||
size_t nr_disks_added;
|
||||
|
||||
if (disk == NULL)
|
||||
return 0;
|
||||
|
||||
nr_disks_added = add_disks_to_handle_reverse (disk->next, errors_r);
|
||||
|
||||
struct guestfs_add_drive_opts_argv optargs = { .bitmask = 0 };
|
||||
|
||||
optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_READONLY_BITMASK;
|
||||
optargs.readonly = 1;
|
||||
|
||||
if (disk->format) {
|
||||
optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK;
|
||||
optargs.format = disk->format;
|
||||
}
|
||||
|
||||
if (guestfs_add_drive_opts_argv (g, disk->filename, &optargs) == -1) {
|
||||
(*errors_r)++;
|
||||
return nr_disks_added;
|
||||
}
|
||||
|
||||
return nr_disks_added+1;
|
||||
}
|
||||
|
||||
/* Close and reopen the libguestfs handle. */
|
||||
static void
|
||||
reset_guestfs_handle (void)
|
||||
{
|
||||
/* Copy the settings from the old handle. */
|
||||
int verbose = guestfs_get_verbose (g);
|
||||
int trace = guestfs_get_trace (g);
|
||||
|
||||
guestfs_close (g);
|
||||
|
||||
g = guestfs_create ();
|
||||
if (g == NULL) {
|
||||
fprintf (stderr, _("guestfs_create: failed to create handle\n"));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
guestfs_set_verbose (g, verbose);
|
||||
guestfs_set_trace (g, trace);
|
||||
}
|
||||
|
||||
#endif
|
||||
73
align/scan.c
73
align/scan.c
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "guestfs.h"
|
||||
#include "options.h"
|
||||
#include "scan.h"
|
||||
|
||||
/* These globals are shared with options.c. */
|
||||
guestfs_h *g;
|
||||
@@ -53,8 +54,6 @@ int inspector = 0;
|
||||
|
||||
static int quiet = 0; /* --quiet */
|
||||
|
||||
static int scan (void);
|
||||
|
||||
static inline char *
|
||||
bad_cast (char const *s)
|
||||
{
|
||||
@@ -111,6 +110,7 @@ main (int argc, char *argv[])
|
||||
{ "format", 2, 0, 0 },
|
||||
{ "help", 0, 0, HELP_OPTION },
|
||||
{ "quiet", 0, 0, 'q' },
|
||||
{ "uuid", 0, 0, 0, },
|
||||
{ "verbose", 0, 0, 'v' },
|
||||
{ "version", 0, 0, 'V' },
|
||||
{ 0, 0, 0, 0 }
|
||||
@@ -120,6 +120,9 @@ main (int argc, char *argv[])
|
||||
const char *format = NULL;
|
||||
int c;
|
||||
int option_index;
|
||||
int uuid = 0;
|
||||
/* This just needs to be larger than any alignment we care about. */
|
||||
size_t worst_alignment = UINT_MAX;
|
||||
int exit_code;
|
||||
|
||||
g = guestfs_create ();
|
||||
@@ -141,6 +144,8 @@ main (int argc, char *argv[])
|
||||
format = NULL;
|
||||
else
|
||||
format = optarg;
|
||||
} else if (STREQ (long_options[option_index].name, "uuid")) {
|
||||
uuid = 1;
|
||||
} else {
|
||||
fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
|
||||
program_name, long_options[option_index].name, option_index);
|
||||
@@ -197,30 +202,50 @@ main (int argc, char *argv[])
|
||||
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)
|
||||
if (drvs == NULL) {
|
||||
#if defined(HAVE_LIBVIRT) && defined(HAVE_LIBXML2)
|
||||
get_domains_from_libvirt (uuid, &worst_alignment);
|
||||
#else
|
||||
fprintf (stderr, _("%s: compiled without support for libvirt and/or libxml2.\n"),
|
||||
program_name);
|
||||
exit (EXIT_FAILURE);
|
||||
#endif
|
||||
} else {
|
||||
if (uuid) {
|
||||
fprintf (stderr, _("%s: --uuid option cannot be used with -a or -d\n"),
|
||||
program_name);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Free up data structures, no longer needed after this point. */
|
||||
free_drives (drvs);
|
||||
/* Add domains/drives from the command line (for a single guest). */
|
||||
add_drives (drvs, 'a');
|
||||
|
||||
/* Perform the scan. */
|
||||
exit_code = scan ();
|
||||
if (guestfs_launch (g) == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
guestfs_close (g);
|
||||
/* Free up data structures, no longer needed after this point. */
|
||||
free_drives (drvs);
|
||||
|
||||
/* Perform the scan. */
|
||||
scan (&worst_alignment, NULL);
|
||||
|
||||
guestfs_close (g);
|
||||
}
|
||||
|
||||
/* Decide on an appropriate exit code. */
|
||||
if (worst_alignment < 10) /* 2^10 = 4096 */
|
||||
exit_code = 3;
|
||||
else if (worst_alignment < 16) /* 2^16 = 65536 */
|
||||
exit_code = 2;
|
||||
else
|
||||
exit_code = 0;
|
||||
|
||||
exit (exit_code);
|
||||
}
|
||||
|
||||
static int
|
||||
scan (void)
|
||||
void
|
||||
scan (size_t *worst_alignment, const char *prefix)
|
||||
{
|
||||
int exit_code = 0;
|
||||
char **devices;
|
||||
size_t i, j;
|
||||
size_t alignment;
|
||||
@@ -247,9 +272,13 @@ scan (void)
|
||||
/* Start offset of the partition in bytes. */
|
||||
start = parts->val[j].part_start;
|
||||
|
||||
if (!quiet)
|
||||
if (!quiet) {
|
||||
if (prefix)
|
||||
printf ("%s:", prefix);
|
||||
|
||||
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. */
|
||||
@@ -267,13 +296,13 @@ scan (void)
|
||||
printf ("- ");
|
||||
}
|
||||
|
||||
if (alignment < *worst_alignment)
|
||||
*worst_alignment = alignment;
|
||||
|
||||
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 {
|
||||
@@ -286,6 +315,4 @@ scan (void)
|
||||
free (devices[i]);
|
||||
}
|
||||
free (devices);
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
30
align/scan.h
Normal file
30
align/scan.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* virt-alignment-scan
|
||||
* Copyright (C) 2012 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.
|
||||
*/
|
||||
|
||||
#ifndef GUESTFS_VIRT_ALIGNMENT_SCAN_H_
|
||||
#define GUESTFS_VIRT_ALIGNMENT_SCAN_H_
|
||||
|
||||
/* domains.c */
|
||||
#if defined(HAVE_LIBVIRT) && defined(HAVE_LIBXML2)
|
||||
extern void get_domains_from_libvirt (int uuid, size_t *worst_alignment);
|
||||
#endif
|
||||
|
||||
/* scan.c */
|
||||
extern void scan (size_t *worst_alignment, const char *prefix);
|
||||
|
||||
#endif /* GUESTFS_VIRT_ALIGNMENT_SCAN_H_ */
|
||||
@@ -10,6 +10,8 @@ virt-alignment-scan - Check alignment of virtual machine partitions
|
||||
|
||||
virt-alignment-scan [--options] -a disk.img [-a disk.img ...]
|
||||
|
||||
virt-alignment-scan [--options]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
When older operating systems install themselves, the partitioning
|
||||
@@ -51,16 +53,28 @@ possibly the I<-c> option:
|
||||
/dev/sda2 105906176 1024K ok
|
||||
/dev/sdb1 65536 64K ok
|
||||
|
||||
Run virt-alignment-scan without any I<-a> or I<-d> options to scan all
|
||||
libvirt domains.
|
||||
|
||||
# virt-alignment-scan
|
||||
F16x64:/dev/sda1 1048576 1024K ok
|
||||
F16x64:/dev/sda2 2097152 2048K ok
|
||||
F16x64:/dev/sda3 526385152 2048K 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
|
||||
the first 4 columns are significant 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)
|
||||
The device and partition name (eg. C</dev/sda1> meaning the
|
||||
first partition on the first block device).
|
||||
|
||||
When listing all libvirt domains (no I<-a> or I<-d> option given) this
|
||||
column is prefixed by the libvirt name or UUID (if I<--uuid> is
|
||||
given). eg: C<WinXP:/dev/sda1>
|
||||
|
||||
=item col 2
|
||||
|
||||
@@ -151,6 +165,15 @@ security problem with malicious guests (CVE-2010-3851).
|
||||
Don't produce any output. Just set the exit code
|
||||
(see L</EXIT STATUS> below).
|
||||
|
||||
=item B<--uuid>
|
||||
|
||||
Print UUIDs instead of names. This is useful for following a guest
|
||||
even when the guest is migrated or renamed, or when two guests happen
|
||||
to have the same name.
|
||||
|
||||
This option only applies when listing all libvirt domains (when no
|
||||
I<-a> or I<-d> options are specified).
|
||||
|
||||
=item B<-v>
|
||||
|
||||
=item B<--verbose>
|
||||
|
||||
@@ -18,10 +18,13 @@
|
||||
include $(top_srcdir)/subdir-rules.mk
|
||||
|
||||
EXTRA_DIST = \
|
||||
packagelist.in \
|
||||
excludelist.in \
|
||||
guestfsd.suppressions \
|
||||
init \
|
||||
make.sh.in
|
||||
libguestfs-make-fixed-appliance.in \
|
||||
libguestfs-make-fixed-appliance.pod \
|
||||
make.sh.in \
|
||||
packagelist.in
|
||||
|
||||
fsdir = $(libdir)/guestfs
|
||||
superminfsdir = $(libdir)/guestfs/supermin.d
|
||||
@@ -42,13 +45,18 @@ make.sh: make.sh.in
|
||||
chmod +x $@-t
|
||||
mv $@-t $@
|
||||
|
||||
PACKAGELIST_CPP_FLAGS = -D$(DISTRO)=1
|
||||
if VALGRIND_DAEMON
|
||||
PACKAGELIST_CPP_FLAGS += -DVALGRIND_DAEMON=1
|
||||
endif
|
||||
|
||||
packagelist: packagelist.in
|
||||
cpp -undef -D$(DISTRO)=1 < $< | \
|
||||
cpp -undef $(PACKAGELIST_CPP_FLAGS) < $< | \
|
||||
grep -v '^[[:space:]]*$$' | grep -v '^#' > $@-t
|
||||
mv $@-t $@
|
||||
|
||||
excludelist: excludelist.in
|
||||
cpp -undef -D$(DISTRO)=1 < $< | \
|
||||
cpp -undef $(PACKAGELIST_CPP_FLAGS) < $< | \
|
||||
grep -v '^[[:space:]]*$$' | grep -v '^#' > $@-t
|
||||
mv $@-t $@
|
||||
|
||||
@@ -59,13 +67,15 @@ stamp-supermin: make.sh packagelist excludelist
|
||||
./make.sh
|
||||
touch $@
|
||||
|
||||
supermin.d/daemon.img: ../daemon/guestfsd
|
||||
supermin.d/daemon.img: ../daemon/guestfsd guestfsd.suppressions
|
||||
mkdir -p supermin.d
|
||||
rm -f $@ $@-t
|
||||
mkdir sbin
|
||||
cd sbin && ln ../../daemon/guestfsd
|
||||
echo -e "sbin\nsbin/guestfsd" | cpio --quiet -o -H newc > $@-t
|
||||
rm -r sbin
|
||||
rm -rf tmp
|
||||
mkdir -p tmp$(DAEMON_SUPERMIN_DIR) tmp/etc
|
||||
ln ../daemon/guestfsd tmp$(DAEMON_SUPERMIN_DIR)/guestfsd
|
||||
ln $(srcdir)/guestfsd.suppressions tmp/etc/guestfsd.suppressions
|
||||
( cd tmp && find | cpio --quiet -o -H newc ) > $@-t
|
||||
rm -rf tmp
|
||||
mv $@-t $@
|
||||
|
||||
supermin.d/init.img: init
|
||||
@@ -75,9 +85,26 @@ supermin.d/init.img: init
|
||||
echo "init" | cpio --quiet -o -H newc > $@-t
|
||||
mv $@-t $@
|
||||
|
||||
# libguestfs-make-fixed-appliance script and man page.
|
||||
|
||||
sbin_SCRIPTS = libguestfs-make-fixed-appliance
|
||||
|
||||
man_MANS = libguestfs-make-fixed-appliance.1
|
||||
|
||||
libguestfs-make-fixed-appliance.1 $(top_builddir)/html/libguestfs-make-fixed-appliance.1.html: stamp-libguestfs-make-fixed-appliance.pod
|
||||
|
||||
stamp-libguestfs-make-fixed-appliance.pod: libguestfs-make-fixed-appliance.pod
|
||||
$(top_builddir)/podwrapper.sh \
|
||||
--man libguestfs-make-fixed-appliance.1 \
|
||||
--html $(top_builddir)/html/libguestfs-make-fixed-appliance.1.html \
|
||||
$<
|
||||
touch $@
|
||||
|
||||
# Make clean.
|
||||
|
||||
CLEANFILES = packagelist excludelist
|
||||
CLEANFILES = packagelist excludelist \
|
||||
libguestfs-make-fixed-appliance.1 \
|
||||
stamp-libguestfs-make-fixed-appliance.pod
|
||||
|
||||
clean-local:
|
||||
rm -rf supermin.d
|
||||
|
||||
19
appliance/guestfsd.suppressions
Normal file
19
appliance/guestfsd.suppressions
Normal file
@@ -0,0 +1,19 @@
|
||||
# This file is only used when libguestfs is configured with
|
||||
#
|
||||
# ./configure --enable-valgrind-daemon
|
||||
#
|
||||
# (only used for development, and only used in the regular supermin
|
||||
# appliance, not libguestfs live).
|
||||
#
|
||||
# If there are any valgrind errors in the base libraries such as
|
||||
# glibc, then we can suppress them here, so we only see errors in
|
||||
# libguestfs daemon code.
|
||||
|
||||
# libdl
|
||||
{
|
||||
libdl_index_cond
|
||||
Memcheck:Cond
|
||||
fun:index
|
||||
fun:expand_dynamic_string_token
|
||||
fun:_dl_map_object
|
||||
}
|
||||
@@ -12,12 +12,17 @@ export RUNLEVEL PREVLEVEL
|
||||
|
||||
mkdir -p /sysroot
|
||||
|
||||
rm -f /proc; mkdir /proc
|
||||
if [ ! -d /proc ]; then rm -f /proc; fi
|
||||
mkdir -p /proc
|
||||
mount -t proc /proc /proc
|
||||
rm -f /sys; mkdir /sys
|
||||
if [ ! -d /sys ]; then rm -f /sys; fi
|
||||
mkdir -p /sys
|
||||
mount -t sysfs /sys /sys
|
||||
mkdir -p /run/lock
|
||||
|
||||
# devtmpfs is required since udev 176
|
||||
mount -t devtmpfs /dev /dev
|
||||
|
||||
if [ ! -L /etc/init.d/udev -a -x /etc/init.d/udev ]; then
|
||||
if type service >/dev/null 2>&1; then
|
||||
service udev start
|
||||
@@ -29,13 +34,13 @@ elif [ -x /sbin/start_udev ] && /sbin/start_udev; then
|
||||
elif [ -x /sbin/udevd ]; then
|
||||
echo -e '\000\000\000\000' > /proc/sys/kernel/hotplug
|
||||
/sbin/udevd --daemon
|
||||
/sbin/udevadm trigger
|
||||
/sbin/udevadm settle
|
||||
udevadm trigger
|
||||
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
|
||||
udevadm trigger
|
||||
udevadm settle
|
||||
else
|
||||
echo No udev, creating /dev manually
|
||||
mount -t tmpfs none /dev
|
||||
@@ -66,9 +71,13 @@ fi
|
||||
hwclock -u -s
|
||||
|
||||
# Set up the network.
|
||||
ifconfig lo 127.0.0.1
|
||||
ifconfig eth0 169.254.2.10
|
||||
route add default gw 169.254.2.2
|
||||
ip addr add 127.0.0.1/8 brd + dev lo scope host
|
||||
ip link set dev lo up
|
||||
|
||||
ip addr add 169.254.2.10/16 brd + dev eth0 scope global
|
||||
ip link set dev eth0 up
|
||||
|
||||
ip route add default via 169.254.2.2
|
||||
|
||||
# Scan for MDs.
|
||||
mdadm -As --auto=yes --run
|
||||
@@ -94,8 +103,8 @@ if grep -sq guestfs_verbose=1 /proc/cmdline; then
|
||||
lvm pvs
|
||||
lvm vgs
|
||||
lvm lvs
|
||||
ifconfig
|
||||
netstat -rn
|
||||
ip a
|
||||
ip r
|
||||
lsmod
|
||||
#hwclock -r
|
||||
date
|
||||
@@ -106,8 +115,19 @@ if grep -sq guestfs_verbose=1 /proc/cmdline; then
|
||||
fi
|
||||
|
||||
if ! grep -sq guestfs_rescue=1 /proc/cmdline; then
|
||||
# Run the daemon under valgrind if ./configure --enable-valgrind-daemon
|
||||
vg_channel=/dev/virtio-ports/org.libguestfs.valgrind
|
||||
if [ -w $vg_channel ]; then
|
||||
if [ -r /etc/guestfsd.suppressions ]; then
|
||||
suppressions="--suppressions=/etc/guestfsd.suppressions"
|
||||
fi
|
||||
exec 3>$vg_channel
|
||||
vg="valgrind --leak-check=full --log-fd=3 --error-exitcode=119 --max-stackframe=8388608 --child-silent-after-fork=yes $suppressions"
|
||||
echo "enabling valgrind: $vg"
|
||||
fi
|
||||
|
||||
# The host will kill qemu abruptly if guestfsd shuts down normally
|
||||
guestfsd
|
||||
$vg guestfsd
|
||||
|
||||
# Otherwise we try to clean up gracefully. For example, this ensures that a
|
||||
# core dump generated by the guest daemon will be written to disk.
|
||||
@@ -132,4 +152,4 @@ else
|
||||
fi
|
||||
|
||||
sync
|
||||
/sbin/reboot -f
|
||||
reboot -f
|
||||
|
||||
163
appliance/libguestfs-make-fixed-appliance.in
Normal file
163
appliance/libguestfs-make-fixed-appliance.in
Normal file
@@ -0,0 +1,163 @@
|
||||
#!/bin/bash -
|
||||
# @configure_input@
|
||||
# libguestfs-make-fixed-appliance tool
|
||||
# Copyright (C) 2012 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="libguestfs-make-fixed-appliance"
|
||||
version="@PACKAGE_VERSION@"
|
||||
|
||||
TEMP=`getopt \
|
||||
-o V \
|
||||
--long help,version,xz \
|
||||
-n $program -- "$@"`
|
||||
if [ $? != 0 ]; then
|
||||
echo "$program: problem parsing the command line arguments"
|
||||
exit 1
|
||||
fi
|
||||
eval set -- "$TEMP"
|
||||
|
||||
usage ()
|
||||
{
|
||||
echo "Usage:"
|
||||
echo " $program [--options] OUTPUTDIR"
|
||||
echo " $program [--options] --xz"
|
||||
echo
|
||||
echo "Read $program(1) man page for more information."
|
||||
exit $1
|
||||
}
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
-V|--version)
|
||||
echo "$program $version"
|
||||
exit 0;;
|
||||
--xz)
|
||||
xz_mode=1
|
||||
shift;;
|
||||
--help)
|
||||
usage 0;;
|
||||
--)
|
||||
shift
|
||||
break;;
|
||||
*)
|
||||
echo "internal error ($1)"
|
||||
exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Either xz_mode or we expect one extra parameter (output directory).
|
||||
if [ -n "$xz_mode" ]; then
|
||||
if [ $# -gt 0 ]; then
|
||||
echo "error: $program: extra parameters on the command line"
|
||||
echo
|
||||
usage 1
|
||||
fi
|
||||
else
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "error: $program: missing output directory"
|
||||
echo
|
||||
usage 1
|
||||
fi
|
||||
outputdir="$1"
|
||||
fi
|
||||
|
||||
# end of command line parsing
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
set -e
|
||||
|
||||
# The two ways to build the appliance are roughly the same, except for
|
||||
# --xz we build into a temporary directory and tar it up at the end.
|
||||
|
||||
if [ -n "$xz_mode" ]; then
|
||||
tmpdir="$(mktemp -d)"
|
||||
outputdir="$tmpdir/appliance"
|
||||
|
||||
cleanup ()
|
||||
{
|
||||
rm -rf $tmpdir ||:
|
||||
}
|
||||
trap cleanup EXIT ERR
|
||||
fi
|
||||
|
||||
# Create the output directory.
|
||||
mkdir -p "$outputdir"
|
||||
|
||||
# Build the supermin appliance, if not already.
|
||||
guestfish -a /dev/null run
|
||||
|
||||
# Find the location of the appliance.
|
||||
if [ -n "$TMPDIR" ]; then
|
||||
appliancedir="$TMPDIR/.guestfs-$(id -u)"
|
||||
else
|
||||
appliancedir="/var/tmp/.guestfs-$(id -u)"
|
||||
fi
|
||||
|
||||
cp "$appliancedir/kernel" "$outputdir/kernel"
|
||||
cp "$appliancedir/initrd" "$outputdir/initrd"
|
||||
cp --sparse=always "$appliancedir/root" "$outputdir/root"
|
||||
|
||||
cat <<EOF >"$outputdir/README.fixed"
|
||||
This is the "fixed appliance", a pre-built binary appliance for
|
||||
libguestfs. This was built using $program.
|
||||
|
||||
Unpack the appliance directory:
|
||||
|
||||
tar -Jxvf appliance-<VERSION>.tar.xz
|
||||
|
||||
Then copy all four files:
|
||||
|
||||
* kernel
|
||||
* initrd
|
||||
* root
|
||||
* README.fixed
|
||||
|
||||
into a directory somewhere, eg. /usr/local/lib/guestfs/appliance/
|
||||
|
||||
Then build libguestfs (>= 1.16.7 or >= 1.17.10) from source, disabling
|
||||
the normal appliance and daemon:
|
||||
|
||||
./configure --disable-appliance --disable-daemon
|
||||
make
|
||||
sudo make install
|
||||
|
||||
Set LIBGUESTFS_PATH to the path where you unpacked these files, eg:
|
||||
|
||||
export LIBGUESTFS_PATH=/usr/local/lib/guestfs/appliance/
|
||||
|
||||
and run the libguestfs programs and virt tools in the normal way.
|
||||
|
||||
|
||||
LICENSE
|
||||
-------
|
||||
|
||||
This appliance contains software under a variety of open source
|
||||
licenses. The software is from Fedora (https://fedoraproject.org/),
|
||||
and to rebuild it you need to download Fedora 17+ and
|
||||
libguestfs >= 1.17.10, and build libguestfs from source in the usual
|
||||
way.
|
||||
|
||||
EOF
|
||||
|
||||
# If --xz, compress the result. Note -S option to preserve sparseness.
|
||||
if [ -n "$xz_mode" ]; then
|
||||
tar -C "$tmpdir" -S -cf - appliance | xz --best > "appliance-$version.tar.xz"
|
||||
rm -rf "$tmpdir" ||:
|
||||
trap - EXIT ERR
|
||||
fi
|
||||
174
appliance/libguestfs-make-fixed-appliance.pod
Normal file
174
appliance/libguestfs-make-fixed-appliance.pod
Normal file
@@ -0,0 +1,174 @@
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
libguestfs-make-fixed-appliance - Make a "fixed appliance" for libguestfs
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
libguestfs-make-fixed-appliance [--options] OUTPUTDIR
|
||||
|
||||
libguestfs-make-fixed-appliance [--options] --xz
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
libguestfs-make-fixed-appliance lets you make a pre-built binary
|
||||
appliance for libguestfs.
|
||||
|
||||
B<Note that ordinary users should not need to run this tool>. The
|
||||
only reason to use it is if you want to make a self-contained
|
||||
libguestfs appliance that can be copied to another machine or platform
|
||||
that doesn't support L<febootstrap(8)>. To understand why you might
|
||||
need to use this tool, read the section L</FIXED APPLIANCE> below.
|
||||
|
||||
Instead of running this tool, you can download fixed appliances from
|
||||
L<http://libguestfs.org/download/binaries/appliance/>. These
|
||||
appliances were made using this tool.
|
||||
|
||||
There are two ways to use this tool.
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Specify an output directory, for example:
|
||||
|
||||
libguestfs-make-fixed-appliance /usr/local/lib/guestfs/appliance
|
||||
|
||||
The output directory is created if it does not exist. Four files are
|
||||
created in this directory:
|
||||
|
||||
<OUTPUTDIR>/kernel
|
||||
<OUTPUTDIR>/initrd
|
||||
<OUTPUTDIR>/root
|
||||
<OUTPUTDIR>/README.fixed
|
||||
|
||||
Note that C<I<OUTPUTDIR>/root> is a sparse file, so take care when
|
||||
copying it.
|
||||
|
||||
You can then run libguestfs (possibly after copying this directory to
|
||||
another machine) by setting the environment variable LIBGUESTFS_PATH
|
||||
to C<OUTPUTDIR>.
|
||||
|
||||
=item *
|
||||
|
||||
The alternative method is to use the I<--xz> option to create a
|
||||
compressed tarball:
|
||||
|
||||
libguestfs-make-fixed-appliance --xz
|
||||
|
||||
This creates a tarball in the I<current> directory called:
|
||||
|
||||
appliance-<VERSION>.tar.xz
|
||||
|
||||
(where C<VERSION> is the version of libguestfs). The tarball contains
|
||||
the four files:
|
||||
|
||||
appliance/kernel
|
||||
appliance/initrd
|
||||
appliance/root
|
||||
appliance/README.fixed
|
||||
|
||||
Note that C<appliance/root> is a sparse file, so take care when
|
||||
copying it.
|
||||
|
||||
=back
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<--help>
|
||||
|
||||
Display short usage information and exit.
|
||||
|
||||
=item B<-V>
|
||||
|
||||
=item B<--version>
|
||||
|
||||
Display the version number and exit.
|
||||
|
||||
=item B<--xz>
|
||||
|
||||
Instead of creating the appliance in an output directory, create a
|
||||
compressed tarball of the appliance in the current directory called
|
||||
C<appliance-I<VERSION>.tar.xz> where C<VERSION> is the version of
|
||||
libguestfs.
|
||||
|
||||
Using I<--xz> can take some time. If working normally, the tool is
|
||||
completely silent when it is running.
|
||||
|
||||
=back
|
||||
|
||||
=head1 FIXED APPLIANCE
|
||||
|
||||
When libguestfs (or libguestfs tools) are run, they search a path
|
||||
looking for an appliance. The path is built into libguestfs, or can
|
||||
be set using the C<LIBGUESTFS_PATH> environment variable.
|
||||
|
||||
Normally a supermin appliance is located on this path (see
|
||||
L<febootstrap(8)/SUPERMIN APPLIANCE>). libguestfs reconstructs this
|
||||
into a full appliance by running L<febootstrap-supermin-helper(8)>.
|
||||
|
||||
However, a simpler "fixed appliance" can also be used. libguestfs
|
||||
detects this by looking for a directory on the path containing four
|
||||
files called C<kernel>, C<initrd>, C<root> and C<README.fixed> (note
|
||||
the C<README.fixed> file must be present as well).
|
||||
|
||||
If the fixed appliance is found, libguestfs skips febootstrap entirely
|
||||
and just runs qemu with the kernel, initrd and root disk from the
|
||||
fixed appliance.
|
||||
|
||||
Thus the fixed appliance can be used when a platform or Linux distro
|
||||
does not support febootstrap. You build the fixed appliance on a
|
||||
platform that does support febootstrap, and copy it over, and use that
|
||||
to run libguestfs.
|
||||
|
||||
=head1 LICENSING
|
||||
|
||||
The fixed appliance is a complete Linux binary distro. If you
|
||||
distribute it, you may need to distribute corresponding source files
|
||||
to remain in legal compliance with the licenses of the software in the
|
||||
appliance (such as the GNU General Public License).
|
||||
|
||||
=head1 EXIT STATUS
|
||||
|
||||
libguestfs-make-fixed-appliance returns I<0> if the appliance was
|
||||
built without errors.
|
||||
|
||||
=head1 ENVIRONMENT VARIABLES
|
||||
|
||||
For the full list of environment variables which may affect
|
||||
libguestfs, please see the L<guestfs(3)> manual page.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<guestfs(3)>,
|
||||
L<febootstrap(8)>,
|
||||
L<febootstrap-supermin-helper(8)>,
|
||||
L<xz(1)>,
|
||||
L<http://libguestfs.org/>,
|
||||
L<http://qemu.org/>.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Richard W.M. Jones (C<rjones at redhat dot com>)
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (C) 2009-2012 Red Hat Inc.
|
||||
L<http://libguestfs.org/>
|
||||
|
||||
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.
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash -
|
||||
# @configure_input@
|
||||
# Copyright (C) 2009-2010 Red Hat Inc.
|
||||
# Copyright (C) 2009-2012 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
|
||||
|
||||
@@ -102,8 +102,10 @@ dosfstools
|
||||
file
|
||||
findutils
|
||||
gawk
|
||||
genisoimage
|
||||
grep
|
||||
gzip
|
||||
iproute
|
||||
jfsutils
|
||||
libxml2
|
||||
lsof
|
||||
@@ -111,7 +113,6 @@ lvm2
|
||||
lzop
|
||||
mdadm
|
||||
module-init-tools
|
||||
net-tools
|
||||
/*
|
||||
Enabling this pulls out 140 extra packages
|
||||
into the appliance:
|
||||
@@ -119,6 +120,7 @@ ocfs2-tools
|
||||
*/
|
||||
parted
|
||||
procps
|
||||
psmisc
|
||||
scrub
|
||||
strace
|
||||
tar
|
||||
@@ -129,3 +131,7 @@ tar
|
||||
xfsprogs
|
||||
#endif
|
||||
zerofree
|
||||
|
||||
#ifdef VALGRIND_DAEMON
|
||||
valgrind
|
||||
#endif
|
||||
|
||||
52
bindtests
52
bindtests
@@ -7,6 +7,10 @@ false
|
||||
123
|
||||
456
|
||||
<61><62><63><00><61><62><63>
|
||||
obool: true
|
||||
oint: 1
|
||||
oint64: unset
|
||||
ostring: unset
|
||||
abc
|
||||
null
|
||||
[]
|
||||
@@ -16,6 +20,10 @@ false
|
||||
123
|
||||
456
|
||||
<61><62><63><00><61><62><63>
|
||||
obool: unset
|
||||
oint: unset
|
||||
oint64: 1
|
||||
ostring: string
|
||||
|
||||
def
|
||||
[]
|
||||
@@ -25,6 +33,10 @@ false
|
||||
123
|
||||
456
|
||||
<61><62><63><00><61><62><63>
|
||||
obool: false
|
||||
oint: unset
|
||||
oint64: unset
|
||||
ostring: unset
|
||||
|
||||
|
||||
[]
|
||||
@@ -34,6 +46,10 @@ false
|
||||
123
|
||||
456
|
||||
<61><62><63><00><61><62><63>
|
||||
obool: unset
|
||||
oint: unset
|
||||
oint64: unset
|
||||
ostring: unset
|
||||
abc
|
||||
def
|
||||
["1"]
|
||||
@@ -43,6 +59,10 @@ false
|
||||
123
|
||||
456
|
||||
<61><62><63><00><61><62><63>
|
||||
obool: unset
|
||||
oint: unset
|
||||
oint64: unset
|
||||
ostring: unset
|
||||
abc
|
||||
def
|
||||
["1", "2"]
|
||||
@@ -52,6 +72,10 @@ false
|
||||
123
|
||||
456
|
||||
<61><62><63><00><61><62><63>
|
||||
obool: unset
|
||||
oint: unset
|
||||
oint64: unset
|
||||
ostring: unset
|
||||
abc
|
||||
def
|
||||
["1"]
|
||||
@@ -61,6 +85,10 @@ true
|
||||
123
|
||||
456
|
||||
<61><62><63><00><61><62><63>
|
||||
obool: unset
|
||||
oint: unset
|
||||
oint64: unset
|
||||
ostring: unset
|
||||
abc
|
||||
def
|
||||
["1"]
|
||||
@@ -70,6 +98,10 @@ false
|
||||
123
|
||||
456
|
||||
<61><62><63><00><61><62><63>
|
||||
obool: unset
|
||||
oint: unset
|
||||
oint64: unset
|
||||
ostring: unset
|
||||
abc
|
||||
def
|
||||
["1"]
|
||||
@@ -79,6 +111,10 @@ false
|
||||
123
|
||||
456
|
||||
<61><62><63><00><61><62><63>
|
||||
obool: unset
|
||||
oint: unset
|
||||
oint64: unset
|
||||
ostring: unset
|
||||
abc
|
||||
def
|
||||
["1"]
|
||||
@@ -88,6 +124,10 @@ false
|
||||
123
|
||||
456
|
||||
<61><62><63><00><61><62><63>
|
||||
obool: unset
|
||||
oint: unset
|
||||
oint64: unset
|
||||
ostring: unset
|
||||
abc
|
||||
def
|
||||
["1"]
|
||||
@@ -97,6 +137,10 @@ false
|
||||
123
|
||||
456
|
||||
<61><62><63><00><61><62><63>
|
||||
obool: unset
|
||||
oint: unset
|
||||
oint64: unset
|
||||
ostring: unset
|
||||
abc
|
||||
def
|
||||
["1"]
|
||||
@@ -106,6 +150,10 @@ false
|
||||
123
|
||||
456
|
||||
<61><62><63><00><61><62><63>
|
||||
obool: unset
|
||||
oint: unset
|
||||
oint64: unset
|
||||
ostring: unset
|
||||
abc
|
||||
def
|
||||
["1"]
|
||||
@@ -115,4 +163,8 @@ false
|
||||
|
||||
|
||||
<61><62><63><00><61><62><63>
|
||||
obool: unset
|
||||
oint: unset
|
||||
oint64: unset
|
||||
ostring: unset
|
||||
EOF
|
||||
|
||||
@@ -44,11 +44,14 @@ gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
|
||||
(cd daemon && mkdir -p tests lib && ../$gnulib_tool --update)
|
||||
|
||||
modules='
|
||||
accept4
|
||||
arpa_inet
|
||||
byteswap
|
||||
c-ctype
|
||||
cloexec
|
||||
closeout
|
||||
connect
|
||||
dup3
|
||||
error
|
||||
filevercmp
|
||||
fsusage
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash -
|
||||
# bugs-in-changelog.sh
|
||||
# Copyright (C) 2009-2010 Red Hat Inc.
|
||||
# Copyright (C) 2009-2012 Red Hat Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# libguestfs virt-cat, virt-filesystems and virt-ls.
|
||||
# Copyright (C) 2010-2011 Red Hat Inc.
|
||||
# Copyright (C) 2010-2012 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
|
||||
@@ -132,8 +132,8 @@ 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)
|
||||
$(top_builddir)/run
|
||||
|
||||
if ENABLE_APPLIANCE
|
||||
TESTS = test-virt-cat.sh test-virt-filesystems.sh test-virt-ls.sh
|
||||
endif ENABLE_APPLIANCE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* virt-cat
|
||||
* Copyright (C) 2010-2011 Red Hat Inc.
|
||||
* Copyright (C) 2010-2012 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
|
||||
@@ -189,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);
|
||||
|
||||
@@ -255,7 +255,7 @@ Richard W.M. Jones L<http://people.redhat.com/~rjones/>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (C) 2010-2011 Red Hat Inc.
|
||||
Copyright (C) 2010-2012 Red Hat Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* virt-filesystems
|
||||
* Copyright (C) 2010-2011 Red Hat Inc.
|
||||
* Copyright (C) 2010-2012 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
|
||||
@@ -77,16 +77,20 @@ static int output = 0;
|
||||
#define COLUMN_VFS_LABEL 8 /* if --filesystems */
|
||||
#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_PARENTS 64
|
||||
#define COLUMN_UUID 128 /* if --uuid */
|
||||
#define NR_COLUMNS 8
|
||||
static int columns;
|
||||
|
||||
static char *canonical_device (const char *dev);
|
||||
|
||||
static void do_output_title (void);
|
||||
static void do_output (void);
|
||||
static void do_output_end (void);
|
||||
|
||||
static struct guestfs_lvm_pv_list *get_pvs (void);
|
||||
static void free_pvs (void);
|
||||
|
||||
static inline char *
|
||||
bad_cast (char const *s)
|
||||
{
|
||||
@@ -334,8 +338,7 @@ main (int argc, char *argv[])
|
||||
columns |= COLUMN_VFS_TYPE;
|
||||
columns |= COLUMN_VFS_LABEL;
|
||||
}
|
||||
if ((output & (OUTPUT_PARTITIONS|OUTPUT_LVS)))
|
||||
columns |= COLUMN_PARENT_NAME;
|
||||
columns |= COLUMN_PARENTS;
|
||||
if ((output & OUTPUT_PARTITIONS))
|
||||
columns |= COLUMN_MBR;
|
||||
if (uuid)
|
||||
@@ -365,6 +368,8 @@ main (int argc, char *argv[])
|
||||
do_output ();
|
||||
do_output_end ();
|
||||
|
||||
free_pvs ();
|
||||
|
||||
guestfs_close (g);
|
||||
|
||||
exit (EXIT_SUCCESS);
|
||||
@@ -376,9 +381,18 @@ 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, int mbr_id, 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, char **parents, const char *uuid);
|
||||
static void write_row_strings (char **strings, size_t len);
|
||||
|
||||
static char **no_parents (void);
|
||||
static int is_md (char *device);
|
||||
static char **parents_of_md (char *device);
|
||||
static char **parents_of_vg (char *vg);
|
||||
|
||||
static void free_strings (char **strings);
|
||||
static size_t count_strings (char **strings);
|
||||
|
||||
static void
|
||||
do_output_title (void)
|
||||
{
|
||||
@@ -398,7 +412,7 @@ do_output_title (void)
|
||||
headings[len++] = "MBR";
|
||||
if ((columns & COLUMN_SIZE))
|
||||
headings[len++] = "Size";
|
||||
if ((columns & COLUMN_PARENT_NAME))
|
||||
if ((columns & COLUMN_PARENTS))
|
||||
headings[len++] = "Parent";
|
||||
if ((columns & COLUMN_UUID))
|
||||
headings[len++] = "UUID";
|
||||
@@ -444,6 +458,7 @@ do_output_filesystems (void)
|
||||
|
||||
for (i = 0; fses[i] != NULL; i += 2) {
|
||||
char *dev, *vfs_label = NULL, *vfs_uuid = NULL;
|
||||
char **parents;
|
||||
int64_t size = -1;
|
||||
|
||||
/* Skip swap and unknown, unless --extra flag was given. */
|
||||
@@ -486,9 +501,15 @@ do_output_filesystems (void)
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
write_row (dev, "filesystem",
|
||||
fses[i+1], vfs_label, -1, size, NULL, vfs_uuid);
|
||||
if (is_md (fses[i]))
|
||||
parents = parents_of_md (fses[i]);
|
||||
else
|
||||
parents = no_parents ();
|
||||
|
||||
write_row (dev, "filesystem",
|
||||
fses[i+1], vfs_label, -1, size, parents, vfs_uuid);
|
||||
|
||||
free_strings (parents);
|
||||
free (dev);
|
||||
free (vfs_label);
|
||||
free (vfs_uuid);
|
||||
@@ -513,6 +534,7 @@ do_output_lvs (void)
|
||||
|
||||
for (i = 0; lvs[i] != NULL; ++i) {
|
||||
char *uuid = NULL, *parent_name = NULL;
|
||||
const char *parents[2];
|
||||
int64_t size = -1;
|
||||
|
||||
if ((columns & COLUMN_SIZE)) {
|
||||
@@ -525,7 +547,7 @@ do_output_lvs (void)
|
||||
if (uuid == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
if ((columns & COLUMN_PARENT_NAME)) {
|
||||
if ((columns & COLUMN_PARENTS)) {
|
||||
parent_name = strdup (lvs[i]);
|
||||
if (parent_name == NULL) {
|
||||
perror ("strdup");
|
||||
@@ -534,10 +556,12 @@ do_output_lvs (void)
|
||||
char *p = strrchr (parent_name, '/');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
parents[0] = parent_name;
|
||||
parents[1] = NULL;
|
||||
}
|
||||
|
||||
write_row (lvs[i], "lv",
|
||||
NULL, NULL, -1, size, parent_name, uuid);
|
||||
NULL, NULL, -1, size, (char **) parents, uuid);
|
||||
|
||||
free (uuid);
|
||||
free (parent_name);
|
||||
@@ -560,44 +584,71 @@ do_output_vgs (void)
|
||||
for (i = 0; i < vgs->len; ++i) {
|
||||
char name[PATH_MAX];
|
||||
char uuid[33];
|
||||
char **parents;
|
||||
|
||||
strcpy (name, "/dev/");
|
||||
strcpy (&name[5], vgs->val[i].vg_name);
|
||||
|
||||
memcpy (uuid, vgs->val[i].vg_uuid, 32);
|
||||
uuid[32] = '\0';
|
||||
write_row (name, "vg",
|
||||
NULL, NULL, -1, (int64_t) vgs->val[i].vg_size, NULL, uuid);
|
||||
|
||||
parents = parents_of_vg (vgs->val[i].vg_name);
|
||||
|
||||
write_row (name, "vg",
|
||||
NULL, NULL, -1, (int64_t) vgs->val[i].vg_size, parents, uuid);
|
||||
|
||||
free_strings (parents);
|
||||
}
|
||||
|
||||
guestfs_free_lvm_vg_list (vgs);
|
||||
}
|
||||
|
||||
/* Cache the output of guestfs_pvs_full, since we use it in a few places. */
|
||||
static struct guestfs_lvm_pv_list *pvs_ = NULL;
|
||||
|
||||
static struct guestfs_lvm_pv_list *
|
||||
get_pvs (void)
|
||||
{
|
||||
if (pvs_)
|
||||
return pvs_;
|
||||
|
||||
pvs_ = guestfs_pvs_full (g);
|
||||
if (pvs_ == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
return pvs_;
|
||||
}
|
||||
|
||||
static void
|
||||
free_pvs (void)
|
||||
{
|
||||
if (pvs_)
|
||||
guestfs_free_lvm_pv_list (pvs_);
|
||||
|
||||
pvs_ = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
do_output_pvs (void)
|
||||
{
|
||||
struct guestfs_lvm_pv_list *pvs;
|
||||
size_t i;
|
||||
|
||||
pvs = guestfs_pvs_full (g);
|
||||
if (pvs == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
struct guestfs_lvm_pv_list *pvs = get_pvs ();
|
||||
|
||||
for (i = 0; i < pvs->len; ++i) {
|
||||
char *dev;
|
||||
char uuid[33];
|
||||
const char *parents[1] = { NULL };
|
||||
|
||||
dev = canonical_device (pvs->val[i].pv_name);
|
||||
|
||||
memcpy (uuid, pvs->val[i].pv_uuid, 32);
|
||||
uuid[32] = '\0';
|
||||
write_row (dev, "pv",
|
||||
NULL, NULL, -1, (int64_t) pvs->val[i].pv_size, NULL, uuid);
|
||||
NULL, NULL, -1, (int64_t) pvs->val[i].pv_size,
|
||||
(char **) parents, uuid);
|
||||
|
||||
free (dev);
|
||||
}
|
||||
|
||||
guestfs_free_lvm_pv_list (pvs);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -638,6 +689,7 @@ do_output_partitions (void)
|
||||
|
||||
for (i = 0; parts[i] != NULL; ++i) {
|
||||
char *dev, *parent_name = NULL;
|
||||
const char *parents[2];
|
||||
int64_t size = -1;
|
||||
int mbr_id = -1;
|
||||
|
||||
@@ -648,7 +700,7 @@ do_output_partitions (void)
|
||||
if (size == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
if ((columns & COLUMN_PARENT_NAME)) {
|
||||
if ((columns & COLUMN_PARENTS)) {
|
||||
parent_name = guestfs_part_to_dev (g, parts[i]);
|
||||
if (parent_name == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
@@ -659,10 +711,13 @@ do_output_partitions (void)
|
||||
char *p = canonical_device (parent_name);
|
||||
free (parent_name);
|
||||
parent_name = p;
|
||||
|
||||
parents[0] = parent_name;
|
||||
parents[1] = NULL;
|
||||
}
|
||||
|
||||
write_row (dev, "partition",
|
||||
NULL, NULL, mbr_id, size, parent_name, NULL);
|
||||
NULL, NULL, mbr_id, size, (char **) parents, NULL);
|
||||
|
||||
free (dev);
|
||||
free (parent_name);
|
||||
@@ -685,6 +740,7 @@ do_output_blockdevs (void)
|
||||
for (i = 0; devices[i] != NULL; ++i) {
|
||||
int64_t size = -1;
|
||||
char *dev;
|
||||
char **parents;
|
||||
|
||||
dev = canonical_device (devices[i]);
|
||||
|
||||
@@ -694,11 +750,17 @@ do_output_blockdevs (void)
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (is_md (devices[i]))
|
||||
parents = parents_of_md (devices[i]);
|
||||
else
|
||||
parents = no_parents ();
|
||||
|
||||
write_row (dev, "device",
|
||||
NULL, NULL, -1, size, NULL, NULL);
|
||||
NULL, NULL, -1, size, parents, NULL);
|
||||
|
||||
free (dev);
|
||||
free (devices[i]);
|
||||
free_strings (parents);
|
||||
}
|
||||
|
||||
free (devices);
|
||||
@@ -724,12 +786,177 @@ canonical_device (const char *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Returns an empty list of parents. Note this must be freed using
|
||||
* free_strings.
|
||||
*/
|
||||
static char **
|
||||
no_parents (void)
|
||||
{
|
||||
char **ret;
|
||||
|
||||
ret = malloc (sizeof (char *));
|
||||
if (!ret) {
|
||||
perror ("malloc");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret[0] = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* XXX Should be a better test than this. */
|
||||
static int
|
||||
is_md (char *device)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (!STRPREFIX (device, "/dev/md"))
|
||||
return 0;
|
||||
|
||||
p = device + 7;
|
||||
while (*p) {
|
||||
if (!c_isdigit (*p))
|
||||
return 0;
|
||||
p++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char **
|
||||
parents_of_md (char *device)
|
||||
{
|
||||
struct guestfs_mdstat_list *stats;
|
||||
char **ret;
|
||||
size_t i;
|
||||
|
||||
stats = guestfs_md_stat (g, device);
|
||||
if (!stats)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
ret = malloc ((stats->len + 1) * sizeof (char *));
|
||||
if (!ret) {
|
||||
perror ("malloc");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; i < stats->len; ++i)
|
||||
ret[i] = canonical_device (stats->val[i].mdstat_device);
|
||||
|
||||
ret[stats->len] = NULL;
|
||||
|
||||
guestfs_free_mdstat_list (stats);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Specialized PV UUID comparison function.
|
||||
* pvuuid1: from vgpvuuids, this may contain '-' characters which
|
||||
* should be ignored.
|
||||
* pvuuid2: from pvs-full, this is 32 characters long and NOT
|
||||
* terminated by \0
|
||||
*/
|
||||
static int
|
||||
compare_pvuuids (const char *pvuuid1, const char *pvuuid2)
|
||||
{
|
||||
size_t i;
|
||||
const char *p = pvuuid1;
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
while (*p && !c_isalnum (*p))
|
||||
p++;
|
||||
if (!*p)
|
||||
return 0;
|
||||
if (*p != pvuuid2[i])
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char **
|
||||
parents_of_vg (char *vg)
|
||||
{
|
||||
struct guestfs_lvm_pv_list *pvs = get_pvs ();
|
||||
char **pvuuids;
|
||||
char **ret;
|
||||
size_t n, i, j;
|
||||
|
||||
pvuuids = guestfs_vgpvuuids (g, vg);
|
||||
if (!pvuuids)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
n = count_strings (pvuuids);
|
||||
|
||||
ret = malloc ((n + 1) * sizeof (char *));
|
||||
if (!ret) {
|
||||
perror ("malloc");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Resolve each PV UUID back to a PV. */
|
||||
for (i = 0; i < n; ++i) {
|
||||
for (j = 0; j < pvs->len; ++j) {
|
||||
if (compare_pvuuids (pvuuids[i], pvs->val[j].pv_uuid) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j < pvs->len)
|
||||
ret[i] = canonical_device (pvs->val[j].pv_name);
|
||||
else {
|
||||
fprintf (stderr, "%s: warning: unknown PV UUID ignored\n", __func__);
|
||||
ret[i] = strndup (pvuuids[i], 32);
|
||||
if (!ret[i]) {
|
||||
perror ("strndup");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret[i] = NULL;
|
||||
|
||||
free_strings (pvuuids);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
join_comma (char **strings)
|
||||
{
|
||||
size_t i, count;
|
||||
char *ret;
|
||||
|
||||
for (count = i = 0; strings[i] != NULL; ++i) {
|
||||
if (i > 0)
|
||||
count++;
|
||||
count += strlen (strings[i]);
|
||||
}
|
||||
|
||||
ret = malloc (count + 1);
|
||||
if (ret == NULL) {
|
||||
perror ("malloc");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (count = i = 0; strings[i] != NULL; ++i) {
|
||||
if (i > 0)
|
||||
ret[count++] = ',';
|
||||
strcpy (&ret[count], strings[i]);
|
||||
count += strlen (strings[i]);
|
||||
}
|
||||
ret[count] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
int64_t size, char **parents, const char *uuid)
|
||||
{
|
||||
const char *strings[NR_COLUMNS];
|
||||
char *parents_str = NULL;
|
||||
size_t len = 0;
|
||||
char hum[LONGEST_HUMAN_READABLE];
|
||||
char num[256];
|
||||
@@ -767,13 +994,18 @@ write_row (const char *name, const char *type,
|
||||
else
|
||||
strings[len++] = NULL;
|
||||
}
|
||||
if ((columns & COLUMN_PARENT_NAME))
|
||||
strings[len++] = parent_name;
|
||||
if ((columns & COLUMN_PARENTS)) {
|
||||
/* Internally comma-separated field. */
|
||||
parents_str = join_comma (parents);
|
||||
strings[len++] = parents_str;
|
||||
}
|
||||
if ((columns & COLUMN_UUID))
|
||||
strings[len++] = uuid;
|
||||
assert (len <= NR_COLUMNS);
|
||||
|
||||
write_row_strings ((char **) strings, len);
|
||||
|
||||
free (parents_str);
|
||||
}
|
||||
|
||||
static void add_row (char **strings, size_t len);
|
||||
@@ -942,3 +1174,23 @@ do_output_end (void)
|
||||
}
|
||||
free (rows);
|
||||
}
|
||||
|
||||
static void
|
||||
free_strings (char **strings)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; strings[i] != NULL; ++i)
|
||||
free (strings[i]);
|
||||
free (strings);
|
||||
}
|
||||
|
||||
static size_t
|
||||
count_strings (char **strings)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; strings[i] != NULL; ++i)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -332,10 +332,14 @@ then the size is displayed in a human-readable form.
|
||||
=item B<Parent>
|
||||
|
||||
The parent column records the parent relationship between objects.
|
||||
|
||||
For example, if the object is a partition, then this column contains
|
||||
the name of the containing device. If the object is a logical volume,
|
||||
then this column is the name of the volume group.
|
||||
|
||||
If there is more than one parent, then this column is (internal to the
|
||||
column) a comma-separated list, eg. C</dev/sda,/dev/sdb>.
|
||||
|
||||
=item B<UUID>
|
||||
|
||||
If the object has a UUID (used for identifying and mounting
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* virt-ls
|
||||
* Copyright (C) 2010-2011 Red Hat Inc.
|
||||
* Copyright (C) 2010-2012 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
|
||||
@@ -36,6 +36,10 @@
|
||||
#include "guestfs.h"
|
||||
#include "options.h"
|
||||
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
/* Currently open libguestfs handle. */
|
||||
guestfs_h *g;
|
||||
|
||||
@@ -101,7 +105,7 @@ usage (int status)
|
||||
else {
|
||||
fprintf (stdout,
|
||||
_("%s: list files in a virtual machine\n"
|
||||
"Copyright (C) 2010-2011 Red Hat Inc.\n"
|
||||
"Copyright (C) 2010-2012 Red Hat Inc.\n"
|
||||
"Usage:\n"
|
||||
" %s [--options] -d domname dir [dir ...]\n"
|
||||
" %s [--options] -a disk.img [-a disk.img ...] dir [dir ...]\n"
|
||||
@@ -297,18 +301,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);
|
||||
@@ -469,7 +472,7 @@ do_ls_R (const char *dir)
|
||||
/* The output of find0 is a \0-separated file. Turn each \0 into
|
||||
* a \n character.
|
||||
*/
|
||||
fd = open (tmpfile, O_RDONLY);
|
||||
fd = open (tmpfile, O_RDONLY|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
perror (tmpfile);
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
@@ -510,7 +510,7 @@ Richard W.M. Jones L<http://people.redhat.com/~rjones/>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (C) 2009-2011 Red Hat Inc.
|
||||
Copyright (C) 2009-2012 Red Hat Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,398 +0,0 @@
|
||||
#!/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
|
||||
460
configure.ac
460
configure.ac
@@ -1,5 +1,5 @@
|
||||
# libguestfs
|
||||
# Copyright (C) 2009-2011 Red Hat Inc.
|
||||
# Copyright (C) 2009-2012 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
|
||||
@@ -19,8 +19,8 @@
|
||||
# add extra information using --with-extra="..." which may be any
|
||||
# freeform string.
|
||||
m4_define([libguestfs_major], [1])
|
||||
m4_define([libguestfs_minor], [15])
|
||||
m4_define([libguestfs_release], [12])
|
||||
m4_define([libguestfs_minor], [17])
|
||||
m4_define([libguestfs_release], [39])
|
||||
|
||||
AC_INIT([libguestfs],libguestfs_major.libguestfs_minor.libguestfs_release)
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
@@ -101,9 +101,8 @@ if test "$gl_gcc_warnings" = yes; then
|
||||
nw="$nw -Wcast-qual" # Too many warnings for now
|
||||
nw="$nw -Wconversion" # Too many warnings for now
|
||||
nw="$nw -Wsystem-headers" # Don't let system headers trigger warnings
|
||||
nw="$nw -Wsign-conversion" # Too many warnings for now
|
||||
nw="$nw -Wtraditional-conversion" # Too many warnings for now
|
||||
nw="$nw -Wunreachable-code" # Too many warnings for now
|
||||
nw="$nw -Wsign-conversion" # Not an error
|
||||
nw="$nw -Wtraditional-conversion" # Don't care about pre-ANSI compilers
|
||||
nw="$nw -Wpadded" # Our structs are not padded
|
||||
nw="$nw -Wredundant-decls" # openat.h declares e.g., mkdirat
|
||||
nw="$nw -Wlogical-op" # any use of fwrite provokes this
|
||||
@@ -117,10 +116,6 @@ if test "$gl_gcc_warnings" = yes; then
|
||||
nw="$nw -Wpacked" # Allow attribute((packed)) on structs
|
||||
nw="$nw -Wlong-long" # Allow long long since it's required
|
||||
# by Python, Ruby and xstrtoll.
|
||||
nw="$nw -Wstack-protector" # Don't warn about stack-protector
|
||||
# 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.
|
||||
@@ -130,17 +125,17 @@ if test "$gl_gcc_warnings" = yes; then
|
||||
for w in $ws; do
|
||||
gl_WARN_ADD([$w])
|
||||
done
|
||||
gl_WARN_ADD([-Wno-unused-parameter]) # stubs.c
|
||||
gl_WARN_ADD([-Wno-jump-misses-init]) # stubs.c
|
||||
gl_WARN_ADD([-Wno-unused-variable]) # FIXME: only temporary, for guestfs_protocol.c, etc
|
||||
|
||||
# In spite of excluding -Wlogical-op above, it is enabled, as of
|
||||
# gcc 4.5.0 20090517, and it provokes warnings in cat.c, dd.c, truncate.c
|
||||
gl_WARN_ADD([-Wno-logical-op])
|
||||
# Normally we disable warnings in $nw above. However for some
|
||||
# unknown reason that doesn't always work, and we need to explicitly
|
||||
# list a few disabled warnings below.
|
||||
|
||||
# Work around warning in src/inspect.c. This seems to be a bug in gcc 4.5.1.
|
||||
gl_WARN_ADD([-Wno-strict-overflow])
|
||||
gl_WARN_ADD([-Wno-unused-parameter]) # Unused parameters are not a bug.
|
||||
|
||||
# Missing field initializers is not a bug in C.
|
||||
gl_WARN_ADD([-Wno-missing-field-initializers])
|
||||
|
||||
# Display the name of the warning option with the warning.
|
||||
gl_WARN_ADD([-fdiagnostics-show-option])
|
||||
|
||||
AC_SUBST([WARN_CFLAGS])
|
||||
@@ -162,6 +157,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
|
||||
|
||||
@@ -211,6 +212,7 @@ AC_CHECK_FUNCS([\
|
||||
ntohl \
|
||||
ntohs \
|
||||
posix_fallocate \
|
||||
posix_fadvise \
|
||||
realpath \
|
||||
removexattr \
|
||||
setitimer \
|
||||
@@ -219,6 +221,20 @@ AC_CHECK_FUNCS([\
|
||||
statvfs \
|
||||
sync])
|
||||
|
||||
dnl tgetent, tputs and UP [sic] are all required. They come from libtinfo
|
||||
dnl which is pulled in as a dependency of libncurses.
|
||||
old_LIBS="$LIBS"
|
||||
AC_CHECK_LIB([ncurses], [tgetent], [], [
|
||||
AC_MSG_ERROR(['ncurses' library not found, or it doesn't contain 'tgetent'])
|
||||
])
|
||||
AC_CHECK_LIB([ncurses], [tputs], [], [
|
||||
AC_MSG_ERROR(['ncurses' library not found, or it doesn't contain 'tputs'])
|
||||
])
|
||||
AC_CHECK_LIB([ncurses], [UP], [], [
|
||||
AC_MSG_ERROR(['ncurses' library not found, or it doesn't contain 'UP'])
|
||||
])
|
||||
LIBS="$old_LIBS"
|
||||
|
||||
dnl For modified printf in the daemon, we need glibc either (old-style)
|
||||
dnl register_printf_function or (new-style) register_printf_specifier.
|
||||
AC_CHECK_FUNC([register_printf_specifier],[
|
||||
@@ -235,6 +251,23 @@ AC_CHECK_FUNC([register_printf_specifier],[
|
||||
This means you either have a very old glibc (pre-2.0) or you
|
||||
are using some other libc where this is not supported.])])])
|
||||
|
||||
dnl GNU gettext tools (optional).
|
||||
AC_CHECK_PROG([XGETTEXT],[xgettext],[xgettext],[no])
|
||||
AC_CHECK_PROG([MSGCAT],[msgcat],[msgcat],[no])
|
||||
AC_CHECK_PROG([MSGFMT],[msgfmt],[msgfmt],[no])
|
||||
AC_CHECK_PROG([MSGMERGE],[msgmerge],[msgmerge],[no])
|
||||
|
||||
dnl Check they are the GNU gettext tools.
|
||||
AC_MSG_CHECKING([msgfmt is GNU tool])
|
||||
if $MSGFMT --version >/dev/null 2>&1 && $MSGFMT --version | grep -q 'GNU gettext'; then
|
||||
msgfmt_is_gnu=yes
|
||||
else
|
||||
msgfmt_is_gnu=no
|
||||
fi
|
||||
AC_MSG_RESULT([$msgfmt_is_gnu])
|
||||
AM_CONDITIONAL([HAVE_GNU_GETTEXT],
|
||||
[test "x$XGETTEXT" != "xno" && test "x$MSGCAT" != "xno" && test "x$MSGFMT" != "xno" && test "x$MSGMERGE" != "xno" && test "x$msgfmt_is_gnu" != "xno"])
|
||||
|
||||
dnl Build the daemon?
|
||||
AC_MSG_CHECKING([if we should build the daemon])
|
||||
AC_ARG_ENABLE([daemon],
|
||||
@@ -253,9 +286,46 @@ if test "x$enable_daemon" = "xyes"; then
|
||||
[enable installing the daemon under $sbindir @<:@default=no@:>@])],
|
||||
[],
|
||||
[enable_install_daemon=no])
|
||||
AM_CONDITIONAL([INSTALL_DAEMON],[test "x$enable_install_daemon" = "xyes"])
|
||||
AC_MSG_RESULT([$enable_install_daemon])
|
||||
|
||||
dnl Enable valgrind in the daemon.
|
||||
AC_MSG_CHECKING([if we should run the daemon under valgrind])
|
||||
AC_ARG_ENABLE([valgrind-daemon],
|
||||
[AS_HELP_STRING([--enable-valgrind-daemon],
|
||||
[run the daemon under valgrind (developers only) @<:@default=no@:>@])],
|
||||
[],
|
||||
[enable_valgrind_daemon=no])
|
||||
AC_MSG_RESULT([$enable_valgrind_daemon])
|
||||
|
||||
if test "x$enable_valgrind_daemon" = "xyes"; then
|
||||
AC_DEFINE([VALGRIND_DAEMON],[1],[Define to 1 to run the daemon under valgrind])
|
||||
AC_DEFINE_UNQUOTED([VALGRIND_LOG_PATH],["$(pwd)"],[Path to save valgrind log files])
|
||||
fi
|
||||
|
||||
dnl Which directory should we put the daemon in? NOTE: This
|
||||
dnl is the "virtual" directory inside the appliance, not the
|
||||
dnl install directory for libguestfs live. Since Fedora 17
|
||||
dnl /sbin is a symlink to /usr/sbin. We have to put the
|
||||
dnl daemon into a real (non-symlink) directory.
|
||||
dirs="/sbin /usr/sbin /bin /usr/bin"
|
||||
AC_MSG_CHECKING([which of $dirs is a real directory])
|
||||
for dir in $dirs; do
|
||||
parent=`dirname $dir`
|
||||
if test ! -L $parent && test -d $parent \
|
||||
&& test ! -L $dir && test -d $dir
|
||||
then
|
||||
DAEMON_SUPERMIN_DIR=$dir
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test "x$DAEMON_SUPERMIN_DIR" = "x"; then
|
||||
AC_MSG_ERROR([non-symlink binary directory not found])
|
||||
fi
|
||||
AC_MSG_RESULT([$DAEMON_SUPERMIN_DIR])
|
||||
AC_SUBST([DAEMON_SUPERMIN_DIR])
|
||||
fi
|
||||
AM_CONDITIONAL([INSTALL_DAEMON],[test "x$enable_install_daemon" = "xyes"])
|
||||
AM_CONDITIONAL([VALGRIND_DAEMON],[test "x$enable_valgrind_daemon" = "xyes"])
|
||||
|
||||
dnl Build the appliance?
|
||||
AC_MSG_CHECKING([if we should build the appliance])
|
||||
@@ -267,47 +337,48 @@ AC_ARG_ENABLE([appliance],
|
||||
AM_CONDITIONAL([ENABLE_APPLIANCE],[test "x$enable_appliance" = "xyes"])
|
||||
AC_MSG_RESULT([$enable_appliance])
|
||||
|
||||
dnl Check for febootstrap >= 3.0
|
||||
AC_CHECK_PROG([FEBOOTSTRAP],
|
||||
[febootstrap],[febootstrap],[no])
|
||||
|
||||
dnl Pass a febootstrap --yum-config option.
|
||||
AC_MSG_CHECKING([if user requested febootstrap --yum-config option])
|
||||
AC_ARG_WITH([febootstrap-yum-config],
|
||||
[AS_HELP_STRING([--with-febootstrap-yum-config=FILE],
|
||||
[pass febootstrap --yum-config option @<:@default=no@:>@])],
|
||||
[FEBOOTSTRAP_YUM_CONFIG="$withval"],
|
||||
[FEBOOTSTRAP_YUM_CONFIG=no])
|
||||
AC_MSG_RESULT([$FEBOOTSTRAP_YUM_CONFIG])
|
||||
AC_SUBST([FEBOOTSTRAP_YUM_CONFIG])
|
||||
|
||||
if test "x$enable_appliance" = "xyes"; then
|
||||
dnl Check for febootstrap >= 3.0
|
||||
AC_CHECK_PROG([FEBOOTSTRAP],
|
||||
[febootstrap],[febootstrap],[no])
|
||||
test "x$FEBOOTSTRAP" = "xno" &&
|
||||
AC_MSG_ERROR([febootstrap must be installed])
|
||||
dnl febootstrap 2.x did not support the --version parameter
|
||||
$FEBOOTSTRAP --version >&AS_MESSAGE_LOG_FD 2>&1 ||
|
||||
AC_MSG_ERROR([febootstrap >= 3.0 must be installed, your version is too old])
|
||||
|
||||
dnl Pass a febootstrap --yum-config option.
|
||||
AC_MSG_CHECKING([if user requested febootstrap --yum-config option])
|
||||
AC_ARG_WITH([febootstrap-yum-config],
|
||||
[AS_HELP_STRING([--with-febootstrap-yum-config=FILE],
|
||||
[pass febootstrap --yum-config option @<:@default=no@:>@])],
|
||||
[FEBOOTSTRAP_YUM_CONFIG="$withval"],
|
||||
[FEBOOTSTRAP_YUM_CONFIG=no])
|
||||
AC_MSG_RESULT([$FEBOOTSTRAP_YUM_CONFIG])
|
||||
AC_SUBST([FEBOOTSTRAP_YUM_CONFIG])
|
||||
|
||||
dnl Which distro?
|
||||
dnl
|
||||
dnl This used to be Very Important but is now just used to select
|
||||
dnl which packages to install in the appliance, since the package
|
||||
dnl names vary slightly across distros. (See
|
||||
dnl appliance/packagelist.in and appliance/excludelist.in)
|
||||
AC_MSG_CHECKING([which Linux distro for package names])
|
||||
DISTRO=REDHAT
|
||||
if test -f /etc/debian_version; then
|
||||
DISTRO=DEBIAN
|
||||
if grep -q 'DISTRIB_ID=Ubuntu' /etc/lsb-release 2>&AS_MESSAGE_LOG_FD; then
|
||||
DISTRO=UBUNTU
|
||||
fi
|
||||
fi
|
||||
if test -f /etc/arch-release; then
|
||||
DISTRO=ARCHLINUX
|
||||
fi
|
||||
AC_MSG_RESULT([$DISTRO])
|
||||
AC_SUBST([DISTRO])
|
||||
fi
|
||||
|
||||
dnl Which distro?
|
||||
dnl
|
||||
dnl This used to be Very Important but is now just used to select
|
||||
dnl which packages to install in the appliance, since the package
|
||||
dnl names vary slightly across distros. (See
|
||||
dnl appliance/packagelist.in and appliance/excludelist.in)
|
||||
AC_MSG_CHECKING([which Linux distro for package names])
|
||||
DISTRO=REDHAT
|
||||
if test -f /etc/debian_version; then
|
||||
DISTRO=DEBIAN
|
||||
if grep -q 'DISTRIB_ID=Ubuntu' /etc/lsb-release 2>&AS_MESSAGE_LOG_FD; then
|
||||
DISTRO=UBUNTU
|
||||
fi
|
||||
fi
|
||||
if test -f /etc/arch-release; then
|
||||
DISTRO=ARCHLINUX
|
||||
fi
|
||||
AC_MSG_RESULT([$DISTRO])
|
||||
AC_SUBST([DISTRO])
|
||||
|
||||
dnl Check for rpcgen and XDR library. rpcgen is optional.
|
||||
AC_CHECK_PROG([RPCGEN],[rpcgen],[rpcgen],[no])
|
||||
AM_CONDITIONAL([HAVE_RPCGEN],[test "x$RPCGEN" != "xno"])
|
||||
@@ -418,6 +489,30 @@ if test "x$DB_LOAD" != "xno"; then
|
||||
AC_DEFINE_UNQUOTED([DB_LOAD],["$DB_LOAD"],[Name of db_load program.])
|
||||
fi
|
||||
|
||||
dnl Check for netpbm programs (optional).
|
||||
AC_CHECK_PROGS([PBMTEXT],[pbmtext],[no])
|
||||
AC_CHECK_PROGS([PNMTOPNG],[pnmtopng],[no])
|
||||
AC_CHECK_PROGS([BMPTOPNM],[bmptopnm],[no])
|
||||
AC_CHECK_PROGS([PAMCUT],[pamcut],[no])
|
||||
if test "x$PBMTEXT" != "xno"; then
|
||||
AC_DEFINE_UNQUOTED([PBMTEXT],["$PBMTEXT"],[Name of pbmtext program.])
|
||||
fi
|
||||
if test "x$PNMTOPNG" != "xno"; then
|
||||
AC_DEFINE_UNQUOTED([PNMTOPNG],["$PNMTOPNG"],[Name of pnmtopng program.])
|
||||
fi
|
||||
if test "x$BMPTOPNM" != "xno"; then
|
||||
AC_DEFINE_UNQUOTED([BMPTOPNM],["$BMPTOPNM"],[Name of bmptopnm program.])
|
||||
fi
|
||||
if test "x$PAMCUT" != "xno"; then
|
||||
AC_DEFINE_UNQUOTED([PAMCUT],["$PAMCUT"],[Name of pamcut program.])
|
||||
fi
|
||||
|
||||
dnl Check for icoutils (optional).
|
||||
AC_CHECK_PROGS([WRESTOOL],[wrestool],[no])
|
||||
if test "x$WRESTOOL" != "xno"; then
|
||||
AC_DEFINE_UNQUOTED([WRESTOOL],["$WRESTOOL"],[Name of wrestool program.])
|
||||
fi
|
||||
|
||||
dnl Check for QEMU for running binaries on this $host_cpu, fall
|
||||
dnl back to basic 'qemu'. Allow the user to override it.
|
||||
default_qemu="qemu-kvm kvm qemu-system-$host_cpu qemu"
|
||||
@@ -574,9 +669,6 @@ AS_IF([test "x$with_readline" != xno],
|
||||
LIBS="$old_LIBS"
|
||||
])
|
||||
|
||||
dnl For i18n.
|
||||
AM_GNU_GETTEXT([external])
|
||||
|
||||
dnl Check for PCRE (required)
|
||||
PKG_CHECK_MODULES([PCRE], [libpcre])
|
||||
|
||||
@@ -633,12 +725,38 @@ AC_ARG_ENABLE([fuse],
|
||||
[],
|
||||
[enable_fuse=yes])
|
||||
AS_IF([test "x$enable_fuse" != "xno"],
|
||||
[PKG_CHECK_MODULES([FUSE],[fuse],,[
|
||||
enable_fuse=no
|
||||
AC_MSG_WARN([FUSE library and headers are missing, so optional FUSE module won't be built])])])
|
||||
[PKG_CHECK_MODULES([FUSE],[fuse],
|
||||
[AC_SUBST([FUSE_CFLAGS])
|
||||
AC_SUBST([FUSE_LIBS])
|
||||
AC_DEFINE([HAVE_FUSE],[1],[Define to 1 if you have FUSE])],
|
||||
[enable_fuse=no
|
||||
AC_MSG_WARN([FUSE library and headers are missing, so optional FUSE module won't be built])
|
||||
])
|
||||
])
|
||||
AM_CONDITIONAL([HAVE_FUSE],[test "x$enable_fuse" != "xno"])
|
||||
|
||||
dnl Check for OCaml (optional, for OCaml bindings).
|
||||
dnl Check for C++ (optional, we just use this to test the header works).
|
||||
AC_PROG_CXX
|
||||
|
||||
dnl The C++ compiler test is pretty useless because even if it fails
|
||||
dnl it sets CXX=g++. So test the compiler actually works.
|
||||
AM_CONDITIONAL([HAVE_CXX], [$CXX --version])
|
||||
|
||||
dnl If valgrind is present (it's not required), check whether or not
|
||||
dnl it supports the new 'valgrind --vgdb' option.
|
||||
AC_CHECK_PROG([VALGRIND],[valgrind],[valgrind],[no])
|
||||
AS_IF([test "x$valgrind" != "xno"],[
|
||||
AC_MSG_CHECKING([if $VALGRIND supports the --vgdb option])
|
||||
if $VALGRIND --help | grep -sq -- --vgdb; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_SUBST([VALGRIND_NO_VGDB],[--vgdb=no])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_SUBST([VALGRIND_NO_VGDB],[])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl Check for OCaml (optional, for OCaml bindings and OCaml tools).
|
||||
OCAMLC=no
|
||||
OCAMLFIND=no
|
||||
AC_ARG_ENABLE([ocaml],
|
||||
@@ -658,7 +776,96 @@ AM_CONDITIONAL([HAVE_OCAML],
|
||||
AM_CONDITIONAL([HAVE_OCAMLDOC],
|
||||
[test "x$OCAMLDOC" != "xno"])
|
||||
|
||||
dnl Check for Perl (optional, for Perl bindings).
|
||||
OCAML_PKG_gettext=no
|
||||
AS_IF([test "x$OCAMLC" != "xno"],[
|
||||
dnl Check for ocaml-gettext package to translate OCaml tools.
|
||||
AC_CHECK_OCAML_PKG(gettext)
|
||||
|
||||
dnl Write gettext modules for each OCaml tool. If OCaml gettext
|
||||
dnl is not available then we write dummy functions.
|
||||
for program in resize sparsify sysprep; do
|
||||
output=$program/${program}_gettext.ml
|
||||
AC_MSG_NOTICE([creating $output])
|
||||
rm -f $output
|
||||
|
||||
cat <<EOF > $output
|
||||
(* This file is generated automatically by ./configure. *)
|
||||
|
||||
(** Gettext functions for virt-$program.
|
||||
|
||||
The ${program}_gettext module provides gettext functions for
|
||||
$program, or dummy functions if ocaml-gettext was not available
|
||||
at configure time.
|
||||
|
||||
{b Note}: Don't translate debug strings, or strings which are
|
||||
meant to be read/written only by machine.
|
||||
|
||||
There are two ways to translate constant strings in OCaml programs.
|
||||
|
||||
For ordinary strings, replace [["string"]] with [[s_"string"]]. Since
|
||||
this is a function call to a function called [[s_]], you may have
|
||||
to put parentheses around the expression.
|
||||
|
||||
For format strings, use:
|
||||
|
||||
{v
|
||||
printf (f_"zeroing filesystem %s") filename;
|
||||
v}
|
||||
|
||||
Note for format strings, the parentheses are almost always required,
|
||||
and they just go around the [[(f_"string")]], {i not} around the other
|
||||
arguments of the printf function.
|
||||
|
||||
At build time, a program parses the OCaml code into an abstract
|
||||
syntax tree and statically determines all calls to the special
|
||||
[[s_]] and [[f_]] functions, which means: (a) You can be very loose
|
||||
with syntax, unlike ordinary xgettext, but (b) you cannot rename
|
||||
these functions.
|
||||
*)
|
||||
|
||||
EOF
|
||||
|
||||
if test "x$OCAML_PKG_gettext" != "xno"; then
|
||||
# ocaml-gettext available: real module.
|
||||
cat <<EOF >>$output
|
||||
module Gettext = Gettext.Program (
|
||||
struct
|
||||
let textdomain = "$PACKAGE_NAME"
|
||||
let codeset = None
|
||||
let dir = None
|
||||
let dependencies = [[]]
|
||||
end
|
||||
) (GettextStub.Native)
|
||||
EOF
|
||||
else
|
||||
# No gettext: module containing dummy gettext functions.
|
||||
cat <<EOF >>$output
|
||||
module Gettext = struct
|
||||
external s_ : string -> string = "%identity"
|
||||
external f_ : ('a, 'b, 'c, 'd, 'e, 'f) format6
|
||||
-> ('a, 'b, 'c, 'd, 'e, 'f) format6
|
||||
= "%identity"
|
||||
let sn_ : string -> string -> int -> string
|
||||
= fun s p n -> if n = 1 then s else p
|
||||
let fn_ : ('a, 'b, 'c, 'd, 'e, 'f) format6
|
||||
-> ('a, 'b, 'c, 'd, 'e, 'f) format6
|
||||
-> int -> ('a, 'b, 'c, 'd, 'e, 'f) format6
|
||||
= fun s p n -> if n = 1 then s else p
|
||||
end
|
||||
EOF
|
||||
fi
|
||||
|
||||
chmod -w $output
|
||||
done
|
||||
])
|
||||
AM_CONDITIONAL([HAVE_OCAML_PKG_GETTEXT],
|
||||
[test "x$OCAMLC" != "xno" && test "x$OCAMLFIND" != "xno" && test "x$OCAML_PKG_gettext" != "xno"])
|
||||
|
||||
AC_CHECK_PROG([OCAML_GETTEXT],[ocaml-gettext],[ocaml-gettext],[no])
|
||||
AM_CONDITIONAL([HAVE_OCAML_GETTEXT],
|
||||
[test "x$OCAMLC" != "xno" && test "x$OCAMLFIND" != "xno" && test "x$OCAML_PKG_gettext" != "xno" && test "x$OCAML_GETTEXT" != "xno"])
|
||||
|
||||
dnl Check for Perl (optional, for Perl bindings and Perl tools).
|
||||
PERL=no
|
||||
AC_ARG_ENABLE([perl],
|
||||
AS_HELP_STRING([--disable-perl], [Disable Perl language bindings]),
|
||||
@@ -738,19 +945,20 @@ AS_IF([test "x$enable_python" != "xno"],
|
||||
AC_MSG_RESULT([$PYTHON_INSTALLDIR])
|
||||
fi
|
||||
|
||||
dnl Look for libpython and some optional symbols in it.
|
||||
dnl Look for some optional symbols in libpython.
|
||||
old_LIBS="$LIBS"
|
||||
if test "x$PYTHON_VERSION_MAJOR" = "x3"; then
|
||||
dnl libpython3 is called "libpython3.Xmu.so"
|
||||
LIBPYTHON="python${PYTHON_VERSION}mu"
|
||||
else
|
||||
LIBPYTHON="python$PYTHON_VERSION"
|
||||
fi
|
||||
AC_CHECK_LIB([$LIBPYTHON], [PyList_Size], [],
|
||||
[AC_MSG_FAILURE([$LIBPYTHON is not installed])])
|
||||
|
||||
AC_CHECK_FUNCS([PyCapsule_New \
|
||||
PyString_AsString])
|
||||
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
|
||||
|
||||
@@ -890,10 +1098,23 @@ if test "x$with_java_home" != "xno"; then
|
||||
esac
|
||||
AC_MSG_RESULT([$JAVAC_FLAGS])
|
||||
|
||||
dnl Where to install jarfiles.
|
||||
dnl XXX How to make it configurable?
|
||||
JAR_INSTALL_DIR=\${prefix}/share/java
|
||||
JNI_INSTALL_DIR=\${libdir}
|
||||
dnl Extra lint flags?
|
||||
AC_MSG_CHECKING([extra javac lint flags])
|
||||
if $JAVAC -X >/dev/null 2>&1 && \
|
||||
$JAVAC -X 2>&1 | grep -q -- '-Xlint:.*all'; then
|
||||
AC_MSG_RESULT([-Xlint:all])
|
||||
JAVAC_FLAGS="$JAVAC_FLAGS -Xlint:all"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
dnl Where to install jarfiles, jnifiles
|
||||
if test -z $JAR_INSTALL_DIR; then
|
||||
JAR_INSTALL_DIR=\${prefix}/share/java
|
||||
fi
|
||||
if test -z $JNI_INSTALL_DIR; then
|
||||
JNI_INSTALL_DIR=\${libdir}
|
||||
fi
|
||||
|
||||
dnl JNI version.
|
||||
jni_major_version=`echo "$VERSION" | awk -F. '{print $1}'`
|
||||
@@ -985,6 +1206,67 @@ AS_IF([test "x$PERL" != "xno"],
|
||||
AM_CONDITIONAL([HAVE_TOOLS],
|
||||
[test "x$PERL" != "xno" && test "x$missing_perl_modules" != "xyes"])
|
||||
|
||||
dnl gobject library
|
||||
AC_ARG_ENABLE([gobject],
|
||||
AS_HELP_STRING([--disable-gobject], [Disable GObject bindings]),
|
||||
[],
|
||||
[enable_gobject=yes])
|
||||
AS_IF(
|
||||
[test "x$enable_gobject" != "xno"],
|
||||
[
|
||||
PKG_CHECK_MODULES([GOBJECT], [gobject-2.0 >= 2.26.0],
|
||||
[
|
||||
AC_SUBST([GOBJECT_CFLAGS])
|
||||
AC_SUBST([GOBJECT_LIBS])
|
||||
AC_DEFINE([HAVE_GOBJECT],[1],
|
||||
[gobject library found at compile time.])
|
||||
],
|
||||
[AC_MSG_WARN([gobject library not found, gobject binding will be disabled])]
|
||||
)
|
||||
|
||||
PKG_CHECK_MODULES([GIO], [gio-2.0 >= 2.26.0],
|
||||
[
|
||||
AC_SUBST([GIO_CFLAGS])
|
||||
AC_SUBST([GIO_LIBS])
|
||||
AC_DEFINE([HAVE_GIO],[1],
|
||||
[gio library found at compile time.])
|
||||
],
|
||||
[AC_MSG_WARN([gio library not found, gobject binding will be disabled])]
|
||||
)
|
||||
]
|
||||
)
|
||||
AM_CONDITIONAL([HAVE_GOBJECT],
|
||||
[test "x$GOBJECT_LIBS" != "x" -a "x$GIO_LIBS" != "x"])
|
||||
|
||||
AC_CHECK_PROG([GJS],[gjs],[gjs])
|
||||
AS_IF(
|
||||
[test "x$GJS" = "x"],
|
||||
[AC_MSG_WARN([gjs not found, gobject bindtests will not run])]
|
||||
)
|
||||
|
||||
dnl gobject introspection
|
||||
m4_ifdef([GOBJECT_INTROSPECTION_CHECK], [
|
||||
GOBJECT_INTROSPECTION_CHECK([1.30.0])
|
||||
|
||||
dnl The above check automatically sets HAVE_INTROSPECTION, but we
|
||||
dnl want this to be conditional on gobject also being
|
||||
dnl available. We can't move the above check inside the gobject if
|
||||
dnl block above or HAVE_INTROSPECTION ends up undefined, so we
|
||||
dnl recheck it here.
|
||||
AM_CONDITIONAL([HAVE_INTROSPECTION],
|
||||
[test "x$HAVE_INTROSPECTION_TRUE" = "x" &&
|
||||
test "x$HAVE_GOBJECT_TRUE" = "x"])
|
||||
],[
|
||||
AM_CONDITIONAL([HAVE_INTROSPECTION], [false])
|
||||
])
|
||||
|
||||
# check for gtk-doc
|
||||
m4_ifdef([GTK_DOC_CHECK], [
|
||||
GTK_DOC_CHECK([1.14],[--flavour no-tmpl])
|
||||
],[
|
||||
AM_CONDITIONAL([ENABLE_GTK_DOC], false)
|
||||
])
|
||||
|
||||
dnl Library versioning.
|
||||
MAX_PROC_NR=`cat $srcdir/src/MAX_PROC_NR`
|
||||
AC_SUBST(MAX_PROC_NR)
|
||||
@@ -997,8 +1279,8 @@ 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([appliance/libguestfs-make-fixed-appliance],
|
||||
[chmod +x appliance/libguestfs-make-fixed-appliance])
|
||||
AC_CONFIG_FILES([podwrapper.sh],
|
||||
[chmod +x podwrapper.sh])
|
||||
AC_CONFIG_FILES([run],
|
||||
@@ -1007,25 +1289,26 @@ AC_CONFIG_FILES([Makefile
|
||||
align/Makefile
|
||||
appliance/Makefile
|
||||
cat/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
|
||||
gobject/Makefile
|
||||
gobject/docs/Makefile
|
||||
gobject/docs/guestfs-docs.sgml
|
||||
haskell/Makefile
|
||||
inspector/Makefile
|
||||
java/Makefile
|
||||
java/examples/Makefile
|
||||
libguestfs.pc
|
||||
ocaml/META
|
||||
ocaml/Makefile
|
||||
ocaml/examples/Makefile
|
||||
@@ -1036,7 +1319,7 @@ AC_CONFIG_FILES([Makefile
|
||||
po-docs/Makefile
|
||||
po-docs/ja/Makefile
|
||||
po-docs/uk/Makefile
|
||||
po/Makefile.in
|
||||
po/Makefile
|
||||
python/Makefile
|
||||
python/examples/Makefile
|
||||
rescue/Makefile
|
||||
@@ -1046,7 +1329,10 @@ AC_CONFIG_FILES([Makefile
|
||||
ruby/examples/Makefile
|
||||
sparsify/Makefile
|
||||
src/Makefile
|
||||
src/libguestfs.pc
|
||||
sysprep/Makefile
|
||||
test-tool/Makefile
|
||||
tests/btrfs/Makefile
|
||||
tests/c-api/Makefile
|
||||
tests/data/Makefile
|
||||
tests/extra/Makefile
|
||||
@@ -1054,9 +1340,11 @@ AC_CONFIG_FILES([Makefile
|
||||
tests/luks/Makefile
|
||||
tests/lvm/Makefile
|
||||
tests/md/Makefile
|
||||
tests/ntfsclone/Makefile
|
||||
tests/protocol/Makefile
|
||||
tests/qemu/Makefile
|
||||
tests/regressions/Makefile
|
||||
tests/xml/Makefile
|
||||
tools/Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -1090,12 +1378,18 @@ 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 ......................... "
|
||||
echo -n "OCaml virt tools .................... "
|
||||
if test "x$HAVE_OCAML_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo "FUSE filesystem ..................... $enable_fuse"
|
||||
echo -n "gobject bindings .................... "
|
||||
if test "x$HAVE_GOBJECT_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo -n "gobject introspection ............... "
|
||||
if test "x$HAVE_INTROSPECTION_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo -n "GNU gettext for i18n ................ "
|
||||
if test "x$HAVE_GNU_GETTEXT_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo
|
||||
echo "If any optional component is configured 'no' when you expected 'yes'"
|
||||
echo "then you should check the preceeding messages."
|
||||
echo "then you should check the preceding messages."
|
||||
echo
|
||||
echo "Please report bugs back to the mailing list:"
|
||||
echo "http://www.redhat.com/mailman/listinfo/libguestfs"
|
||||
|
||||
@@ -5,25 +5,6 @@ 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
|
||||
from EL-5 here:
|
||||
http://pkgs.fedoraproject.org/gitweb/?p=libguestfs.git;a=shortlog;h=refs/heads/el5/master
|
||||
or the RHEL 5 source RPMs here:
|
||||
http://libguestfs.org/download/binaries/rhel5-packages/
|
||||
|
||||
febootstrap/
|
||||
[REMOVED]
|
||||
An experimental, non-working attempt to use febootstrap
|
||||
to install operating systems.
|
||||
|
||||
fedora-libguestfs.spec
|
||||
[REMOVED]
|
||||
This used to be a Fedora 10+ specfile. Please use the specfile
|
||||
from Fedora instead:
|
||||
http://pkgs.fedoraproject.org/gitweb/?p=libguestfs.git
|
||||
|
||||
guestfsd-in-wine.sh
|
||||
Run a Windows-compiled guestfsd under Wine. Read the
|
||||
instructions at the top of this file carefully.
|
||||
@@ -34,6 +15,13 @@ intro/ "Slides" for an intro to libguestfs. This is a short (10-15
|
||||
self-contained HTML page with a handful images that can be
|
||||
easily distributed before the talk.
|
||||
|
||||
make-check-on-installed.pl
|
||||
This Perl script allows you to run the test suite (ie. 'make
|
||||
check', 'make extra-tests' etc) on an installed RPM. This is
|
||||
useful for adding another layer of testing to packages before
|
||||
we release them. Note that a checked out copy of the source
|
||||
from git is required. Read the top of the file before using.
|
||||
|
||||
visualize-alignment/
|
||||
Tests for visualizing block device reads and writes and
|
||||
alignment using a patched qemu. See the README file in that
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash -
|
||||
# libguestfs autobuild script
|
||||
# Copyright (C) 2009-2011 Red Hat Inc.
|
||||
# Copyright (C) 2009-2012 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
|
||||
|
||||
177
contrib/make-check-on-installed.pl
Executable file
177
contrib/make-check-on-installed.pl
Executable file
@@ -0,0 +1,177 @@
|
||||
#!/usr/bin/perl -w
|
||||
# libguestfs
|
||||
# Copyright (C) 2009-2012 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 allows you to run the test suite ('make check' etc) on
|
||||
# an installed copy of libguestfs. Currently only RPM installs are
|
||||
# supported, but adding support for dpkg would be relatively
|
||||
# straightforward. It works by examining the installed packages, and
|
||||
# copying binaries (eg. '/usr/bin/guestfish') and libraries into the
|
||||
# correct place in the local directory.
|
||||
#
|
||||
# * You MUST have the full source tree unpacked locally. Either
|
||||
# use the same source tarball as the version you are testing, or
|
||||
# check it out from git and 'git-reset' to the right version tag.
|
||||
#
|
||||
# * You MUST do a successful local build from source before using
|
||||
# this script (ie. './autogen.sh && make').
|
||||
#
|
||||
# Run the script from the top builddir. Usually:
|
||||
#
|
||||
# ./contrib/make-check-on-installed.pl
|
||||
#
|
||||
# If the script runs successfully, then run the test suite as normal:
|
||||
#
|
||||
# make check
|
||||
# make extra-tests
|
||||
#
|
||||
# To switch back to running the test suite on the locally built
|
||||
# version, do:
|
||||
#
|
||||
# make clean && make
|
||||
|
||||
use strict;
|
||||
|
||||
die "wrong directory -- read the file before running\n" unless -f "BUGS";
|
||||
|
||||
my $cmd;
|
||||
|
||||
# Remove all libtool crappage.
|
||||
$cmd = "find -name 'lt-*' | grep -v '/tests/' | grep '/.libs/lt-' | xargs -r rm";
|
||||
system ($cmd) == 0 or die "$cmd: failed\n";
|
||||
|
||||
$cmd = "find -name 'lib*.so*' | grep -v '/tests/' | grep '/.libs/lib' | xargs -r rm";
|
||||
system ($cmd) == 0 or die "$cmd: failed\n";
|
||||
|
||||
# Map of installed file to local file. Key is a regexp.
|
||||
# Remember that ONLY libraries and binaries need to be copied.
|
||||
my %mapping = (
|
||||
'/bin/erl-guestfs$' => "erlang",
|
||||
'/bin/libguestfs-test-tool$' => "test-tool",
|
||||
'/bin/guestfish$' => "fish",
|
||||
'/bin/guestmount$' => "fuse",
|
||||
'/bin/virt-alignment-scan$' => "align",
|
||||
'/bin/virt-cat$' => "cat",
|
||||
'/bin/virt-copy-in$' => "fish",
|
||||
'/bin/virt-copy-out$' => "fish",
|
||||
'/bin/virt-df$' => "df",
|
||||
'/bin/virt-edit$' => "edit",
|
||||
'/bin/virt-filesystems$' => "cat",
|
||||
'/bin/virt-format$' => "format",
|
||||
'/bin/virt-inspector$' => "inspector",
|
||||
'/bin/virt-list-filesystems$' => "tools",
|
||||
'/bin/virt-list-partitions$' => "tools",
|
||||
'/bin/virt-ls$' => "cat",
|
||||
'/bin/virt-make-fs$' => "tools",
|
||||
'/bin/virt-rescue$' => "rescue",
|
||||
'/bin/virt-resize$' => "resize",
|
||||
'/bin/virt-sparsify$' => "sparsify",
|
||||
'/bin/virt-sysprep$' => "sysprep",
|
||||
'/bin/virt-tar$' => "tools",
|
||||
'/bin/virt-tar-in$' => "fish",
|
||||
'/bin/virt-tar-out$' => "fish",
|
||||
'/bin/virt-win-reg$' => "tools",
|
||||
|
||||
# Ignore this because the daemon is included in the appliance.
|
||||
'/sbin/guestfsd$' => "IGNORE",
|
||||
|
||||
'/erlang/lib/libguestfs-.*/ebin/guestfs\.beam$' => "erlang",
|
||||
|
||||
'/girepository-1\.0/Guestfs-1\.0\.typelib$' => "gobject",
|
||||
'/gir-1.0/Guestfs-1.0.gir$' => "gobject",
|
||||
|
||||
'/guestfs/supermin.d/.*' => "appliance/supermin.d",
|
||||
|
||||
'/java/libguestfs-.*\.jar$' => "java",
|
||||
|
||||
'/libguestfs\.so.*' => "src/.libs",
|
||||
'/libguestfs_jni\.so.*' => "java/.libs",
|
||||
'/libguestfs-gobject-1\.0\.so.*' => "gobject/.libs",
|
||||
|
||||
'/ocaml/.*\.cmi$' => "IGNORE",
|
||||
'/ocaml/.*\.cmo$' => "ocaml",
|
||||
'/ocaml/.*\.cmx$' => "ocaml",
|
||||
'/ocaml/.*\.cma$' => "ocaml",
|
||||
'/ocaml/.*\.cmxa$' => "ocaml",
|
||||
'/ocaml/.*\.a$' => "ocaml",
|
||||
'/ocaml/.*\.so$' => "ocaml",
|
||||
'/ocaml/.*\.so.owner$' => "IGNORE",
|
||||
'/ocaml/.*META$' => "IGNORE",
|
||||
'/ocaml/.*/guestfs\.mli$' => "IGNORE",
|
||||
'/ocaml/.*/guestfs\.ml$' => "IGNORE",
|
||||
|
||||
'/perl5/.*/Guestfs\.so$' => "perl/blib/arch/auto/Sys/Guestfs",
|
||||
'/perl5/.*/Guestfs.pm$' => "perl/blib/lib/Sys/Guestfs.pm",
|
||||
'/perl5/.*/Lib.pm$' => "perl/blib/lib/Sys/Guestfs/Lib.pm",
|
||||
|
||||
'/php/modules/guestfs_php\.so$' => "php/extension/modules",
|
||||
'/php/modules/guestfs_php\.so$' => "php/extension/.libs",
|
||||
|
||||
'/python.*/libguestfsmod\.so$' => "python/.libs",
|
||||
'/python.*/guestfs\.py' => "IGNORE",
|
||||
'/python.*/guestfs\.pyc$' => "python/guestfs.pyc",
|
||||
'/python.*/guestfs\.pyo$' => "python/guestfs.pyo",
|
||||
|
||||
'/ruby/.*/_guestfs\.so$' => "ruby/ext/guestfs",
|
||||
'/ruby/.*/guestfs\.rb$' => "IGNORE",
|
||||
|
||||
'/share/doc/' => "IGNORE",
|
||||
'/share/javadoc/' => "IGNORE",
|
||||
'/share/locale/' => "IGNORE",
|
||||
'/share/man/' => "IGNORE",
|
||||
|
||||
'^/etc/' => "IGNORE",
|
||||
'/systemd/' => "IGNORE",
|
||||
'/include/guestfs\.h$' => "IGNORE",
|
||||
'/include/guestfs-gobject\.h$' => "IGNORE",
|
||||
'/libguestfs\.pc$' => "IGNORE",
|
||||
);
|
||||
|
||||
# Get list of installed files.
|
||||
$cmd = 'rpm -ql $(rpm -qa | grep -i guestf | grep -v debug) | sort';
|
||||
my @files;
|
||||
open CMD, "$cmd |" or die "$cmd: $!";
|
||||
while (<CMD>) {
|
||||
chomp;
|
||||
push @files, $_;
|
||||
}
|
||||
close CMD;
|
||||
|
||||
# Now try to map (copy) installed files to the local equivalents.
|
||||
foreach my $file (@files) {
|
||||
my $match = 0;
|
||||
foreach my $regexp (keys %mapping) {
|
||||
if ($file =~ m/$regexp/) {
|
||||
my $dest = $mapping{$regexp};
|
||||
if ($dest ne "IGNORE") {
|
||||
# Make destination writable if it's a file.
|
||||
chmod 0644, "$dest" if -f "$dest" && ! -w "$dest";
|
||||
|
||||
# Copy file to destination.
|
||||
$cmd = "cp '$file' '$dest'";
|
||||
system ($cmd) == 0 or die "$cmd: failed\n";
|
||||
print "$file => $dest\n";
|
||||
}
|
||||
$match++;
|
||||
}
|
||||
}
|
||||
if ($match == 0) {
|
||||
if (! -d $file) {
|
||||
warn "WARNING: file '$file' is unmatched\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/ocamlrun /usr/bin/ocaml
|
||||
|
||||
(* Convert *.qtr (qemu block device trace) to Postscript.
|
||||
* Copyright (C) 2009-2010 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 Red Hat Inc.
|
||||
* By Richard W.M. Jones <rjones@redhat.com>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
28
daemon/9p.c
28
daemon/9p.c
@@ -40,11 +40,9 @@ static char *read_whole_file (const char *filename);
|
||||
char **
|
||||
do_list_9p (void)
|
||||
{
|
||||
char **r = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (r);
|
||||
|
||||
DIR *dir;
|
||||
int err = 0;
|
||||
|
||||
dir = opendir (BUS_PATH);
|
||||
if (!dir) {
|
||||
@@ -56,10 +54,10 @@ do_list_9p (void)
|
||||
* the virtio driver isn't loaded. Don't return an error
|
||||
* in this case, but return an empty list.
|
||||
*/
|
||||
if (add_string (&r, &size, &alloc, NULL) == -1)
|
||||
if (end_stringsbuf (&r) == -1)
|
||||
return NULL;
|
||||
|
||||
return r;
|
||||
return r.argv;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
@@ -80,7 +78,7 @@ do_list_9p (void)
|
||||
if (mount_tag == 0)
|
||||
continue;
|
||||
|
||||
if (add_string (&r, &size, &alloc, mount_tag) == -1) {
|
||||
if (add_string (&r, mount_tag) == -1) {
|
||||
free (mount_tag);
|
||||
closedir (dir);
|
||||
return NULL;
|
||||
@@ -93,7 +91,7 @@ do_list_9p (void)
|
||||
/* Check readdir didn't fail */
|
||||
if (errno != 0) {
|
||||
reply_with_perror ("readdir: /sys/block");
|
||||
free_stringslen (r, size);
|
||||
free_stringslen (r.argv, r.size);
|
||||
closedir (dir);
|
||||
return NULL;
|
||||
}
|
||||
@@ -101,19 +99,19 @@ do_list_9p (void)
|
||||
/* Close the directory handle */
|
||||
if (closedir (dir) == -1) {
|
||||
reply_with_perror ("closedir: /sys/block");
|
||||
free_stringslen (r, size);
|
||||
free_stringslen (r.argv, r.size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Sort the tags. Note that r might be NULL if there are no tags. */
|
||||
if (r != NULL)
|
||||
sort_strings (r, size);
|
||||
/* Sort the tags. */
|
||||
if (r.size > 0)
|
||||
sort_strings (r.argv, r.size);
|
||||
|
||||
/* NULL terminate the list */
|
||||
if (add_string (&r, &size, &alloc, NULL) == -1)
|
||||
if (end_stringsbuf (&r) == -1)
|
||||
return NULL;
|
||||
|
||||
return r;
|
||||
return r.argv;
|
||||
}
|
||||
|
||||
/* Read whole file into dynamically allocated array. If there is an
|
||||
@@ -127,7 +125,7 @@ read_whole_file (const char *filename)
|
||||
size_t alloc = 0, size = 0;
|
||||
int fd;
|
||||
|
||||
fd = open (filename, O_RDONLY);
|
||||
fd = open (filename, O_RDONLY|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
perror (filename);
|
||||
return NULL;
|
||||
@@ -139,6 +137,7 @@ read_whole_file (const char *filename)
|
||||
if (r2 == NULL) {
|
||||
perror ("realloc");
|
||||
free (r);
|
||||
close (fd);
|
||||
return NULL;
|
||||
}
|
||||
r = r2;
|
||||
@@ -150,6 +149,7 @@ read_whole_file (const char *filename)
|
||||
if (n == -1) {
|
||||
perror (filename);
|
||||
free (r);
|
||||
close (fd);
|
||||
return NULL;
|
||||
}
|
||||
if (n == 0)
|
||||
|
||||
@@ -123,7 +123,10 @@ guestfsd_SOURCES = \
|
||||
htonl.c \
|
||||
initrd.c \
|
||||
inotify.c \
|
||||
internal.c \
|
||||
is.c \
|
||||
isoinfo.c \
|
||||
labels.c \
|
||||
link.c \
|
||||
ls.c \
|
||||
luks.c \
|
||||
@@ -136,6 +139,7 @@ guestfsd_SOURCES = \
|
||||
mount.c \
|
||||
names.c \
|
||||
ntfs.c \
|
||||
ntfsclone.c \
|
||||
optgroups.c \
|
||||
optgroups.h \
|
||||
parted.c \
|
||||
|
||||
192
daemon/augeas.c
192
daemon/augeas.c
@@ -38,6 +38,17 @@
|
||||
*/
|
||||
static augeas *aug = NULL;
|
||||
|
||||
/* Clean up the augeas handle on daemon exit. */
|
||||
static void aug_finalize (void) __attribute__((destructor));
|
||||
static void
|
||||
aug_finalize (void)
|
||||
{
|
||||
if (aug) {
|
||||
aug_close (aug);
|
||||
aug = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define NEED_AUG(errcode) \
|
||||
do { \
|
||||
if (!aug) { \
|
||||
@@ -52,19 +63,11 @@ optgroup_augeas_available (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#else /* !HAVE_AUGEAS */
|
||||
int
|
||||
optgroup_augeas_available (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We need to rewrite the root path so it is based at /sysroot. */
|
||||
int
|
||||
do_aug_init (const char *root, int flags)
|
||||
{
|
||||
#ifdef HAVE_AUGEAS
|
||||
char *buf;
|
||||
|
||||
if (aug) {
|
||||
@@ -87,24 +90,17 @@ do_aug_init (const char *root, int flags)
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_close (void)
|
||||
{
|
||||
#ifdef HAVE_AUGEAS
|
||||
NEED_AUG(-1);
|
||||
|
||||
aug_close (aug);
|
||||
aug = NULL;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@@ -122,7 +118,8 @@ do_aug_defvar (const char *name, const char *expr)
|
||||
}
|
||||
return r;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
reply_with_error ("function not available");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -130,27 +127,36 @@ guestfs_int_int_bool *
|
||||
do_aug_defnode (const char *name, const char *expr, const char *val)
|
||||
{
|
||||
#ifdef HAVE_AUG_DEFNODE
|
||||
static guestfs_int_int_bool r;
|
||||
int created;
|
||||
guestfs_int_int_bool *r;
|
||||
int i, created;
|
||||
|
||||
NEED_AUG (NULL);
|
||||
|
||||
r.i = aug_defnode (aug, name, expr, val, &created);
|
||||
if (r.i == -1) {
|
||||
i = aug_defnode (aug, name, expr, val, &created);
|
||||
if (i == -1) {
|
||||
reply_with_error ("Augeas defnode failed");
|
||||
return NULL;
|
||||
}
|
||||
r.b = created;
|
||||
return &r;
|
||||
|
||||
r = malloc (sizeof *r);
|
||||
if (r == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r->i = i;
|
||||
r->b = created;
|
||||
|
||||
return r;
|
||||
#else
|
||||
NOT_AVAILABLE (NULL);
|
||||
reply_with_error ("function not available");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
char *
|
||||
do_aug_get (const char *path)
|
||||
{
|
||||
#ifdef HAVE_AUGEAS
|
||||
const char *value = NULL;
|
||||
char *v;
|
||||
int r;
|
||||
@@ -184,15 +190,11 @@ do_aug_get (const char *path)
|
||||
}
|
||||
|
||||
return v; /* Caller frees. */
|
||||
#else
|
||||
NOT_AVAILABLE (NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_set (const char *path, const char *val)
|
||||
{
|
||||
#ifdef HAVE_AUGEAS
|
||||
int r;
|
||||
|
||||
NEED_AUG (-1);
|
||||
@@ -204,15 +206,11 @@ do_aug_set (const char *path, const char *val)
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_clear (const char *path)
|
||||
{
|
||||
#ifdef HAVE_AUGEAS
|
||||
int r;
|
||||
|
||||
NEED_AUG (-1);
|
||||
@@ -224,15 +222,11 @@ do_aug_clear (const char *path)
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_insert (const char *path, const char *label, int before)
|
||||
{
|
||||
#ifdef HAVE_AUGEAS
|
||||
int r;
|
||||
|
||||
NEED_AUG (-1);
|
||||
@@ -244,15 +238,11 @@ do_aug_insert (const char *path, const char *label, int before)
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_rm (const char *path)
|
||||
{
|
||||
#ifdef HAVE_AUGEAS
|
||||
int r;
|
||||
|
||||
NEED_AUG (-1);
|
||||
@@ -264,15 +254,11 @@ do_aug_rm (const char *path)
|
||||
}
|
||||
|
||||
return r;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_mv (const char *src, const char *dest)
|
||||
{
|
||||
#ifdef HAVE_AUGEAS
|
||||
int r;
|
||||
|
||||
NEED_AUG (-1);
|
||||
@@ -284,15 +270,11 @@ do_aug_mv (const char *src, const char *dest)
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
char **
|
||||
do_aug_match (const char *path)
|
||||
{
|
||||
#ifdef HAVE_AUGEAS
|
||||
char **matches = NULL;
|
||||
void *vp;
|
||||
int r;
|
||||
@@ -318,15 +300,11 @@ do_aug_match (const char *path)
|
||||
matches[r] = NULL;
|
||||
|
||||
return matches; /* Caller frees. */
|
||||
#else
|
||||
NOT_AVAILABLE (NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_save (void)
|
||||
{
|
||||
#ifdef HAVE_AUGEAS
|
||||
NEED_AUG (-1);
|
||||
|
||||
if (aug_save (aug) == -1) {
|
||||
@@ -335,9 +313,6 @@ do_aug_save (void)
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@@ -353,7 +328,8 @@ do_aug_load (void)
|
||||
|
||||
return 0;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
reply_with_error ("function not available");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -361,10 +337,9 @@ do_aug_load (void)
|
||||
char **
|
||||
do_aug_ls (const char *path)
|
||||
{
|
||||
#ifdef HAVE_AUGEAS
|
||||
char **matches;
|
||||
char *buf;
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
NEED_AUG (NULL);
|
||||
|
||||
@@ -400,7 +375,102 @@ do_aug_ls (const char *path)
|
||||
|
||||
sort_strings (matches, count_strings ((void *) matches));
|
||||
return matches; /* Caller frees. */
|
||||
#else
|
||||
NOT_AVAILABLE (NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* !HAVE_AUGEAS */
|
||||
|
||||
/* Note that the wrapper code (daemon/stubs.c) ensures that the
|
||||
* functions below are never called because optgroup_augeas_available
|
||||
* returns false.
|
||||
*/
|
||||
int
|
||||
optgroup_augeas_available (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_init (const char *root, int flags)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_close (void)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_defvar (const char *name, const char *expr)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
guestfs_int_int_bool *
|
||||
do_aug_defnode (const char *name, const char *expr, const char *val)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
char *
|
||||
do_aug_get (const char *path)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_set (const char *path, const char *val)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_clear (const char *path)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_insert (const char *path, const char *label, int before)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_rm (const char *path)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_mv (const char *src, const char *dest)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
char **
|
||||
do_aug_match (const char *path)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_save (void)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_aug_load (void)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
char **
|
||||
do_aug_ls (const char *path)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -58,16 +58,15 @@ char **
|
||||
do_available_all_groups (void)
|
||||
{
|
||||
size_t i;
|
||||
char **groups = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (groups);
|
||||
|
||||
for (i = 0; optgroups[i].group != NULL; ++i) {
|
||||
if (add_string (&groups, &size, &alloc, optgroups[i].group) == -1)
|
||||
if (add_string (&groups, optgroups[i].group) == -1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (add_string (&groups, &size, &alloc, NULL) == -1)
|
||||
if (end_stringsbuf (&groups) == -1)
|
||||
return NULL;
|
||||
|
||||
return groups; /* caller frees */
|
||||
return groups.argv; /* caller frees */
|
||||
}
|
||||
|
||||
150
daemon/blkid.c
150
daemon/blkid.c
@@ -84,53 +84,67 @@ do_vfs_uuid (const char *device)
|
||||
return get_blkid_tag (device, "UUID");
|
||||
}
|
||||
|
||||
/* RHEL5 blkid doesn't have the -p(partition info) option and the
|
||||
/* RHEL5 blkid doesn't have the -p (low-level probing) option and the
|
||||
* -i(I/O limits) option so we must test for these options the first
|
||||
* time the function is called.
|
||||
*
|
||||
* Debian 6 has -p but not -i.
|
||||
*/
|
||||
static int
|
||||
test_blkid_p_opt(void)
|
||||
test_blkid_p_i_opt (void)
|
||||
{
|
||||
static int result;
|
||||
char *err = NULL;
|
||||
int r;
|
||||
char *err;
|
||||
|
||||
int r = commandr(NULL, &err, "blkid", "-p", "/dev/null", NULL);
|
||||
r = commandr (NULL, &err, "blkid", "-p", "/dev/null", NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error("could not run 'blkid' command: %s", err);
|
||||
free(err);
|
||||
/* This means we couldn't run the blkid command at all. */
|
||||
command_failed:
|
||||
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;
|
||||
if (strstr (err, "invalid option --")) {
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
free (err);
|
||||
|
||||
r = commandr (NULL, &err, "blkid", "-i", NULL);
|
||||
if (r == -1)
|
||||
goto command_failed;
|
||||
|
||||
if (strstr (err, "invalid option --")) {
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
free (err);
|
||||
|
||||
/* We have both options. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char **
|
||||
blkid_with_p_opt(const char *device)
|
||||
blkid_with_p_i_opt (const char *device)
|
||||
{
|
||||
size_t i;
|
||||
int r;
|
||||
char *out = NULL, *err = NULL;
|
||||
char **lines = NULL;
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (ret);
|
||||
|
||||
r = command(&out, &err, "blkid", "-c", "/dev/null",
|
||||
r = command (&out, &err, "blkid", "-c", "/dev/null",
|
||||
"-p", "-i", "-o", "export", device, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error("%s", err);
|
||||
reply_with_error ("%s", err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Split the command output into lines */
|
||||
lines = split_lines(out);
|
||||
if (lines == NULL) {
|
||||
reply_with_perror("malloc");
|
||||
lines = split_lines (out);
|
||||
if (lines == NULL)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Parse the output of blkid -p -i -o export:
|
||||
* UUID=b6d83437-c6b4-4bf0-8381-ef3fc3578590
|
||||
@@ -147,80 +161,90 @@ blkid_with_p_opt(const char *device)
|
||||
* PART_ENTRY_SIZE=104857600
|
||||
* PART_ENTRY_DISK=8:0
|
||||
*/
|
||||
for (char **i = lines; *i != NULL; i++) {
|
||||
char *line = *i;
|
||||
for (i = 0; lines[i] != NULL; ++i) {
|
||||
char *line = lines[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, '=');
|
||||
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;
|
||||
if (add_string (&ret, line) == -1 ||
|
||||
add_string (&ret, eq) == -1) goto error;
|
||||
} else {
|
||||
fprintf(stderr, "blkid: unexpected blkid output ignored: %s", line);
|
||||
fprintf (stderr, "blkid: unexpected blkid output ignored: %s", line);
|
||||
}
|
||||
}
|
||||
|
||||
if (add_string(&ret, &size, &alloc, NULL) == -1) goto error;
|
||||
if (end_stringsbuf (&ret) == -1) goto error;
|
||||
|
||||
free(out);
|
||||
free(err);
|
||||
free(lines);
|
||||
free (out);
|
||||
free (err);
|
||||
free_strings (lines);
|
||||
|
||||
return ret;
|
||||
return ret.argv;
|
||||
|
||||
error:
|
||||
free(out);
|
||||
free(err);
|
||||
if (lines) free(lines);
|
||||
if (ret) free_strings(ret);
|
||||
free (out);
|
||||
free (err);
|
||||
if (lines)
|
||||
free_strings (lines);
|
||||
if (ret.argv)
|
||||
free_strings (ret.argv);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char **
|
||||
blkid_without_p_opt(const char *device)
|
||||
blkid_without_p_i_opt(const char *device)
|
||||
{
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
char *s;
|
||||
DECLARE_STRINGSBUF (ret);
|
||||
|
||||
if (add_string(&ret, &size, &alloc, "TYPE") == -1) goto error;
|
||||
if (add_string(&ret, &size, &alloc, get_blkid_tag(device, "TYPE")) == -1)
|
||||
if (add_string (&ret, "TYPE") == -1) goto error;
|
||||
s = get_blkid_tag (device, "TYPE");
|
||||
if (s == NULL) goto error;
|
||||
if (add_string (&ret, s) == -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;
|
||||
if (add_string (&ret, "LABEL") == -1) goto error;
|
||||
s = get_blkid_tag (device, "LABEL");
|
||||
if (s == NULL) goto error;
|
||||
if (add_string (&ret, s) == -1)
|
||||
goto error;
|
||||
|
||||
if (add_string (&ret, "UUID") == -1) goto error;
|
||||
s = get_blkid_tag (device, "UUID");
|
||||
if (s == NULL) goto error;
|
||||
if (add_string (&ret, s) == -1)
|
||||
goto error;
|
||||
|
||||
if (end_stringsbuf (&ret) == -1) goto error;
|
||||
|
||||
return ret.argv;
|
||||
error:
|
||||
if (ret) free_strings(ret);
|
||||
if (ret.argv)
|
||||
free_strings (ret.argv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char **
|
||||
do_blkid(const char *device)
|
||||
do_blkid (const char *device)
|
||||
{
|
||||
int r;
|
||||
char *out = NULL, *err = NULL;
|
||||
char **lines = NULL;
|
||||
static int blkid_has_p_i_opt = -1;
|
||||
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
int blkid_has_p_opt;
|
||||
if (blkid_has_p_i_opt == -1) {
|
||||
blkid_has_p_i_opt = test_blkid_p_i_opt ();
|
||||
if (blkid_has_p_i_opt == -1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((blkid_has_p_opt = test_blkid_p_opt()) == -1)
|
||||
return NULL;
|
||||
else if (blkid_has_p_opt)
|
||||
return blkid_with_p_opt(device);
|
||||
if (blkid_has_p_i_opt)
|
||||
return blkid_with_p_i_opt (device);
|
||||
else
|
||||
return blkid_without_p_opt(device);
|
||||
return blkid_without_p_i_opt (device);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,20 @@ call_blockdev (const char *device, const char *switc, int extraarg, int prints)
|
||||
};
|
||||
char buf[64];
|
||||
|
||||
/* When you call close on any block device, udev kicks off a rule
|
||||
* which runs blkid to reexamine the device. We need to wait for
|
||||
* this rule to finish running (from a previous operation) since it
|
||||
* holds the device open and can cause other operations to fail,
|
||||
* notably BLKRRPART.
|
||||
*
|
||||
* This is particularly a problem where we have just written to a
|
||||
* device (eg. zeroing it) and immediately call blockdev --rereadpt.
|
||||
*
|
||||
* Therefore, wait for udev to finish all outstanding events before
|
||||
* performing any blockdev command.
|
||||
*/
|
||||
udev_settle ();
|
||||
|
||||
if (extraarg > 0) {
|
||||
snprintf (buf, sizeof buf, "%d", extraarg);
|
||||
argv[2] = buf;
|
||||
|
||||
522
daemon/btrfs.c
522
daemon/btrfs.c
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2011 Red Hat Inc.
|
||||
* Copyright (C) 2011-2012 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -28,8 +28,6 @@
|
||||
#include "actions.h"
|
||||
#include "optgroups.h"
|
||||
|
||||
#define MAX_ARGS 64
|
||||
|
||||
int
|
||||
optgroup_btrfs_available (void)
|
||||
{
|
||||
@@ -40,6 +38,7 @@ optgroup_btrfs_available (void)
|
||||
int
|
||||
do_btrfs_filesystem_resize (const char *filesystem, int64_t size)
|
||||
{
|
||||
const size_t MAX_ARGS = 64;
|
||||
char *buf;
|
||||
char *err;
|
||||
int r;
|
||||
@@ -84,3 +83,520 @@ do_btrfs_filesystem_resize (const char *filesystem, int64_t size)
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_mkfs_btrfs (char *const *devices,
|
||||
int64_t allocstart, int64_t bytecount, const char *datatype,
|
||||
int leafsize, const char *label, const char *metadata,
|
||||
int nodesize, int sectorsize)
|
||||
{
|
||||
size_t nr_devices = count_strings (devices);
|
||||
|
||||
if (nr_devices == 0) {
|
||||
reply_with_error ("list of devices must be non-empty");
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t MAX_ARGS = nr_devices + 64;
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0, j;
|
||||
int r;
|
||||
char *err;
|
||||
char allocstart_s[64];
|
||||
char bytecount_s[64];
|
||||
char leafsize_s[64];
|
||||
char nodesize_s[64];
|
||||
char sectorsize_s[64];
|
||||
|
||||
ADD_ARG (argv, i, "mkfs.btrfs");
|
||||
|
||||
/* Optional arguments. */
|
||||
if (optargs_bitmask & GUESTFS_MKFS_BTRFS_ALLOCSTART_BITMASK) {
|
||||
if (allocstart < 0) {
|
||||
reply_with_error ("allocstart must be >= 0");
|
||||
return -1;
|
||||
}
|
||||
snprintf (allocstart_s, sizeof allocstart_s, "%" PRIi64, allocstart);
|
||||
ADD_ARG (argv, i, "--alloc-start");
|
||||
ADD_ARG (argv, i, allocstart_s);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MKFS_BTRFS_BYTECOUNT_BITMASK) {
|
||||
if (bytecount <= 0) { /* actually the minimum is 256MB */
|
||||
reply_with_error ("bytecount must be > 0");
|
||||
return -1;
|
||||
}
|
||||
snprintf (bytecount_s, sizeof bytecount_s, "%" PRIi64, bytecount);
|
||||
ADD_ARG (argv, i, "--byte-count");
|
||||
ADD_ARG (argv, i, bytecount_s);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MKFS_BTRFS_DATATYPE_BITMASK) {
|
||||
if (STRNEQ (datatype, "raid0") && STRNEQ (datatype, "raid1") &&
|
||||
STRNEQ (datatype, "raid10") && STRNEQ (datatype, "single")) {
|
||||
reply_with_error ("datatype not one of the allowed values");
|
||||
return -1;
|
||||
}
|
||||
ADD_ARG (argv, i, "--data");
|
||||
ADD_ARG (argv, i, datatype);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MKFS_BTRFS_LEAFSIZE_BITMASK) {
|
||||
if (!is_power_of_2 (leafsize) || leafsize <= 0) {
|
||||
reply_with_error ("leafsize must be > 0 and a power of two");
|
||||
return -1;
|
||||
}
|
||||
snprintf (leafsize_s, sizeof leafsize_s, "%d", leafsize);
|
||||
ADD_ARG (argv, i, "--leafsize");
|
||||
ADD_ARG (argv, i, leafsize_s);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MKFS_BTRFS_LABEL_BITMASK) {
|
||||
ADD_ARG (argv, i, "--label");
|
||||
ADD_ARG (argv, i, label);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MKFS_BTRFS_METADATA_BITMASK) {
|
||||
if (STRNEQ (metadata, "raid0") && STRNEQ (metadata, "raid1") &&
|
||||
STRNEQ (metadata, "raid10") && STRNEQ (metadata, "single")) {
|
||||
reply_with_error ("metadata not one of the allowed values");
|
||||
return -1;
|
||||
}
|
||||
ADD_ARG (argv, i, "--metadata");
|
||||
ADD_ARG (argv, i, metadata);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MKFS_BTRFS_NODESIZE_BITMASK) {
|
||||
if (!is_power_of_2 (nodesize) || nodesize <= 0) {
|
||||
reply_with_error ("nodesize must be > 0 and a power of two");
|
||||
return -1;
|
||||
}
|
||||
snprintf (nodesize_s, sizeof nodesize_s, "%d", nodesize);
|
||||
ADD_ARG (argv, i, "--nodesize");
|
||||
ADD_ARG (argv, i, nodesize_s);
|
||||
}
|
||||
|
||||
if (optargs_bitmask & GUESTFS_MKFS_BTRFS_SECTORSIZE_BITMASK) {
|
||||
if (!is_power_of_2 (sectorsize) || sectorsize <= 0) {
|
||||
reply_with_error ("sectorsize must be > 0 and a power of two");
|
||||
return -1;
|
||||
}
|
||||
snprintf (sectorsize_s, sizeof sectorsize_s, "%d", sectorsize);
|
||||
ADD_ARG (argv, i, "--sectorsize");
|
||||
ADD_ARG (argv, i, sectorsize_s);
|
||||
}
|
||||
|
||||
for (j = 0; j < nr_devices; ++j)
|
||||
ADD_ARG (argv, i, devices[j]);
|
||||
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s", devices[0], err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_btrfs_subvolume_snapshot (const char *source, const char *dest)
|
||||
{
|
||||
const size_t MAX_ARGS = 64;
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0;
|
||||
char *source_buf, *dest_buf;
|
||||
char *err;
|
||||
int r;
|
||||
|
||||
source_buf = sysroot_path (source);
|
||||
if (source_buf == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
dest_buf = sysroot_path (dest);
|
||||
if (dest_buf == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
free (source_buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ADD_ARG (argv, i, "btrfs");
|
||||
ADD_ARG (argv, i, "subvolume");
|
||||
ADD_ARG (argv, i, "snapshot");
|
||||
ADD_ARG (argv, i, source_buf);
|
||||
ADD_ARG (argv, i, dest_buf);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
free (source_buf);
|
||||
free (dest_buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s: %s", source, dest, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_btrfs_subvolume_delete (const char *subvolume)
|
||||
{
|
||||
const size_t MAX_ARGS = 64;
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0;
|
||||
char *subvolume_buf;
|
||||
char *err;
|
||||
int r;
|
||||
|
||||
subvolume_buf = sysroot_path (subvolume);
|
||||
if (subvolume_buf == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ADD_ARG (argv, i, "btrfs");
|
||||
ADD_ARG (argv, i, "subvolume");
|
||||
ADD_ARG (argv, i, "delete");
|
||||
ADD_ARG (argv, i, subvolume_buf);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
free (subvolume_buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s", subvolume, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_btrfs_subvolume_create (const char *dest)
|
||||
{
|
||||
const size_t MAX_ARGS = 64;
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0;
|
||||
char *dest_buf;
|
||||
char *err;
|
||||
int r;
|
||||
|
||||
dest_buf = sysroot_path (dest);
|
||||
if (dest_buf == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ADD_ARG (argv, i, "btrfs");
|
||||
ADD_ARG (argv, i, "subvolume");
|
||||
ADD_ARG (argv, i, "create");
|
||||
ADD_ARG (argv, i, dest_buf);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
free (dest_buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s", dest, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
guestfs_int_btrfssubvolume_list *
|
||||
do_btrfs_subvolume_list (const char *fs)
|
||||
{
|
||||
const size_t MAX_ARGS = 64;
|
||||
guestfs_int_btrfssubvolume_list *ret;
|
||||
char *fs_buf;
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0;
|
||||
char *out, *err, **lines, *pos;
|
||||
size_t nr_subvolumes;
|
||||
int r;
|
||||
|
||||
fs_buf = sysroot_path (fs);
|
||||
if (fs_buf == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ADD_ARG (argv, i, "btrfs");
|
||||
ADD_ARG (argv, i, "subvolume");
|
||||
ADD_ARG (argv, i, "list");
|
||||
ADD_ARG (argv, i, fs_buf);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (&out, &err, argv);
|
||||
free (fs_buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s", fs, err);
|
||||
free (err);
|
||||
return NULL;
|
||||
}
|
||||
free (err);
|
||||
|
||||
lines = split_lines (out);
|
||||
free (out);
|
||||
if (!lines)
|
||||
return NULL;
|
||||
|
||||
/* Output is:
|
||||
*
|
||||
* ID 256 top level 5 path test1
|
||||
* ID 257 top level 5 path dir/test2
|
||||
* ID 258 top level 5 path test3
|
||||
*
|
||||
* "ID <n>" is the subvolume ID. "top level <n>" is the top level
|
||||
* subvolume ID. "path <str>" is the subvolume path, relative to
|
||||
* the top of the filesystem.
|
||||
*/
|
||||
nr_subvolumes = count_strings (lines);
|
||||
|
||||
ret = malloc (sizeof *ret);
|
||||
if (!ret) {
|
||||
reply_with_perror ("malloc");
|
||||
free_stringslen (lines, nr_subvolumes);
|
||||
return NULL;
|
||||
}
|
||||
ret->guestfs_int_btrfssubvolume_list_len = nr_subvolumes;
|
||||
ret->guestfs_int_btrfssubvolume_list_val =
|
||||
calloc (nr_subvolumes, sizeof (struct guestfs_int_btrfssubvolume));
|
||||
if (ret->guestfs_int_btrfssubvolume_list_val == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
free (ret);
|
||||
free_stringslen (lines, nr_subvolumes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_subvolumes; ++i) {
|
||||
/* To avoid allocations, reuse the 'line' buffer to store the
|
||||
* path. Thus we don't need to free 'line', since it will be
|
||||
* freed by the calling (XDR) code.
|
||||
*/
|
||||
char *line = lines[i];
|
||||
|
||||
if (sscanf (line, "ID %" SCNu64 " top level %" SCNu64 " path ",
|
||||
&ret->guestfs_int_btrfssubvolume_list_val[i].btrfssubvolume_id,
|
||||
&ret->guestfs_int_btrfssubvolume_list_val[i].btrfssubvolume_top_level_id) != 2) {
|
||||
unexpected_output:
|
||||
reply_with_error ("unexpected output from 'btrfs subvolume list' command: %s", line);
|
||||
free_stringslen (lines, nr_subvolumes);
|
||||
free (ret->guestfs_int_btrfssubvolume_list_val);
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pos = strstr (line, " path ");
|
||||
if (pos == NULL)
|
||||
goto unexpected_output;
|
||||
pos += 6;
|
||||
|
||||
memmove (line, pos, strlen (pos) + 1);
|
||||
ret->guestfs_int_btrfssubvolume_list_val[i].btrfssubvolume_path = line;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
do_btrfs_subvolume_set_default (int64_t id, const char *fs)
|
||||
{
|
||||
const size_t MAX_ARGS = 64;
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0;
|
||||
char *fs_buf;
|
||||
char buf[64];
|
||||
char *err;
|
||||
int r;
|
||||
|
||||
snprintf (buf, sizeof buf, "%" PRIi64, id);
|
||||
|
||||
fs_buf = sysroot_path (fs);
|
||||
if (fs_buf == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ADD_ARG (argv, i, "btrfs");
|
||||
ADD_ARG (argv, i, "subvolume");
|
||||
ADD_ARG (argv, i, "set-default");
|
||||
ADD_ARG (argv, i, buf);
|
||||
ADD_ARG (argv, i, fs_buf);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
free (fs_buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s", fs, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_btrfs_filesystem_sync (const char *fs)
|
||||
{
|
||||
const size_t MAX_ARGS = 64;
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0;
|
||||
char *fs_buf;
|
||||
char *err;
|
||||
int r;
|
||||
|
||||
fs_buf = sysroot_path (fs);
|
||||
if (fs_buf == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ADD_ARG (argv, i, "btrfs");
|
||||
ADD_ARG (argv, i, "filesystem");
|
||||
ADD_ARG (argv, i, "sync");
|
||||
ADD_ARG (argv, i, fs_buf);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
free (fs_buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s", fs, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_btrfs_filesystem_balance (const char *fs)
|
||||
{
|
||||
const size_t MAX_ARGS = 64;
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0;
|
||||
char *fs_buf;
|
||||
char *err;
|
||||
int r;
|
||||
|
||||
fs_buf = sysroot_path (fs);
|
||||
if (fs_buf == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ADD_ARG (argv, i, "btrfs");
|
||||
ADD_ARG (argv, i, "filesystem");
|
||||
ADD_ARG (argv, i, "balance");
|
||||
ADD_ARG (argv, i, fs_buf);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
free (fs_buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s", fs, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_btrfs_device_add (char *const *devices, const char *fs)
|
||||
{
|
||||
size_t nr_devices = count_strings (devices);
|
||||
|
||||
if (nr_devices == 0)
|
||||
return 0;
|
||||
|
||||
size_t MAX_ARGS = nr_devices + 8;
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0, j;
|
||||
char *fs_buf;
|
||||
char *err;
|
||||
int r;
|
||||
|
||||
fs_buf = sysroot_path (fs);
|
||||
if (fs_buf == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ADD_ARG (argv, i, "btrfs");
|
||||
ADD_ARG (argv, i, "device");
|
||||
ADD_ARG (argv, i, "add");
|
||||
|
||||
for (j = 0; j < nr_devices; ++j)
|
||||
ADD_ARG (argv, i, devices[j]);
|
||||
|
||||
ADD_ARG (argv, i, fs_buf);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
free (fs_buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s", fs, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_btrfs_device_delete (char *const *devices, const char *fs)
|
||||
{
|
||||
size_t nr_devices = count_strings (devices);
|
||||
|
||||
if (nr_devices == 0)
|
||||
return 0;
|
||||
|
||||
size_t MAX_ARGS = nr_devices + 8;
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0, j;
|
||||
char *fs_buf;
|
||||
char *err;
|
||||
int r;
|
||||
|
||||
fs_buf = sysroot_path (fs);
|
||||
if (fs_buf == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ADD_ARG (argv, i, "btrfs");
|
||||
ADD_ARG (argv, i, "device");
|
||||
ADD_ARG (argv, i, "delete");
|
||||
|
||||
for (j = 0; j < nr_devices; ++j)
|
||||
ADD_ARG (argv, i, devices[j]);
|
||||
|
||||
ADD_ARG (argv, i, fs_buf);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
free (fs_buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s", fs, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 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
|
||||
@@ -58,7 +58,7 @@ checksum (const char *csumtype, int fd)
|
||||
const char *program;
|
||||
char *out, *err;
|
||||
int flags, r;
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
program = program_of_csum (csumtype);
|
||||
if (program == NULL) {
|
||||
@@ -95,7 +95,7 @@ do_checksum (const char *csumtype, const char *path)
|
||||
int fd;
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_RDONLY);
|
||||
fd = open (path, O_RDONLY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
@@ -111,7 +111,7 @@ do_checksum_device (const char *csumtype, const char *device)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open (device, O_RDONLY);
|
||||
fd = open (device, O_RDONLY|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("%s", device);
|
||||
return NULL;
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
#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
|
||||
#define DEST_FILE_FLAGS O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666
|
||||
#define DEST_DEVICE_FLAGS O_WRONLY|O_CLOEXEC, 0
|
||||
|
||||
/* NB: We cheat slightly by assuming that optargs_bitmask is
|
||||
* compatible for all four of the calls. This is true provided they
|
||||
@@ -78,7 +78,7 @@ copy (const char *src, const char *src_display,
|
||||
size = -1;
|
||||
|
||||
/* Open source and destination. */
|
||||
src_fd = open (src, O_RDONLY);
|
||||
src_fd = open (src, O_RDONLY|O_CLOEXEC);
|
||||
if (src_fd == -1) {
|
||||
reply_with_perror ("%s", src_display);
|
||||
return -1;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -30,6 +30,10 @@
|
||||
|
||||
#include "guestfs_protocol.h"
|
||||
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
/*-- in guestfsd.c --*/
|
||||
extern int verbose;
|
||||
|
||||
@@ -47,14 +51,35 @@ 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);
|
||||
extern void free_strings (char **argv);
|
||||
extern void free_stringslen (char **argv, int len);
|
||||
/* Growable strings buffer. */
|
||||
struct stringsbuf {
|
||||
char **argv;
|
||||
size_t size;
|
||||
size_t alloc;
|
||||
};
|
||||
#define DECLARE_STRINGSBUF(v) \
|
||||
struct stringsbuf (v) = { .argv = NULL, .size = 0, .alloc = 0 }
|
||||
|
||||
extern int is_power_of_2 (unsigned long v);
|
||||
/* Append a string to the strings buffer.
|
||||
*
|
||||
* add_string_nodup: don't copy the string.
|
||||
* add_string: copy the string.
|
||||
* end_stringsbuf: NULL-terminate the buffer.
|
||||
*
|
||||
* All functions may fail. If these functions return -1, then
|
||||
* reply_with_* has been called, the strings have been freed and the
|
||||
* buffer should no longer be used.
|
||||
*/
|
||||
extern int add_string_nodup (struct stringsbuf *sb, char *str);
|
||||
extern int add_string (struct stringsbuf *sb, const char *str);
|
||||
extern int end_stringsbuf (struct stringsbuf *sb);
|
||||
|
||||
extern size_t count_strings (char *const *argv);
|
||||
extern void sort_strings (char **argv, size_t len);
|
||||
extern void free_strings (char **argv);
|
||||
extern void free_stringslen (char **argv, size_t len);
|
||||
|
||||
extern char **split_lines (char *str);
|
||||
|
||||
#define command(out,err,name,...) commandf((out),(err),0,(name),__VA_ARGS__)
|
||||
#define commandr(out,err,name,...) commandrf((out),(err),0,(name),__VA_ARGS__)
|
||||
@@ -74,7 +99,7 @@ extern int commandvf (char **stdoutput, char **stderror, int flags,
|
||||
extern int commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
char const* const *argv);
|
||||
|
||||
extern char **split_lines (char *str);
|
||||
extern int is_power_of_2 (unsigned long v);
|
||||
|
||||
extern void trim (char *str);
|
||||
|
||||
@@ -111,6 +136,7 @@ extern uint64_t optargs_bitmask;
|
||||
|
||||
/*-- in mount.c --*/
|
||||
extern int is_root_mounted (void);
|
||||
extern int is_device_mounted (const char *device);
|
||||
|
||||
/*-- in stubs.c (auto-generated) --*/
|
||||
extern void dispatch_incoming_message (XDR *);
|
||||
@@ -132,6 +158,9 @@ extern int sync_disks (void);
|
||||
/*-- in ext2.c --*/
|
||||
extern int e2prog (char *name); /* Massive hack for RHEL 5. */
|
||||
|
||||
/* Confirmed this is true up to ext4 from the Linux sources. */
|
||||
#define EXT2_LABEL_MAX 16
|
||||
|
||||
/*-- in lvm.c --*/
|
||||
extern int lv_canonical (const char *device, char **ret);
|
||||
|
||||
@@ -145,10 +174,11 @@ extern void main_loop (int sock) __attribute__((noreturn));
|
||||
* NB: you don't need to prefix the string with the current command,
|
||||
* it is added automatically by the client-side RPC stubs.
|
||||
*/
|
||||
extern void reply_with_error (const char *fs, ...)
|
||||
__attribute__((format (printf,1,2)));
|
||||
extern void reply_with_error_errno (int err, const char *fs, ...)
|
||||
__attribute__((format (printf,2,3)));
|
||||
extern void reply_with_perror_errno (int err, const char *fs, ...)
|
||||
__attribute__((format (printf,2,3)));
|
||||
#define reply_with_error(...) reply_with_error_errno(0, __VA_ARGS__)
|
||||
#define reply_with_perror(...) reply_with_perror_errno(errno, __VA_ARGS__)
|
||||
|
||||
/* daemon functions that receive files (FileIn) should call
|
||||
@@ -166,7 +196,7 @@ extern int cancel_receive (void);
|
||||
* reply, then send_file_* for each FileOut parameter.
|
||||
* Note max write size if GUESTFS_MAX_CHUNK_SIZE.
|
||||
*/
|
||||
extern int send_file_write (const void *buf, int len);
|
||||
extern int send_file_write (const void *buf, size_t len);
|
||||
extern int send_file_end (int cancel);
|
||||
|
||||
/* only call this if there is a FileOut parameter */
|
||||
@@ -264,8 +294,11 @@ is_zero (const char *buffer, size_t size)
|
||||
reply_with_error ("%s: %s: expecting a device name", __func__, (path)); \
|
||||
fail_stmt; \
|
||||
} \
|
||||
if (is_root_device (path)) \
|
||||
if (is_root_device (path)) { \
|
||||
cancel_stmt; \
|
||||
reply_with_error ("%s: %s: device not found", __func__, path); \
|
||||
fail_stmt; \
|
||||
} \
|
||||
if (device_name_translation ((path)) == -1) { \
|
||||
int err = errno; \
|
||||
cancel_stmt; \
|
||||
@@ -331,16 +364,6 @@ is_zero (const char *buffer, size_t size)
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Marks functions which are not available.
|
||||
* NB. Cannot be used for FileIn functions.
|
||||
*/
|
||||
#define NOT_AVAILABLE(errcode) \
|
||||
do { \
|
||||
reply_with_error ("%s: function not available", __func__); \
|
||||
return (errcode); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#ifndef __attribute__
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
|
||||
# define __attribute__(x) /* empty */
|
||||
|
||||
@@ -79,14 +79,14 @@ do_copy_size (const char *src, const char *dest, int64_t ssize)
|
||||
int src_fd, dest_fd;
|
||||
|
||||
if (STRPREFIX (src, "/dev/"))
|
||||
src_fd = open (src, O_RDONLY);
|
||||
src_fd = open (src, O_RDONLY | O_CLOEXEC);
|
||||
else {
|
||||
buf = sysroot_path (src);
|
||||
if (!buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
src_fd = open (buf, O_RDONLY);
|
||||
src_fd = open (buf, O_RDONLY | O_CLOEXEC);
|
||||
free (buf);
|
||||
}
|
||||
if (src_fd == -1) {
|
||||
@@ -95,7 +95,7 @@ do_copy_size (const char *src, const char *dest, int64_t ssize)
|
||||
}
|
||||
|
||||
if (STRPREFIX (dest, "/dev/"))
|
||||
dest_fd = open (dest, O_WRONLY);
|
||||
dest_fd = open (dest, O_WRONLY | O_CLOEXEC);
|
||||
else {
|
||||
buf = sysroot_path (dest);
|
||||
if (!buf) {
|
||||
@@ -103,7 +103,7 @@ do_copy_size (const char *src, const char *dest, int64_t ssize)
|
||||
close (src_fd);
|
||||
return -1;
|
||||
}
|
||||
dest_fd = open (buf, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666);
|
||||
dest_fd = open (buf, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666);
|
||||
free (buf);
|
||||
}
|
||||
if (dest_fd == -1) {
|
||||
|
||||
@@ -47,21 +47,21 @@
|
||||
|
||||
struct cmd {
|
||||
const char *cmd;
|
||||
char * (*f) (const char *subcmd, int argc, char *const *const argv);
|
||||
char * (*f) (const char *subcmd, size_t argc, char *const *const argv);
|
||||
};
|
||||
|
||||
static char *debug_help (const char *subcmd, int argc, char *const *const argv);
|
||||
static char *debug_binaries (const char *subcmd, int argc, char *const *const argv);
|
||||
static char *debug_core_pattern (const char *subcmd, int argc, char *const *const argv);
|
||||
static char *debug_env (const char *subcmd, int argc, char *const *const argv);
|
||||
static char *debug_fds (const char *subcmd, int argc, char *const *const argv);
|
||||
static char *debug_ldd (const char *subcmd, int argc, char *const *const argv);
|
||||
static char *debug_ls (const char *subcmd, int argc, char *const *const argv);
|
||||
static char *debug_ll (const char *subcmd, int argc, char *const *const argv);
|
||||
static char *debug_progress (const char *subcmd, int argc, char *const *const argv);
|
||||
static char *debug_qtrace (const char *subcmd, int argc, char *const *const argv);
|
||||
static char *debug_segv (const char *subcmd, int argc, char *const *const argv);
|
||||
static char *debug_sh (const char *subcmd, int argc, char *const *const argv);
|
||||
static char *debug_help (const char *subcmd, size_t argc, char *const *const argv);
|
||||
static char *debug_binaries (const char *subcmd, size_t argc, char *const *const argv);
|
||||
static char *debug_core_pattern (const char *subcmd, size_t argc, char *const *const argv);
|
||||
static char *debug_env (const char *subcmd, size_t argc, char *const *const argv);
|
||||
static char *debug_fds (const char *subcmd, size_t argc, char *const *const argv);
|
||||
static char *debug_ldd (const char *subcmd, size_t argc, char *const *const argv);
|
||||
static char *debug_ls (const char *subcmd, size_t argc, char *const *const argv);
|
||||
static char *debug_ll (const char *subcmd, size_t argc, char *const *const argv);
|
||||
static char *debug_progress (const char *subcmd, size_t argc, char *const *const argv);
|
||||
static char *debug_qtrace (const char *subcmd, size_t argc, char *const *const argv);
|
||||
static char *debug_segv (const char *subcmd, size_t argc, char *const *const argv);
|
||||
static char *debug_sh (const char *subcmd, size_t argc, char *const *const argv);
|
||||
|
||||
static struct cmd cmds[] = {
|
||||
{ "help", debug_help },
|
||||
@@ -82,7 +82,7 @@ static struct cmd cmds[] = {
|
||||
char *
|
||||
do_debug (const char *subcmd, char *const *argv)
|
||||
{
|
||||
int argc, i;
|
||||
size_t argc, i;
|
||||
|
||||
for (i = argc = 0; argv[i] != NULL; ++i)
|
||||
argc++;
|
||||
@@ -97,9 +97,9 @@ do_debug (const char *subcmd, char *const *argv)
|
||||
}
|
||||
|
||||
static char *
|
||||
debug_help (const char *subcmd, int argc, char *const *const argv)
|
||||
debug_help (const char *subcmd, size_t argc, char *const *const argv)
|
||||
{
|
||||
int len, i;
|
||||
size_t len, i;
|
||||
char *r, *p;
|
||||
|
||||
r = strdup ("Commands supported:");
|
||||
@@ -128,7 +128,7 @@ debug_help (const char *subcmd, int argc, char *const *const argv)
|
||||
|
||||
/* Show open FDs. */
|
||||
static char *
|
||||
debug_fds (const char *subcmd, int argc, char *const *const argv)
|
||||
debug_fds (const char *subcmd, size_t argc, char *const *const argv)
|
||||
{
|
||||
int r;
|
||||
char *out;
|
||||
@@ -196,9 +196,15 @@ debug_fds (const char *subcmd, int argc, char *const *const argv)
|
||||
|
||||
/* Force a segfault in the daemon. */
|
||||
static char *
|
||||
debug_segv (const char *subcmd, int argc, char *const *const argv)
|
||||
debug_segv (const char *subcmd, size_t 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;
|
||||
}
|
||||
|
||||
@@ -208,16 +214,16 @@ debug_segv (const char *subcmd, int argc, char *const *const argv)
|
||||
* because it's not using the guest shell, and is not chrooted.
|
||||
*/
|
||||
static char *
|
||||
debug_sh (const char *subcmd, int argc, char *const *const argv)
|
||||
debug_sh (const char *subcmd, size_t argc, char *const *const argv)
|
||||
{
|
||||
char *cmd;
|
||||
size_t len, i, j;
|
||||
|
||||
if (argc < 1) {
|
||||
reply_with_error ("sh: expecting a command to run");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *cmd;
|
||||
int len, i, j;
|
||||
|
||||
/* guestfish splits the parameter(s) into a list of strings,
|
||||
* and we have to reassemble them here. Not ideal. XXX
|
||||
*/
|
||||
@@ -262,7 +268,7 @@ debug_sh (const char *subcmd, int argc, char *const *const argv)
|
||||
|
||||
/* Print the environment that commands get (by running external printenv). */
|
||||
static char *
|
||||
debug_env (const char *subcmd, int argc, char *const *const argv)
|
||||
debug_env (const char *subcmd, size_t argc, char *const *const argv)
|
||||
{
|
||||
int r;
|
||||
char *out, *err;
|
||||
@@ -284,7 +290,7 @@ debug_env (const char *subcmd, int argc, char *const *const argv)
|
||||
* See tests/regressions/rhbz727178.sh
|
||||
*/
|
||||
static char *
|
||||
debug_binaries (const char *subcmd, int argc, char *const *const argv)
|
||||
debug_binaries (const char *subcmd, size_t argc, char *const *const argv)
|
||||
{
|
||||
int r;
|
||||
char *out, *err;
|
||||
@@ -312,7 +318,7 @@ debug_binaries (const char *subcmd, int argc, char *const *const argv)
|
||||
* See tests/regressions/rhbz727178.sh
|
||||
*/
|
||||
static char *
|
||||
debug_ldd (const char *subcmd, int argc, char *const *const argv)
|
||||
debug_ldd (const char *subcmd, size_t argc, char *const *const argv)
|
||||
{
|
||||
int r;
|
||||
char *out, *err, *ret;
|
||||
@@ -353,11 +359,11 @@ debug_ldd (const char *subcmd, int argc, char *const *const argv)
|
||||
|
||||
/* List files in the appliance. */
|
||||
static char *
|
||||
debug_ls (const char *subcmd, int argc, char *const *const argv)
|
||||
debug_ls (const char *subcmd, size_t argc, char *const *const argv)
|
||||
{
|
||||
int len = count_strings (argv);
|
||||
size_t len = count_strings (argv);
|
||||
const char *cargv[len+3];
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
cargv[0] = "ls";
|
||||
cargv[1] = "-a";
|
||||
@@ -383,11 +389,11 @@ debug_ls (const char *subcmd, int argc, char *const *const argv)
|
||||
|
||||
/* List files in the appliance. */
|
||||
static char *
|
||||
debug_ll (const char *subcmd, int argc, char *const *const argv)
|
||||
debug_ll (const char *subcmd, size_t argc, char *const *const argv)
|
||||
{
|
||||
int len = count_strings (argv);
|
||||
size_t len = count_strings (argv);
|
||||
const char *cargv[len+3];
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
cargv[0] = "ls";
|
||||
cargv[1] = "-la";
|
||||
@@ -413,7 +419,7 @@ debug_ll (const char *subcmd, int argc, char *const *const argv)
|
||||
|
||||
/* Generate progress notification messages in order to test progress bars. */
|
||||
static char *
|
||||
debug_progress (const char *subcmd, int argc, char *const *const argv)
|
||||
debug_progress (const char *subcmd, size_t argc, char *const *const argv)
|
||||
{
|
||||
if (argc < 1) {
|
||||
error:
|
||||
@@ -423,8 +429,12 @@ debug_progress (const char *subcmd, int argc, char *const *const argv)
|
||||
|
||||
char *secs_str = argv[0];
|
||||
unsigned secs;
|
||||
if (sscanf (secs_str, "%u", &secs) != 1 || secs == 0)
|
||||
if (sscanf (secs_str, "%u", &secs) != 1)
|
||||
goto error;
|
||||
if (secs == 0 || secs > 1000000) { /* RHBZ#816839 */
|
||||
reply_with_error ("progress: argument is 0, less than 0, or too large");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned i;
|
||||
unsigned tsecs = secs * 10; /* 1/10ths of seconds */
|
||||
@@ -449,7 +459,7 @@ debug_progress (const char *subcmd, int argc, char *const *const argv)
|
||||
* crashes doesn't chroot.
|
||||
*/
|
||||
static char *
|
||||
debug_core_pattern (const char *subcmd, int argc, char *const *const argv)
|
||||
debug_core_pattern (const char *subcmd, size_t argc, char *const *const argv)
|
||||
{
|
||||
if (argc < 1) {
|
||||
reply_with_error ("core_pattern: expecting a core pattern");
|
||||
@@ -460,13 +470,14 @@ debug_core_pattern (const char *subcmd, int argc, char *const *const argv)
|
||||
const size_t pattern_len = strlen(pattern);
|
||||
|
||||
#define CORE_PATTERN "/proc/sys/kernel/core_pattern"
|
||||
int fd = open (CORE_PATTERN, O_WRONLY);
|
||||
int fd = open (CORE_PATTERN, O_WRONLY|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("open: " CORE_PATTERN);
|
||||
return NULL;
|
||||
}
|
||||
if (write (fd, pattern, pattern_len) < (ssize_t) pattern_len) {
|
||||
reply_with_perror ("write: " CORE_PATTERN);
|
||||
close (fd);
|
||||
return NULL;
|
||||
}
|
||||
if (close (fd) == -1) {
|
||||
@@ -503,7 +514,7 @@ write_cb (void *fd_ptr, const void *buf, size_t len)
|
||||
* directory in the libguestfs source tree.
|
||||
*/
|
||||
static char *
|
||||
debug_qtrace (const char *subcmd, int argc, char *const *const argv)
|
||||
debug_qtrace (const char *subcmd, size_t argc, char *const *const argv)
|
||||
{
|
||||
int enable;
|
||||
|
||||
@@ -525,7 +536,7 @@ debug_qtrace (const char *subcmd, int argc, char *const *const argv)
|
||||
return NULL;
|
||||
|
||||
/* Note this doesn't do device name translation or check this is a device. */
|
||||
int fd = open (argv[0], O_RDONLY | O_DIRECT);
|
||||
int fd = open (argv[0], O_RDONLY|O_DIRECT|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("qtrace: %s: open", argv[0]);
|
||||
return NULL;
|
||||
@@ -595,7 +606,7 @@ do_debug_upload (const char *filename, int mode)
|
||||
/* Not chrooted - this command lets you upload a file to anywhere
|
||||
* in the appliance.
|
||||
*/
|
||||
int fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, mode);
|
||||
int fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, mode);
|
||||
|
||||
if (fd == -1) {
|
||||
int err = errno;
|
||||
|
||||
@@ -31,15 +31,13 @@
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
|
||||
typedef int (*block_dev_func_t)(const char *dev,
|
||||
char ***r, int *size, int *alloc);
|
||||
typedef int (*block_dev_func_t) (const char *dev, struct stringsbuf *r);
|
||||
|
||||
/* Execute a given function for each discovered block device */
|
||||
static char**
|
||||
static char **
|
||||
foreach_block_device (block_dev_func_t func)
|
||||
{
|
||||
char **r = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (r);
|
||||
|
||||
DIR *dir;
|
||||
int err = 0;
|
||||
@@ -70,7 +68,7 @@ foreach_block_device (block_dev_func_t func)
|
||||
* CD-ROM device even though we didn't request it. Try to
|
||||
* detect this by seeing if the device contains media.
|
||||
*/
|
||||
int fd = open (dev_path, O_RDONLY);
|
||||
int fd = open (dev_path, O_RDONLY|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
perror (dev_path);
|
||||
continue;
|
||||
@@ -78,7 +76,7 @@ foreach_block_device (block_dev_func_t func)
|
||||
close (fd);
|
||||
|
||||
/* Call the map function for this device */
|
||||
if((*func)(d->d_name, &r, &size, &alloc) != 0) {
|
||||
if((*func)(d->d_name, &r) != 0) {
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
@@ -88,7 +86,7 @@ foreach_block_device (block_dev_func_t func)
|
||||
/* Check readdir didn't fail */
|
||||
if(0 != errno) {
|
||||
reply_with_perror ("readdir: /sys/block");
|
||||
free_stringslen(r, size);
|
||||
free_stringslen (r.argv, r.size);
|
||||
closedir (dir);
|
||||
return NULL;
|
||||
}
|
||||
@@ -96,37 +94,36 @@ foreach_block_device (block_dev_func_t func)
|
||||
/* Close the directory handle */
|
||||
if (closedir (dir) == -1) {
|
||||
reply_with_perror ("closedir: /sys/block");
|
||||
free_stringslen(r, size);
|
||||
free_stringslen (r.argv, r.size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Free the result list on error */
|
||||
if(err) {
|
||||
free_stringslen(r, size);
|
||||
if (err) {
|
||||
free_stringslen (r.argv, r.size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Sort the devices. Note that r might be NULL if there are no devices. */
|
||||
if (r != NULL)
|
||||
sort_strings (r, size);
|
||||
/* Sort the devices. */
|
||||
if (r.size > 0)
|
||||
sort_strings (r.argv, r.size);
|
||||
|
||||
/* NULL terminate the list */
|
||||
if (add_string (&r, &size, &alloc, NULL) == -1) {
|
||||
if (end_stringsbuf (&r) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
return r.argv;
|
||||
}
|
||||
|
||||
/* Add a device to the list of devices */
|
||||
static int
|
||||
add_device(const char *device,
|
||||
char ***const r, int *const size, int *const alloc)
|
||||
add_device (const char *device, struct stringsbuf *r)
|
||||
{
|
||||
char dev_path[256];
|
||||
snprintf (dev_path, sizeof dev_path, "/dev/%s", device);
|
||||
|
||||
if (add_string (r, size, alloc, dev_path) == -1) {
|
||||
if (add_string (r, dev_path) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -136,12 +133,11 @@ add_device(const char *device,
|
||||
char **
|
||||
do_list_devices (void)
|
||||
{
|
||||
return foreach_block_device(add_device);
|
||||
return foreach_block_device (add_device);
|
||||
}
|
||||
|
||||
static int
|
||||
add_partitions(const char *device,
|
||||
char ***const r, int *const size, int *const alloc)
|
||||
add_partitions (const char *device, struct stringsbuf *r)
|
||||
{
|
||||
char devdir[256];
|
||||
|
||||
@@ -151,7 +147,7 @@ add_partitions(const char *device,
|
||||
DIR *dir = opendir (devdir);
|
||||
if (!dir) {
|
||||
reply_with_perror ("opendir: %s", devdir);
|
||||
free_stringslen (*r, *size);
|
||||
free_stringslen (r->argv, r->size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -165,7 +161,7 @@ add_partitions(const char *device,
|
||||
char part[256];
|
||||
snprintf (part, sizeof part, "/dev/%s", d->d_name);
|
||||
|
||||
if (add_string (r, size, alloc, part) == -1) {
|
||||
if (add_string (r, part) == -1) {
|
||||
closedir (dir);
|
||||
return -1;
|
||||
}
|
||||
@@ -173,9 +169,9 @@ add_partitions(const char *device,
|
||||
}
|
||||
|
||||
/* Check if readdir failed */
|
||||
if(0 != errno) {
|
||||
if (0 != errno) {
|
||||
reply_with_perror ("readdir: %s", devdir);
|
||||
free_stringslen(*r, *size);
|
||||
free_stringslen (r->argv, r->size);
|
||||
closedir (dir);
|
||||
return -1;
|
||||
}
|
||||
@@ -183,7 +179,7 @@ add_partitions(const char *device,
|
||||
/* Close the directory handle */
|
||||
if (closedir (dir) == -1) {
|
||||
reply_with_perror ("closedir: /sys/block/%s", device);
|
||||
free_stringslen (*r, *size);
|
||||
free_stringslen (r->argv, r->size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -193,7 +189,7 @@ add_partitions(const char *device,
|
||||
char **
|
||||
do_list_partitions (void)
|
||||
{
|
||||
return foreach_block_device(add_partitions);
|
||||
return foreach_block_device (add_partitions);
|
||||
}
|
||||
|
||||
char *
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 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
|
||||
|
||||
363
daemon/ext2.c
363
daemon/ext2.c
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 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
|
||||
@@ -29,9 +29,6 @@
|
||||
#include "c-ctype.h"
|
||||
#include "actions.h"
|
||||
|
||||
/* 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
|
||||
@@ -66,8 +63,7 @@ do_tune2fs_l (const char *device)
|
||||
int r;
|
||||
char *out, *err;
|
||||
char *p, *pend, *colon;
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (ret);
|
||||
|
||||
char prog[] = "tune2fs";
|
||||
if (e2prog (prog) == -1)
|
||||
@@ -111,30 +107,30 @@ do_tune2fs_l (const char *device)
|
||||
|
||||
do { colon++; } while (*colon && c_isspace (*colon));
|
||||
|
||||
if (add_string (&ret, &size, &alloc, p) == -1) {
|
||||
if (add_string (&ret, p) == -1) {
|
||||
free (out);
|
||||
return NULL;
|
||||
}
|
||||
if (STREQ (colon, "<none>") ||
|
||||
STREQ (colon, "<not available>") ||
|
||||
STREQ (colon, "(none)")) {
|
||||
if (add_string (&ret, &size, &alloc, "") == -1) {
|
||||
if (add_string (&ret, "") == -1) {
|
||||
free (out);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (add_string (&ret, &size, &alloc, colon) == -1) {
|
||||
if (add_string (&ret, colon) == -1) {
|
||||
free (out);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (add_string (&ret, &size, &alloc, p) == -1) {
|
||||
if (add_string (&ret, p) == -1) {
|
||||
free (out);
|
||||
return NULL;
|
||||
}
|
||||
if (add_string (&ret, &size, &alloc, "") == -1) {
|
||||
if (add_string (&ret, "") == -1) {
|
||||
free (out);
|
||||
return NULL;
|
||||
}
|
||||
@@ -145,37 +141,16 @@ do_tune2fs_l (const char *device)
|
||||
|
||||
free (out);
|
||||
|
||||
if (add_string (&ret, &size, &alloc, NULL) == -1)
|
||||
if (end_stringsbuf (&ret) == -1)
|
||||
return NULL;
|
||||
|
||||
return ret;
|
||||
return ret.argv;
|
||||
}
|
||||
|
||||
int
|
||||
do_set_e2label (const char *device, const char *label)
|
||||
{
|
||||
int r;
|
||||
char *err;
|
||||
|
||||
char prog[] = "e2label";
|
||||
if (e2prog (prog) == -1)
|
||||
return -1;
|
||||
|
||||
if (strlen (label) > EXT2_LABEL_MAX) {
|
||||
reply_with_error ("%s: ext2 labels are limited to %d bytes",
|
||||
label, EXT2_LABEL_MAX);
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = command (NULL, &err, prog, device, label, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s", err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return 0;
|
||||
return do_set_label (device, label);
|
||||
}
|
||||
|
||||
char *
|
||||
@@ -211,6 +186,34 @@ do_get_e2uuid (const char *device)
|
||||
return do_vfs_uuid (device);
|
||||
}
|
||||
|
||||
/* If the filesystem is not mounted, run e2fsck -f on it unconditionally. */
|
||||
static int
|
||||
if_not_mounted_run_e2fsck (const char *device)
|
||||
{
|
||||
char *err;
|
||||
int r, mounted;
|
||||
char prog[] = "e2fsck";
|
||||
|
||||
if (e2prog (prog) == -1)
|
||||
return -1;
|
||||
|
||||
mounted = is_device_mounted (device);
|
||||
if (mounted == -1)
|
||||
return -1;
|
||||
|
||||
if (!mounted) {
|
||||
r = command (NULL, &err, prog, "-fy", device, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s", err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_resize2fs (const char *device)
|
||||
{
|
||||
@@ -221,6 +224,9 @@ do_resize2fs (const char *device)
|
||||
if (e2prog (prog) == -1)
|
||||
return -1;
|
||||
|
||||
if (if_not_mounted_run_e2fsck (device) == -1)
|
||||
return -1;
|
||||
|
||||
r = command (NULL, &err, prog, device, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s", err);
|
||||
@@ -253,6 +259,9 @@ do_resize2fs_size (const char *device, int64_t size)
|
||||
}
|
||||
size /= 1024;
|
||||
|
||||
if (if_not_mounted_run_e2fsck (device) == -1)
|
||||
return -1;
|
||||
|
||||
char buf[32];
|
||||
snprintf (buf, sizeof buf, "%" PRIi64 "K", size);
|
||||
|
||||
@@ -277,7 +286,10 @@ do_resize2fs_M (const char *device)
|
||||
if (e2prog (prog) == -1)
|
||||
return -1;
|
||||
|
||||
r = command (NULL, &err, prog, "-M" , device, NULL);
|
||||
if (if_not_mounted_run_e2fsck (device) == -1)
|
||||
return -1;
|
||||
|
||||
r = command (NULL, &err, prog, "-M", device, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s", err);
|
||||
free (err);
|
||||
@@ -288,32 +300,67 @@ do_resize2fs_M (const char *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
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 'correct', 'forceall' 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;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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
|
||||
@@ -416,7 +463,7 @@ do_mke2fs_J (const char *fstype, int blocksize, const char *device,
|
||||
char blocksize_s[32];
|
||||
snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize);
|
||||
|
||||
int len = strlen (journal);
|
||||
size_t len = strlen (journal);
|
||||
char jdev[len+32];
|
||||
snprintf (jdev, len+32, "device=%s", journal);
|
||||
|
||||
@@ -453,7 +500,7 @@ do_mke2fs_JL (const char *fstype, int blocksize, const char *device,
|
||||
char blocksize_s[32];
|
||||
snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize);
|
||||
|
||||
int len = strlen (label);
|
||||
size_t len = strlen (label);
|
||||
char jdev[len+32];
|
||||
snprintf (jdev, len+32, "device=LABEL=%s", label);
|
||||
|
||||
@@ -484,7 +531,7 @@ do_mke2fs_JU (const char *fstype, int blocksize, const char *device,
|
||||
char blocksize_s[32];
|
||||
snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize);
|
||||
|
||||
int len = strlen (uuid);
|
||||
size_t len = strlen (uuid);
|
||||
char jdev[len+32];
|
||||
snprintf (jdev, len+32, "device=UUID=%s", uuid);
|
||||
|
||||
@@ -647,3 +694,195 @@ do_tune2fs (const char *device, /* only required parameter */
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
compare_chars (const void *vc1, const void *vc2)
|
||||
{
|
||||
char c1 = * (char *) vc1;
|
||||
char c2 = * (char *) vc2;
|
||||
return c1 - c2;
|
||||
}
|
||||
|
||||
char *
|
||||
do_get_e2attrs (const char *filename)
|
||||
{
|
||||
int r;
|
||||
char *buf;
|
||||
char *out, *err;
|
||||
size_t i, j;
|
||||
|
||||
buf = sysroot_path (filename);
|
||||
if (!buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = command (&out, &err, "lsattr", "-d", "--", buf, NULL);
|
||||
free (buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s: %s", "lsattr", filename, err);
|
||||
free (err);
|
||||
free (out);
|
||||
return NULL;
|
||||
}
|
||||
free (err);
|
||||
|
||||
/* Output looks like:
|
||||
* -------------e- filename
|
||||
* Remove the dashes and return everything up to the space.
|
||||
*/
|
||||
for (i = j = 0; out[j] != ' '; j++) {
|
||||
if (out[j] != '-')
|
||||
out[i++] = out[j];
|
||||
}
|
||||
|
||||
out[i] = '\0';
|
||||
|
||||
/* Sort the output, mainly to make testing simpler. */
|
||||
qsort (out, i, sizeof (char), compare_chars);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_set_e2attrs (const char *filename, const char *attrs, int clear)
|
||||
{
|
||||
int r;
|
||||
char *buf;
|
||||
char *err;
|
||||
size_t i, j;
|
||||
int lowers[26], uppers[26];
|
||||
char attr_arg[26*2+1+1]; /* '+'/'-' + attrs + trailing '\0' */
|
||||
|
||||
if (!(optargs_bitmask & GUESTFS_SET_E2ATTRS_CLEAR_BITMASK))
|
||||
attr_arg[0] = '+';
|
||||
else if (!clear)
|
||||
attr_arg[0] = '+';
|
||||
else
|
||||
attr_arg[0] = '-';
|
||||
j = 1;
|
||||
|
||||
/* You can't write "chattr - file", so we have to just return if
|
||||
* the string is empty.
|
||||
*/
|
||||
if (STREQ (attrs, ""))
|
||||
return 0;
|
||||
|
||||
/* Valid attrs are all lower or upper case ASCII letters. Check
|
||||
* this and that there are no duplicates.
|
||||
*/
|
||||
memset (lowers, 0, sizeof lowers);
|
||||
memset (uppers, 0, sizeof uppers);
|
||||
for (; *attrs; attrs++) {
|
||||
/* These are reserved by the chattr program for command line flags. */
|
||||
if (*attrs == 'R' || *attrs == 'V' || *attrs == 'f' || *attrs == 'v') {
|
||||
reply_with_error ("bad file attribute '%c'", *attrs);
|
||||
return -1;
|
||||
}
|
||||
else if (*attrs >= 'a' && *attrs <= 'z') {
|
||||
i = *attrs - 'a';
|
||||
if (lowers[i] > 0)
|
||||
goto error_duplicate;
|
||||
lowers[i]++;
|
||||
attr_arg[j++] = *attrs;
|
||||
}
|
||||
else if (*attrs >= 'A' && *attrs <= 'Z') {
|
||||
i = *attrs - 'A';
|
||||
if (uppers[i] > 0) {
|
||||
error_duplicate:
|
||||
reply_with_error ("duplicate file attribute '%c'", *attrs);
|
||||
return -1;
|
||||
}
|
||||
uppers[i]++;
|
||||
attr_arg[j++] = *attrs;
|
||||
}
|
||||
else {
|
||||
reply_with_error ("unknown file attribute '%c'", *attrs);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
attr_arg[j] = '\0';
|
||||
|
||||
buf = sysroot_path (filename);
|
||||
if (!buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = command (NULL, &err, "chattr", attr_arg, "--", buf, NULL);
|
||||
free (buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s: %s", "chattr", filename, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t
|
||||
do_get_e2generation (const char *filename)
|
||||
{
|
||||
int r;
|
||||
char *buf;
|
||||
char *out, *err;
|
||||
int64_t ret;
|
||||
|
||||
buf = sysroot_path (filename);
|
||||
if (!buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = command (&out, &err, "lsattr", "-dv", "--", buf, NULL);
|
||||
free (buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s: %s", "lsattr", filename, err);
|
||||
free (err);
|
||||
free (out);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
if (sscanf (out, "%" SCNu64, &ret) != 1) {
|
||||
reply_with_error ("cannot parse output from '%s' command: %s",
|
||||
"lsattr", out);
|
||||
free (out);
|
||||
return -1;
|
||||
}
|
||||
free (out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
do_set_e2generation (const char *filename, int64_t generation)
|
||||
{
|
||||
int r;
|
||||
char *buf;
|
||||
char *err;
|
||||
char generation_str[64];
|
||||
|
||||
buf = sysroot_path (filename);
|
||||
if (!buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf (generation_str, sizeof generation_str,
|
||||
"%" PRIu64, (uint64_t) generation);
|
||||
|
||||
r = command (NULL, &err, "chattr", "-v", generation_str, "--", buf, NULL);
|
||||
free (buf);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s: %s", "chattr", filename, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ do_fallocate64 (const char *path, int64_t len)
|
||||
int fd;
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_NOCTTY, 0666);
|
||||
fd = open (path, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666);
|
||||
CHROOT_OUT;
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("open: %s", path);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 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
|
||||
@@ -38,6 +38,12 @@ do_touch (const char *path)
|
||||
|
||||
/* RHBZ#582484: Restrict touch to regular files. It's also OK
|
||||
* here if the file does not exist, since we will create it.
|
||||
*
|
||||
* XXX Coverity flags this as a time-of-check to time-of-use race
|
||||
* condition, particularly in the libguestfs live case. Not clear
|
||||
* how to fix this yet, since unconditionally opening the file can
|
||||
* cause a hang, so you have to somehow check it first before you
|
||||
* open it.
|
||||
*/
|
||||
CHROOT_IN;
|
||||
r = lstat (path, &buf);
|
||||
@@ -56,7 +62,7 @@ do_touch (const char *path)
|
||||
}
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_WRONLY | O_CREAT | O_NOCTTY, 0666);
|
||||
fd = open (path, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0666);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
@@ -83,11 +89,12 @@ char *
|
||||
do_cat (const char *path)
|
||||
{
|
||||
int fd;
|
||||
int alloc, size, r, max;
|
||||
size_t alloc, size, max;
|
||||
ssize_t r;
|
||||
char *buf, *buf2;
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_RDONLY);
|
||||
fd = open (path, O_RDONLY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
@@ -150,8 +157,7 @@ do_cat (const char *path)
|
||||
char **
|
||||
do_read_lines (const char *path)
|
||||
{
|
||||
char **r = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (r);
|
||||
FILE *fp;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
@@ -173,7 +179,7 @@ do_read_lines (const char *path)
|
||||
else if (n >= 1 && line[n-1] == '\n')
|
||||
line[n-1] = '\0';
|
||||
|
||||
if (add_string (&r, &size, &alloc, line) == -1) {
|
||||
if (add_string (&r, line) == -1) {
|
||||
free (line);
|
||||
fclose (fp);
|
||||
return NULL;
|
||||
@@ -182,18 +188,18 @@ do_read_lines (const char *path)
|
||||
|
||||
free (line);
|
||||
|
||||
if (add_string (&r, &size, &alloc, NULL) == -1) {
|
||||
if (end_stringsbuf (&r) == -1) {
|
||||
fclose (fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fclose (fp) == EOF) {
|
||||
reply_with_perror ("fclose: %s", path);
|
||||
free_strings (r);
|
||||
free_stringslen (r.argv, r.size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
return r.argv;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -299,7 +305,7 @@ do_write_file (const char *path, const char *content, int size)
|
||||
}
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_WRONLY | O_TRUNC | O_CREAT | O_NOCTTY, 0666);
|
||||
fd = open (path, O_WRONLY|O_TRUNC|O_CREAT|O_NOCTTY|O_CLOEXEC, 0666);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
@@ -327,7 +333,7 @@ do_write (const char *path, const char *content, size_t size)
|
||||
int fd;
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_WRONLY | O_TRUNC | O_CREAT | O_NOCTTY, 0666);
|
||||
fd = open (path, O_WRONLY|O_TRUNC|O_CREAT|O_NOCTTY|O_CLOEXEC, 0666);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
@@ -355,7 +361,7 @@ do_write_append (const char *path, const char *content, size_t size)
|
||||
int fd;
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_WRONLY | O_APPEND | O_CREAT | O_NOCTTY, 0666);
|
||||
fd = open (path, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY|O_CLOEXEC, 0666);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
@@ -385,7 +391,7 @@ do_read_file (const char *path, size_t *size_r)
|
||||
char *r;
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_RDONLY);
|
||||
fd = open (path, O_RDONLY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
@@ -483,7 +489,6 @@ pread_fd (int fd, int count, int64_t offset, size_t *size_r,
|
||||
|
||||
if (close (fd) == -1) {
|
||||
reply_with_perror ("close: %s", display_path);
|
||||
close (fd);
|
||||
free (buf);
|
||||
return NULL;
|
||||
}
|
||||
@@ -501,7 +506,7 @@ do_pread (const char *path, int count, int64_t offset, size_t *size_r)
|
||||
int fd;
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_RDONLY);
|
||||
fd = open (path, O_RDONLY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
@@ -515,7 +520,7 @@ do_pread (const char *path, int count, int64_t offset, size_t *size_r)
|
||||
char *
|
||||
do_pread_device (const char *device, int count, int64_t offset, size_t *size_r)
|
||||
{
|
||||
int fd = open (device, O_RDONLY);
|
||||
int fd = open (device, O_RDONLY|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("open: %s", device);
|
||||
return NULL;
|
||||
@@ -539,7 +544,6 @@ pwrite_fd (int fd, const char *content, size_t size, int64_t offset,
|
||||
|
||||
if (close (fd) == -1) {
|
||||
reply_with_perror ("close: %s", display_path);
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -557,7 +561,7 @@ do_pwrite (const char *path, const char *content, size_t size, int64_t offset)
|
||||
}
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_WRONLY);
|
||||
fd = open (path, O_WRONLY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
@@ -577,7 +581,7 @@ do_pwrite_device (const char *device, const char *content, size_t size,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fd = open (device, O_WRONLY);
|
||||
int fd = open (device, O_WRONLY|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("open: %s", device);
|
||||
return -1;
|
||||
@@ -668,7 +672,7 @@ do_file (const char *path)
|
||||
char *
|
||||
do_zfile (const char *method, const char *path)
|
||||
{
|
||||
int len;
|
||||
size_t len;
|
||||
const char *zcat;
|
||||
char *cmd;
|
||||
FILE *fp;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -31,9 +31,10 @@
|
||||
#include "actions.h"
|
||||
|
||||
static int
|
||||
input_to_nul (FILE *fp, char *buf, int maxlen)
|
||||
input_to_nul (FILE *fp, char *buf, size_t maxlen)
|
||||
{
|
||||
int i = 0, c;
|
||||
size_t i = 0;
|
||||
int c;
|
||||
|
||||
while (i < maxlen) {
|
||||
c = fgetc (fp);
|
||||
@@ -52,11 +53,12 @@ char **
|
||||
do_find (const char *dir)
|
||||
{
|
||||
struct stat statbuf;
|
||||
int r, len, sysrootdirlen;
|
||||
int r;
|
||||
size_t sysrootdirlen;
|
||||
size_t len;
|
||||
char *cmd;
|
||||
FILE *fp;
|
||||
char **res = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (ret);
|
||||
char *sysrootdir;
|
||||
char str[PATH_MAX];
|
||||
|
||||
@@ -105,28 +107,29 @@ do_find (const char *dir)
|
||||
continue;
|
||||
|
||||
/* Remove the directory part of the path when adding it. */
|
||||
if (add_string (&res, &size, &alloc, str + sysrootdirlen) == -1) {
|
||||
if (add_string (&ret, str + sysrootdirlen) == -1) {
|
||||
pclose (fp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (pclose (fp) != 0) {
|
||||
reply_with_perror ("pclose");
|
||||
free_stringslen (res, size);
|
||||
free_stringslen (ret.argv, ret.size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (r == -1) {
|
||||
free_stringslen (res, size);
|
||||
free_stringslen (ret.argv, ret.size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (add_string (&res, &size, &alloc, NULL) == -1)
|
||||
if (ret.size > 0)
|
||||
sort_strings (ret.argv, ret.size);
|
||||
|
||||
if (end_stringsbuf (&ret) == -1)
|
||||
return NULL;
|
||||
|
||||
sort_strings (res, size-1);
|
||||
|
||||
return res; /* caller frees */
|
||||
return ret.argv; /* caller frees */
|
||||
}
|
||||
|
||||
/* The code below assumes each path returned can fit into a protocol
|
||||
|
||||
@@ -35,6 +35,7 @@ findfs (const char *tag, const char *label_or_uuid)
|
||||
* is not supported in RHEL 5.
|
||||
*/
|
||||
unlink ("/etc/blkid/blkid.tab");
|
||||
unlink ("/run/blkid/blkid.tab");
|
||||
|
||||
size_t len = strlen (tag) + strlen (label_or_uuid) + 2;
|
||||
char arg[len];
|
||||
|
||||
@@ -29,7 +29,7 @@ char **
|
||||
do_glob_expand (const char *pattern)
|
||||
{
|
||||
int r;
|
||||
glob_t buf;
|
||||
glob_t buf = { .gl_pathc = 0, .gl_pathv = NULL, .gl_offs = 0 };
|
||||
|
||||
/* glob(3) in glibc never calls chdir, so this seems to be safe: */
|
||||
CHROOT_IN;
|
||||
|
||||
@@ -36,7 +36,7 @@ grep (const char *prog, const char *flag, const char *regex, const char *path)
|
||||
char **lines;
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_RDONLY);
|
||||
fd = open (path, O_RDONLY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -203,6 +203,8 @@ main (int argc, char *argv[])
|
||||
printf ("could not read linux command line\n");
|
||||
}
|
||||
|
||||
free (cmdline);
|
||||
|
||||
#ifndef WIN32
|
||||
/* Make sure SIGPIPE doesn't kill us. */
|
||||
struct sigaction sa;
|
||||
@@ -245,7 +247,7 @@ main (int argc, char *argv[])
|
||||
copy_lvm ();
|
||||
|
||||
/* Connect to virtio-serial channel. */
|
||||
int sock = open (VIRTIO_SERIAL_CHANNEL, O_RDWR | O_CLOEXEC);
|
||||
int sock = open (VIRTIO_SERIAL_CHANNEL, O_RDWR|O_CLOEXEC);
|
||||
if (sock == -1) {
|
||||
fprintf (stderr,
|
||||
"\n"
|
||||
@@ -290,7 +292,7 @@ main (int argc, char *argv[])
|
||||
static char *
|
||||
read_cmdline (void)
|
||||
{
|
||||
int fd = open ("/proc/cmdline", O_RDONLY);
|
||||
int fd = open ("/proc/cmdline", O_RDONLY|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
perror ("/proc/cmdline");
|
||||
return NULL;
|
||||
@@ -362,7 +364,7 @@ char *
|
||||
sysroot_path (const char *path)
|
||||
{
|
||||
char *r;
|
||||
int len = strlen (path) + sysroot_len + 1;
|
||||
size_t len = strlen (path) + sysroot_len + 1;
|
||||
|
||||
r = malloc (len);
|
||||
if (r == NULL)
|
||||
@@ -375,7 +377,7 @@ sysroot_path (const char *path)
|
||||
int
|
||||
xwrite (int sock, const void *v_buf, size_t len)
|
||||
{
|
||||
int r;
|
||||
ssize_t r;
|
||||
const char *buf = v_buf;
|
||||
|
||||
while (len > 0) {
|
||||
@@ -415,46 +417,50 @@ xread (int sock, void *v_buf, size_t len)
|
||||
}
|
||||
|
||||
int
|
||||
add_string_nodup (char ***argv, int *size, int *alloc, char *str)
|
||||
add_string_nodup (struct stringsbuf *sb, char *str)
|
||||
{
|
||||
char **new_argv;
|
||||
|
||||
if (*size >= *alloc) {
|
||||
*alloc += 64;
|
||||
new_argv = realloc (*argv, *alloc * sizeof (char *));
|
||||
if (sb->size >= sb->alloc) {
|
||||
sb->alloc += 64;
|
||||
new_argv = realloc (sb->argv, sb->alloc * sizeof (char *));
|
||||
if (new_argv == NULL) {
|
||||
reply_with_perror ("realloc");
|
||||
free_strings (*argv);
|
||||
*argv = NULL;
|
||||
free_stringslen (sb->argv, sb->size);
|
||||
sb->argv = NULL;
|
||||
return -1;
|
||||
}
|
||||
*argv = new_argv;
|
||||
sb->argv = new_argv;
|
||||
}
|
||||
|
||||
(*argv)[*size] = str;
|
||||
sb->argv[sb->size] = str;
|
||||
sb->size++;
|
||||
|
||||
(*size)++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
add_string (char ***argv, int *size, int *alloc, const char *str)
|
||||
add_string (struct stringsbuf *sb, const char *str)
|
||||
{
|
||||
char *new_str;
|
||||
char *new_str = NULL;
|
||||
|
||||
if (str) {
|
||||
new_str = strdup (str);
|
||||
if (new_str == NULL) {
|
||||
reply_with_perror ("strdup");
|
||||
free_strings (*argv);
|
||||
*argv = NULL;
|
||||
free_stringslen (sb->argv, sb->size);
|
||||
sb->argv = NULL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
new_str = NULL;
|
||||
}
|
||||
|
||||
return add_string_nodup (argv, size, alloc, new_str);
|
||||
return add_string_nodup (sb, new_str);
|
||||
}
|
||||
|
||||
int
|
||||
end_stringsbuf (struct stringsbuf *sb)
|
||||
{
|
||||
return add_string_nodup (sb, NULL);
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -483,7 +489,7 @@ compare (const void *vp1, const void *vp2)
|
||||
}
|
||||
|
||||
void
|
||||
sort_strings (char **argv, int len)
|
||||
sort_strings (char **argv, size_t len)
|
||||
{
|
||||
qsort (argv, len, sizeof (char *), compare);
|
||||
}
|
||||
@@ -491,7 +497,7 @@ sort_strings (char **argv, int len)
|
||||
void
|
||||
free_strings (char **argv)
|
||||
{
|
||||
int argc;
|
||||
size_t argc;
|
||||
|
||||
for (argc = 0; argv[argc] != NULL; ++argc)
|
||||
free (argv[argc]);
|
||||
@@ -499,9 +505,9 @@ free_strings (char **argv)
|
||||
}
|
||||
|
||||
void
|
||||
free_stringslen (char **argv, int len)
|
||||
free_stringslen (char **argv, size_t len)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
free (argv[i]);
|
||||
@@ -517,7 +523,8 @@ commandf (char **stdoutput, char **stderror, int flags, const char *name, ...)
|
||||
va_list args;
|
||||
const char **argv;
|
||||
char *s;
|
||||
int i, r;
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
/* Collect the command line arguments into an array. */
|
||||
i = 2;
|
||||
@@ -649,7 +656,7 @@ int
|
||||
commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
char const* const *argv)
|
||||
{
|
||||
int so_size = 0, se_size = 0;
|
||||
size_t so_size = 0, se_size = 0;
|
||||
int so_fd[2], se_fd[2];
|
||||
int flag_copy_stdin = flags & COMMAND_FLAG_CHROOT_COPY_FILE_TO_STDIN;
|
||||
int stdin_fd[2] = { -1, -1 };
|
||||
@@ -706,7 +713,7 @@ commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
close (stdin_fd[1]);
|
||||
} else {
|
||||
/* Set stdin to /dev/null (ignore failure) */
|
||||
ignore_value (open ("/dev/null", O_RDONLY));
|
||||
ignore_value (open ("/dev/null", O_RDONLY|O_CLOEXEC));
|
||||
}
|
||||
close (so_fd[0]);
|
||||
close (se_fd[0]);
|
||||
@@ -888,9 +895,10 @@ commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
*stderror = q;
|
||||
if (*stderror) {
|
||||
(*stderror)[se_size] = '\0';
|
||||
se_size--;
|
||||
while (se_size >= 0 && (*stderror)[se_size] == '\n')
|
||||
(*stderror)[se_size--] = '\0';
|
||||
while (se_size > 0 && (*stderror)[se_size-1] == '\n') {
|
||||
se_size--;
|
||||
(*stderror)[se_size] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -904,7 +912,7 @@ commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
}
|
||||
|
||||
if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
|
||||
fprintf (stderr, "failed copying from input file, see earlier messages\n");
|
||||
fprintf (stderr, "failed copying from input file, see earlier messages (r = %d)\n", r);
|
||||
kill (pid, 9);
|
||||
waitpid (pid, NULL, 0);
|
||||
return -1;
|
||||
@@ -944,8 +952,7 @@ commandrvf (char **stdoutput, char **stderror, int flags,
|
||||
char **
|
||||
split_lines (char *str)
|
||||
{
|
||||
char **lines = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (lines);
|
||||
char *p, *pend;
|
||||
|
||||
if (STREQ (str, ""))
|
||||
@@ -963,7 +970,7 @@ split_lines (char *str)
|
||||
pend++;
|
||||
}
|
||||
|
||||
if (add_string (&lines, &size, &alloc, p) == -1) {
|
||||
if (add_string (&lines, p) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -971,10 +978,10 @@ split_lines (char *str)
|
||||
}
|
||||
|
||||
empty_list:
|
||||
if (add_string (&lines, &size, &alloc, NULL) == -1)
|
||||
if (end_stringsbuf (&lines) == -1)
|
||||
return NULL;
|
||||
|
||||
return lines;
|
||||
return lines.argv;
|
||||
}
|
||||
|
||||
/* Skip leading and trailing whitespace, updating the original string
|
||||
@@ -1072,7 +1079,7 @@ device_name_translation (char *device)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open (device, O_RDONLY);
|
||||
fd = open (device, O_RDONLY|O_CLOEXEC);
|
||||
if (fd >= 0) {
|
||||
close_ok:
|
||||
close (fd);
|
||||
@@ -1087,12 +1094,12 @@ device_name_translation (char *device)
|
||||
return -1;
|
||||
|
||||
device[5] = 'h'; /* /dev/hd (old IDE driver) */
|
||||
fd = open (device, O_RDONLY);
|
||||
fd = open (device, O_RDONLY|O_CLOEXEC);
|
||||
if (fd >= 0)
|
||||
goto close_ok;
|
||||
|
||||
device[5] = 'v'; /* /dev/vd (for virtio devices) */
|
||||
fd = open (device, O_RDONLY);
|
||||
fd = open (device, O_RDONLY|O_CLOEXEC);
|
||||
if (fd >= 0)
|
||||
goto close_ok;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ headtail (const char *prog, const char *flag, const char *n, const char *path)
|
||||
char **lines;
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_RDONLY);
|
||||
fd = open (path, O_RDONLY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
|
||||
@@ -34,7 +34,7 @@ do_hexdump (const char *path)
|
||||
char *out, *err;
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_RDONLY);
|
||||
fd = open (path, O_RDONLY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
|
||||
@@ -36,8 +36,7 @@ do_initrd_list (const char *path)
|
||||
FILE *fp;
|
||||
char *cmd;
|
||||
char filename[PATH_MAX];
|
||||
char **filenames = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (filenames);
|
||||
size_t len;
|
||||
|
||||
/* "zcat /sysroot/<path> | cpio --quiet -it", but path must be quoted. */
|
||||
@@ -62,24 +61,24 @@ do_initrd_list (const char *path)
|
||||
if (len > 0 && filename[len-1] == '\n')
|
||||
filename[len-1] = '\0';
|
||||
|
||||
if (add_string (&filenames, &size, &alloc, filename) == -1) {
|
||||
if (add_string (&filenames, filename) == -1) {
|
||||
pclose (fp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (add_string (&filenames, &size, &alloc, NULL) == -1) {
|
||||
if (end_stringsbuf (&filenames) == -1) {
|
||||
pclose (fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pclose (fp) != 0) {
|
||||
reply_with_perror ("pclose");
|
||||
free_strings (filenames);
|
||||
free_stringslen (filenames.argv, filenames.size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return filenames;
|
||||
return filenames.argv;
|
||||
}
|
||||
|
||||
char *
|
||||
@@ -108,9 +107,11 @@ do_initrd_cat (const char *path, const char *filename, size_t *size_r)
|
||||
int r = system (cmd);
|
||||
if (r == -1) {
|
||||
reply_with_perror ("command failed: %s", cmd);
|
||||
free (cmd);
|
||||
rmdir (tmpdir);
|
||||
return NULL;
|
||||
}
|
||||
free (cmd);
|
||||
if (WEXITSTATUS (r) != 0) {
|
||||
reply_with_perror ("command failed with return code %d",
|
||||
WEXITSTATUS (r));
|
||||
@@ -125,7 +126,7 @@ do_initrd_cat (const char *path, const char *filename, size_t *size_r)
|
||||
struct stat statbuf;
|
||||
int fd;
|
||||
|
||||
fd = open (fullpath, O_RDONLY);
|
||||
fd = open (fullpath, O_RDONLY|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("open: %s:%s", path, filename);
|
||||
rmdir (tmpdir);
|
||||
|
||||
112
daemon/inotify.c
112
daemon/inotify.c
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
@@ -40,18 +41,22 @@ static int inotify_fd = -1;
|
||||
static char inotify_buf[64*1024*1024]; /* Event buffer, [0..posn-1] is valid */
|
||||
static size_t inotify_posn = 0;
|
||||
|
||||
/* Clean up the inotify handle on daemon exit. */
|
||||
static void inotify_finalize (void) __attribute__((destructor));
|
||||
static void
|
||||
inotify_finalize (void)
|
||||
{
|
||||
if (inotify_fd >= 0) {
|
||||
close (inotify_fd);
|
||||
inotify_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
optgroup_inotify_available (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#else /* !HAVE_SYS_INOTIFY_H */
|
||||
int
|
||||
optgroup_inotify_available (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Because inotify_init does NEED_ROOT, NEED_INOTIFY implies NEED_ROOT. */
|
||||
#define NEED_INOTIFY(errcode) \
|
||||
@@ -67,7 +72,6 @@ optgroup_inotify_available (void)
|
||||
int
|
||||
do_inotify_init (int max_events)
|
||||
{
|
||||
#ifdef HAVE_SYS_INOTIFY_H
|
||||
FILE *fp;
|
||||
|
||||
NEED_ROOT (, return -1);
|
||||
@@ -118,15 +122,11 @@ do_inotify_init (int max_events)
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
do_inotify_close (void)
|
||||
{
|
||||
#ifdef HAVE_SYS_INOTIFY_H
|
||||
NEED_INOTIFY (-1);
|
||||
|
||||
if (inotify_fd == -1) {
|
||||
@@ -143,15 +143,11 @@ do_inotify_close (void)
|
||||
inotify_posn = 0;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int64_t
|
||||
do_inotify_add_watch (const char *path, int mask)
|
||||
{
|
||||
#ifdef HAVE_SYS_INOTIFY_H
|
||||
int64_t r;
|
||||
char *buf;
|
||||
|
||||
@@ -171,15 +167,11 @@ do_inotify_add_watch (const char *path, int mask)
|
||||
}
|
||||
|
||||
return r;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
do_inotify_rm_watch (int wd)
|
||||
{
|
||||
#ifdef HAVE_SYS_INOTIFY_H
|
||||
NEED_INOTIFY (-1);
|
||||
|
||||
if (inotify_rm_watch (inotify_fd, wd) == -1) {
|
||||
@@ -188,15 +180,11 @@ do_inotify_rm_watch (int wd)
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
guestfs_int_inotify_event_list *
|
||||
do_inotify_read (void)
|
||||
{
|
||||
#ifdef HAVE_SYS_INOTIFY_H
|
||||
int space;
|
||||
guestfs_int_inotify_event_list *ret;
|
||||
|
||||
@@ -253,6 +241,12 @@ do_inotify_read (void)
|
||||
#error "this code needs fixing so it works on non-GCC compilers"
|
||||
#endif
|
||||
|
||||
/* Check event->len is reasonable (note the field is uint32_t). */
|
||||
if (event->len > PATH_MAX) {
|
||||
reply_with_error ("event->len = %" PRIu32 " > PATH_MAX", event->len);
|
||||
goto error;
|
||||
}
|
||||
|
||||
np = realloc (ret->guestfs_int_inotify_event_list_val,
|
||||
(ret->guestfs_int_inotify_event_list_len + 1) *
|
||||
sizeof (guestfs_int_inotify_event));
|
||||
@@ -302,17 +296,12 @@ do_inotify_read (void)
|
||||
xdr_free ((xdrproc_t) xdr_guestfs_int_inotify_event_list, (char *) ret);
|
||||
free (ret);
|
||||
return NULL;
|
||||
#else
|
||||
NOT_AVAILABLE (NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
char **
|
||||
do_inotify_files (void)
|
||||
{
|
||||
#ifdef HAVE_SYS_INOTIFY_H
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (ret);
|
||||
unsigned int i;
|
||||
FILE *fp = NULL;
|
||||
guestfs_int_inotify_event_list *events;
|
||||
@@ -369,23 +358,23 @@ do_inotify_files (void)
|
||||
}
|
||||
|
||||
while (fgets (buf, sizeof buf, fp) != NULL) {
|
||||
int len = strlen (buf);
|
||||
size_t len = strlen (buf);
|
||||
|
||||
if (len > 0 && buf[len-1] == '\n')
|
||||
buf[len-1] = '\0';
|
||||
|
||||
if (add_string (&ret, &size, &alloc, buf) == -1)
|
||||
if (add_string (&ret, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
|
||||
fclose (fp); /* implicitly closes fd */
|
||||
fp = NULL;
|
||||
|
||||
if (add_string (&ret, &size, &alloc, NULL) == -1)
|
||||
if (end_stringsbuf (&ret) == -1)
|
||||
goto error;
|
||||
|
||||
unlink (tempfile);
|
||||
return ret;
|
||||
return ret.argv;
|
||||
|
||||
error:
|
||||
if (fp != NULL)
|
||||
@@ -393,7 +382,54 @@ do_inotify_files (void)
|
||||
|
||||
unlink (tempfile);
|
||||
return NULL;
|
||||
#else
|
||||
NOT_AVAILABLE (NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* !HAVE_SYS_INOTIFY_H */
|
||||
|
||||
/* Note that the wrapper code (daemon/stubs.c) ensures that the
|
||||
* functions below are never called because optgroup_inotify_available
|
||||
* returns false.
|
||||
*/
|
||||
int
|
||||
optgroup_inotify_available (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_inotify_init (int max_events)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_inotify_close (void)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int64_t
|
||||
do_inotify_add_watch (const char *path, int mask)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_inotify_rm_watch (int wd)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
guestfs_int_inotify_event_list *
|
||||
do_inotify_read (void)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
char **
|
||||
do_inotify_files (void)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
46
daemon/internal.c
Normal file
46
daemon/internal.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2012 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.
|
||||
*/
|
||||
|
||||
/* Internal functions are not part of the public API. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
|
||||
/* Older versions of libguestfs used to issue separate 'umount_all'
|
||||
* and 'sync' commands just before closing the handle. Since
|
||||
* libguestfs 1.9.7 the library issues this 'internal_autosync'
|
||||
* internal operation instead, allowing more control in the daemon.
|
||||
*/
|
||||
int
|
||||
do_internal_autosync (void)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
if (autosync_umount)
|
||||
r = do_umount_all ();
|
||||
|
||||
sync_disks ();
|
||||
|
||||
return r;
|
||||
}
|
||||
292
daemon/isoinfo.c
Normal file
292
daemon/isoinfo.c
Normal file
@@ -0,0 +1,292 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2012 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 <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "guestfs_protocol.h"
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
|
||||
static int
|
||||
parse_uint32 (uint32_t *ret, const char *str)
|
||||
{
|
||||
uint32_t r;
|
||||
|
||||
if (sscanf (str, "%" SCNu32, &r) != 1) {
|
||||
reply_with_error ("cannot parse numeric field from isoinfo: %s", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ret = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is always in a fixed format:
|
||||
* "2012 03 16 11:05:46.00"
|
||||
* or if the field is not present, then:
|
||||
* "0000 00 00 00:00:00.00"
|
||||
*/
|
||||
static int
|
||||
parse_time_t (int64_t *ret, const char *str)
|
||||
{
|
||||
struct tm tm;
|
||||
time_t r;
|
||||
|
||||
if (STREQ (str, "0000 00 00 00:00:00.00")) {
|
||||
*ret = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sscanf (str, "%04d %02d %02d %02d:%02d:%02d",
|
||||
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
|
||||
&tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
|
||||
reply_with_error ("cannot parse date from isoinfo: %s", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Adjust fields. */
|
||||
tm.tm_year -= 1900;
|
||||
tm.tm_mon--;
|
||||
tm.tm_isdst = -1;
|
||||
|
||||
/* Convert to time_t. */
|
||||
r = timegm (&tm);
|
||||
if (r == -1) {
|
||||
reply_with_error ("invalid date or time: %s", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ret = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static guestfs_int_isoinfo *
|
||||
parse_isoinfo (char **lines)
|
||||
{
|
||||
guestfs_int_isoinfo *ret;
|
||||
size_t i;
|
||||
|
||||
ret = calloc (1, sizeof *ret);
|
||||
if (ret == NULL) {
|
||||
reply_with_perror ("calloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Default each int field in the struct to -1. */
|
||||
ret->iso_volume_space_size = (uint32_t) -1;
|
||||
ret->iso_volume_set_size = (uint32_t) -1;
|
||||
ret->iso_volume_sequence_number = (uint32_t) -1;
|
||||
ret->iso_logical_block_size = (uint32_t) -1;
|
||||
ret->iso_volume_creation_t = -1;
|
||||
ret->iso_volume_modification_t = -1;
|
||||
ret->iso_volume_expiration_t = -1;
|
||||
ret->iso_volume_effective_t = -1;
|
||||
|
||||
for (i = 0; lines[i] != NULL; ++i) {
|
||||
if (STRPREFIX (lines[i], "System id: ")) {
|
||||
ret->iso_system_id = strdup (&lines[i][11]);
|
||||
if (ret->iso_system_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Volume id: ")) {
|
||||
ret->iso_volume_id = strdup (&lines[i][11]);
|
||||
if (ret->iso_volume_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Volume set id: ")) {
|
||||
ret->iso_volume_set_id = strdup (&lines[i][15]);
|
||||
if (ret->iso_volume_set_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Publisher id: ")) {
|
||||
ret->iso_publisher_id = strdup (&lines[i][14]);
|
||||
if (ret->iso_publisher_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Data preparer id: ")) {
|
||||
ret->iso_data_preparer_id = strdup (&lines[i][18]);
|
||||
if (ret->iso_data_preparer_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Application id: ")) {
|
||||
ret->iso_application_id = strdup (&lines[i][16]);
|
||||
if (ret->iso_application_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Copyright File id: ")) {
|
||||
ret->iso_copyright_file_id = strdup (&lines[i][19]);
|
||||
if (ret->iso_copyright_file_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Abstract File id: ")) {
|
||||
ret->iso_abstract_file_id = strdup (&lines[i][18]);
|
||||
if (ret->iso_abstract_file_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Bibliographic File id: ")) {
|
||||
ret->iso_bibliographic_file_id = strdup (&lines[i][23]);
|
||||
if (ret->iso_bibliographic_file_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Volume size is: ")) {
|
||||
if (parse_uint32 (&ret->iso_volume_space_size, &lines[i][16]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Volume set size is: ")) {
|
||||
if (parse_uint32 (&ret->iso_volume_set_size, &lines[i][20]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Volume set sequence number is: ")) {
|
||||
if (parse_uint32 (&ret->iso_volume_sequence_number, &lines[i][31]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Logical block size is: ")) {
|
||||
if (parse_uint32 (&ret->iso_logical_block_size, &lines[i][23]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Creation Date: ")) {
|
||||
if (parse_time_t (&ret->iso_volume_creation_t, &lines[i][19]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Modification Date: ")) {
|
||||
if (parse_time_t (&ret->iso_volume_modification_t, &lines[i][19]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Expiration Date: ")) {
|
||||
if (parse_time_t (&ret->iso_volume_expiration_t, &lines[i][19]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Effective Date: ")) {
|
||||
if (parse_time_t (&ret->iso_volume_effective_t, &lines[i][19]) == -1)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Any string fields which were not set above will be NULL. However
|
||||
* we cannot return NULL fields in structs, so we convert these to
|
||||
* empty strings here.
|
||||
*/
|
||||
if (ret->iso_system_id == NULL) {
|
||||
ret->iso_system_id = strdup ("");
|
||||
if (ret->iso_system_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_volume_id == NULL) {
|
||||
ret->iso_volume_id = strdup ("");
|
||||
if (ret->iso_volume_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_volume_set_id == NULL) {
|
||||
ret->iso_volume_set_id = strdup ("");
|
||||
if (ret->iso_volume_set_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_publisher_id == NULL) {
|
||||
ret->iso_publisher_id = strdup ("");
|
||||
if (ret->iso_publisher_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_data_preparer_id == NULL) {
|
||||
ret->iso_data_preparer_id = strdup ("");
|
||||
if (ret->iso_data_preparer_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_application_id == NULL) {
|
||||
ret->iso_application_id = strdup ("");
|
||||
if (ret->iso_application_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_copyright_file_id == NULL) {
|
||||
ret->iso_copyright_file_id = strdup ("");
|
||||
if (ret->iso_copyright_file_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_abstract_file_id == NULL) {
|
||||
ret->iso_abstract_file_id = strdup ("");
|
||||
if (ret->iso_abstract_file_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_bibliographic_file_id == NULL) {
|
||||
ret->iso_bibliographic_file_id = strdup ("");
|
||||
if (ret->iso_bibliographic_file_id == NULL) goto error;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
free (ret->iso_system_id);
|
||||
free (ret->iso_volume_id);
|
||||
free (ret->iso_volume_set_id);
|
||||
free (ret->iso_publisher_id);
|
||||
free (ret->iso_data_preparer_id);
|
||||
free (ret->iso_application_id);
|
||||
free (ret->iso_copyright_file_id);
|
||||
free (ret->iso_abstract_file_id);
|
||||
free (ret->iso_bibliographic_file_id);
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static guestfs_int_isoinfo *
|
||||
isoinfo (const char *path)
|
||||
{
|
||||
char *out = NULL, *err = NULL;
|
||||
int r;
|
||||
char **lines = NULL;
|
||||
guestfs_int_isoinfo *ret = NULL;
|
||||
|
||||
/* --debug is necessary to get additional fields, in particular
|
||||
* the date & time fields.
|
||||
*/
|
||||
r = command (&out, &err, "isoinfo", "--debug", "-d", "-i", path, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
lines = split_lines (out);
|
||||
if (lines == NULL)
|
||||
goto done;
|
||||
|
||||
ret = parse_isoinfo (lines);
|
||||
if (ret == NULL)
|
||||
goto done;
|
||||
|
||||
done:
|
||||
free (out);
|
||||
free (err);
|
||||
if (lines)
|
||||
free_strings (lines);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
guestfs_int_isoinfo *
|
||||
do_isoinfo_device (const char *device)
|
||||
{
|
||||
return isoinfo (device);
|
||||
}
|
||||
|
||||
guestfs_int_isoinfo *
|
||||
do_isoinfo (const char *path)
|
||||
{
|
||||
char *buf;
|
||||
guestfs_int_isoinfo *ret;
|
||||
|
||||
buf = sysroot_path (path);
|
||||
if (!buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = isoinfo (buf);
|
||||
free (buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
104
daemon/labels.c
Normal file
104
daemon/labels.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2012 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 <unistd.h>
|
||||
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
#include "optgroups.h"
|
||||
|
||||
static int
|
||||
e2label (const char *device, const char *label)
|
||||
{
|
||||
int r;
|
||||
char *err;
|
||||
|
||||
char prog[] = "e2label";
|
||||
if (e2prog (prog) == -1)
|
||||
return -1;
|
||||
|
||||
if (strlen (label) > EXT2_LABEL_MAX) {
|
||||
reply_with_error ("%s: ext2 labels are limited to %d bytes",
|
||||
label, EXT2_LABEL_MAX);
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = command (NULL, &err, prog, device, label, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s", err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ntfslabel (const char *device, const char *label)
|
||||
{
|
||||
int r;
|
||||
char *err;
|
||||
|
||||
/* XXX We should check if the label is longer than 128 unicode
|
||||
* characters and return an error. This is not so easy since we
|
||||
* don't have the required libraries.
|
||||
*/
|
||||
r = command (NULL, &err, "ntfslabel", device, label, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s", err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_set_label (const char *device, const char *label)
|
||||
{
|
||||
char *vfs_type;
|
||||
int r;
|
||||
|
||||
/* How we set the label depends on the filesystem type. */
|
||||
vfs_type = do_vfs_type (device);
|
||||
if (vfs_type == NULL)
|
||||
return -1;
|
||||
|
||||
if (STREQ (vfs_type, "ext2") || STREQ (vfs_type, "ext3")
|
||||
|| STREQ (vfs_type, "ext4"))
|
||||
r = e2label (device, label);
|
||||
|
||||
else if (STREQ (vfs_type, "ntfs"))
|
||||
r = ntfslabel (device, label);
|
||||
|
||||
else {
|
||||
reply_with_error ("don't know how to set the label for '%s' filesystems",
|
||||
vfs_type);
|
||||
r = -1;
|
||||
}
|
||||
|
||||
free (vfs_type);
|
||||
return r;
|
||||
}
|
||||
@@ -60,11 +60,10 @@ do_readlinklist (const char *path, char *const *names)
|
||||
ssize_t r;
|
||||
char link[PATH_MAX];
|
||||
const char *str;
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (ret);
|
||||
|
||||
CHROOT_IN;
|
||||
fd_cwd = open (path, O_RDONLY | O_DIRECTORY);
|
||||
fd_cwd = open (path, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd_cwd == -1) {
|
||||
@@ -87,7 +86,7 @@ do_readlinklist (const char *path, char *const *names)
|
||||
str = link;
|
||||
} else
|
||||
str = "";
|
||||
if (add_string (&ret, &size, &alloc, str) == -1) {
|
||||
if (add_string (&ret, str) == -1) {
|
||||
close (fd_cwd);
|
||||
return NULL;
|
||||
}
|
||||
@@ -95,10 +94,10 @@ do_readlinklist (const char *path, char *const *names)
|
||||
|
||||
close (fd_cwd);
|
||||
|
||||
if (add_string (&ret, &size, &alloc, NULL) == -1)
|
||||
if (end_stringsbuf (&ret) == -1)
|
||||
return NULL;
|
||||
|
||||
return ret;
|
||||
return ret.argv;
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
41
daemon/ls.c
41
daemon/ls.c
@@ -32,8 +32,7 @@
|
||||
char **
|
||||
do_ls (const char *path)
|
||||
{
|
||||
char **r = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (ret);
|
||||
DIR *dir;
|
||||
struct dirent *d;
|
||||
|
||||
@@ -50,25 +49,27 @@ do_ls (const char *path)
|
||||
if (STREQ (d->d_name, ".") || STREQ (d->d_name, ".."))
|
||||
continue;
|
||||
|
||||
if (add_string (&r, &size, &alloc, d->d_name) == -1) {
|
||||
if (add_string (&ret, d->d_name) == -1) {
|
||||
closedir (dir);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (add_string (&r, &size, &alloc, NULL) == -1) {
|
||||
if (ret.size > 0)
|
||||
sort_strings (ret.argv, ret.size);
|
||||
|
||||
if (end_stringsbuf (&ret) == -1) {
|
||||
closedir (dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (closedir (dir) == -1) {
|
||||
reply_with_perror ("closedir: %s", path);
|
||||
free_strings (r);
|
||||
free_stringslen (ret.argv, ret.size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sort_strings (r, size-1);
|
||||
return r;
|
||||
return ret.argv;
|
||||
}
|
||||
|
||||
/* Because we can't chroot and run the ls command (since 'ls' won't
|
||||
@@ -102,3 +103,29 @@ do_ll (const char *path)
|
||||
free (err);
|
||||
return out; /* caller frees */
|
||||
}
|
||||
|
||||
char *
|
||||
do_llz (const char *path)
|
||||
{
|
||||
int r;
|
||||
char *out, *err;
|
||||
char *spath;
|
||||
|
||||
spath = sysroot_path (path);
|
||||
if (!spath) {
|
||||
reply_with_perror ("malloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = command (&out, &err, "ls", "-laZ", spath, NULL);
|
||||
free (spath);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s", err);
|
||||
free (out);
|
||||
free (err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return out; /* caller frees */
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2010-2011 Red Hat Inc.
|
||||
* Copyright (C) 2010-2012 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
|
||||
|
||||
157
daemon/lvm.c
157
daemon/lvm.c
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 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
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
|
||||
@@ -45,9 +46,8 @@ static char **
|
||||
convert_lvm_output (char *out, const char *prefix)
|
||||
{
|
||||
char *p, *pend;
|
||||
char **r = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
int len;
|
||||
DECLARE_STRINGSBUF (ret);
|
||||
size_t len;
|
||||
char buf[256];
|
||||
char *str;
|
||||
|
||||
@@ -79,7 +79,7 @@ convert_lvm_output (char *out, const char *prefix)
|
||||
} else
|
||||
str = p;
|
||||
|
||||
if (add_string (&r, &size, &alloc, str) == -1) {
|
||||
if (add_string (&ret, str) == -1) {
|
||||
free (out);
|
||||
return NULL;
|
||||
}
|
||||
@@ -89,11 +89,13 @@ convert_lvm_output (char *out, const char *prefix)
|
||||
|
||||
free (out);
|
||||
|
||||
if (add_string (&r, &size, &alloc, NULL) == -1)
|
||||
if (ret.size > 0)
|
||||
sort_strings (ret.argv, ret.size);
|
||||
|
||||
if (end_stringsbuf (&ret) == -1)
|
||||
return NULL;
|
||||
|
||||
sort_strings (r, size-1);
|
||||
return r;
|
||||
return ret.argv;
|
||||
}
|
||||
|
||||
char **
|
||||
@@ -261,6 +263,36 @@ do_lvcreate (const char *logvol, const char *volgroup, int mbytes)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_lvcreate_free (const char *logvol, const char *volgroup, int percent)
|
||||
{
|
||||
char *err;
|
||||
int r;
|
||||
|
||||
if (percent < 0 || percent > 100) {
|
||||
reply_with_error ("percentage must be [0..100] (was %d)", percent);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char size[64];
|
||||
snprintf (size, sizeof size, "%d%%FREE", percent);
|
||||
|
||||
r = command (NULL, &err,
|
||||
"lvm", "lvcreate",
|
||||
"-l", size, "-n", logvol, volgroup, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s", err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
|
||||
udev_settle ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_lvresize (const char *logvol, int mbytes)
|
||||
{
|
||||
@@ -316,7 +348,8 @@ int
|
||||
do_lvm_remove_all (void)
|
||||
{
|
||||
char **xs;
|
||||
int i, r;
|
||||
size_t i;
|
||||
int r;
|
||||
char *err;
|
||||
|
||||
/* Remove LVs. */
|
||||
@@ -769,8 +802,7 @@ do_lvm_canonical_lv_name (const char *device)
|
||||
char **
|
||||
do_list_dm_devices (void)
|
||||
{
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (ret);
|
||||
struct dirent *d;
|
||||
DIR *dir;
|
||||
int r;
|
||||
@@ -802,7 +834,7 @@ do_list_dm_devices (void)
|
||||
/* Ignore dm devices which are LVs. */
|
||||
r = lv_canonical (devname, NULL);
|
||||
if (r == -1) {
|
||||
free_stringslen (ret, size);
|
||||
free_stringslen (ret.argv, ret.size);
|
||||
closedir (dir);
|
||||
return NULL;
|
||||
}
|
||||
@@ -810,7 +842,7 @@ do_list_dm_devices (void)
|
||||
continue;
|
||||
|
||||
/* Not an LV, so add it. */
|
||||
if (add_string (&ret, &size, &alloc, devname) == -1) {
|
||||
if (add_string (&ret, devname) == -1) {
|
||||
closedir (dir);
|
||||
return NULL;
|
||||
}
|
||||
@@ -819,7 +851,7 @@ do_list_dm_devices (void)
|
||||
/* Did readdir fail? */
|
||||
if (errno != 0) {
|
||||
reply_with_perror ("readdir: /dev/mapper");
|
||||
free_stringslen (ret, size);
|
||||
free_stringslen (ret.argv, ret.size);
|
||||
closedir (dir);
|
||||
return NULL;
|
||||
}
|
||||
@@ -827,17 +859,104 @@ do_list_dm_devices (void)
|
||||
/* Close the directory handle. */
|
||||
if (closedir (dir) == -1) {
|
||||
reply_with_perror ("closedir: /dev/mapper");
|
||||
free_stringslen (ret, size);
|
||||
free_stringslen (ret.argv, ret.size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Sort the output (may be empty). */
|
||||
if (ret != NULL)
|
||||
sort_strings (ret, size);
|
||||
if (ret.size > 0)
|
||||
sort_strings (ret.argv, ret.size);
|
||||
|
||||
/* NULL-terminate the list. */
|
||||
if (add_string (&ret, &size, &alloc, NULL) == -1)
|
||||
if (end_stringsbuf (&ret) == -1)
|
||||
return NULL;
|
||||
|
||||
return ret;
|
||||
return ret.argv;
|
||||
}
|
||||
|
||||
char *
|
||||
do_vgmeta (const char *vg, size_t *size_r)
|
||||
{
|
||||
char *err;
|
||||
int fd, r;
|
||||
char tmp[] = "/tmp/vgmetaXXXXXX";
|
||||
size_t alloc, size, max;
|
||||
ssize_t rs;
|
||||
char *buf, *buf2;
|
||||
|
||||
/* Make a temporary file. */
|
||||
fd = mkstemp (tmp);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("mkstemp");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
close (fd);
|
||||
|
||||
r = command (NULL, &err, "lvm", "vgcfgbackup", "-f", tmp, vg, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("vgcfgbackup: %s", err);
|
||||
free (err);
|
||||
return NULL;
|
||||
}
|
||||
free (err);
|
||||
|
||||
/* Now read back the temporary file. */
|
||||
fd = open (tmp, O_RDONLY|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
reply_with_error ("%s", tmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read up to GUESTFS_MESSAGE_MAX - <overhead> bytes. If it's
|
||||
* larger than that, we need to return an error instead (for
|
||||
* correctness).
|
||||
*/
|
||||
max = GUESTFS_MESSAGE_MAX - 1000;
|
||||
buf = NULL;
|
||||
size = alloc = 0;
|
||||
|
||||
for (;;) {
|
||||
if (size >= alloc) {
|
||||
alloc += 8192;
|
||||
if (alloc > max) {
|
||||
reply_with_error ("metadata is too large for message buffer");
|
||||
free (buf);
|
||||
close (fd);
|
||||
return NULL;
|
||||
}
|
||||
buf2 = realloc (buf, alloc);
|
||||
if (buf2 == NULL) {
|
||||
reply_with_perror ("realloc");
|
||||
free (buf);
|
||||
close (fd);
|
||||
return NULL;
|
||||
}
|
||||
buf = buf2;
|
||||
}
|
||||
|
||||
rs = read (fd, buf + size, alloc - size);
|
||||
if (rs == -1) {
|
||||
reply_with_perror ("read: %s", tmp);
|
||||
free (buf);
|
||||
close (fd);
|
||||
return NULL;
|
||||
}
|
||||
if (rs == 0)
|
||||
break;
|
||||
if (rs > 0)
|
||||
size += rs;
|
||||
}
|
||||
|
||||
if (close (fd) == -1) {
|
||||
reply_with_perror ("close: %s", tmp);
|
||||
free (buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unlink (tmp);
|
||||
|
||||
*size_r = size;
|
||||
|
||||
return buf; /* caller will free */
|
||||
}
|
||||
|
||||
237
daemon/md.c
237
daemon/md.c
@@ -180,8 +180,7 @@ glob_errfunc (const char *epath, int eerrno)
|
||||
char **
|
||||
do_list_md_devices (void)
|
||||
{
|
||||
char **r = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (ret);
|
||||
glob_t mds;
|
||||
|
||||
memset(&mds, 0, sizeof(mds));
|
||||
@@ -218,44 +217,44 @@ do_list_md_devices (void)
|
||||
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 (&ret, dev) == -1) goto error;
|
||||
}
|
||||
|
||||
if (add_string_nodup (&r, &size, &alloc, NULL) == -1) goto error;
|
||||
if (end_stringsbuf (&ret) == -1) goto error;
|
||||
globfree (&mds);
|
||||
|
||||
return r;
|
||||
return ret.argv;
|
||||
|
||||
error:
|
||||
globfree (&mds);
|
||||
if (r != NULL) free_strings (r);
|
||||
if (ret.argv != NULL)
|
||||
free_stringslen (ret.argv, ret.size);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char **
|
||||
do_md_detail(const char *md)
|
||||
{
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
char *out = NULL, *err = NULL;
|
||||
char **lines = NULL;
|
||||
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (ret);
|
||||
|
||||
const char *mdadm[] = { "mdadm", "-D", "--export", md, NULL };
|
||||
r = commandv(&out, &err, mdadm);
|
||||
r = commandv (&out, &err, mdadm);
|
||||
if (r == -1) {
|
||||
reply_with_error("%s", err);
|
||||
reply_with_error ("%s", err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Split the command output into lines */
|
||||
lines = split_lines(out);
|
||||
if (lines == NULL) {
|
||||
reply_with_perror("malloc");
|
||||
lines = split_lines (out);
|
||||
if (lines == NULL)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Parse the output of mdadm -D --export:
|
||||
* MD_LEVEL=raid1
|
||||
@@ -264,49 +263,52 @@ do_md_detail(const char *md)
|
||||
* MD_UUID=cfa81b59:b6cfbd53:3f02085b:58f4a2e1
|
||||
* MD_NAME=localhost.localdomain:0
|
||||
*/
|
||||
for (char **i = lines; *i != NULL; i++) {
|
||||
char *line = *i;
|
||||
for (i = 0; lines[i] != NULL; ++i) {
|
||||
char *line = lines[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, '=');
|
||||
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_")) {
|
||||
if (STRPREFIX (line, "MD_")) {
|
||||
line += 3;
|
||||
for (char *j = line; *j != '\0'; j++) {
|
||||
*j = c_tolower(*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;
|
||||
if (add_string (&ret, line) == -1 ||
|
||||
add_string (&ret, 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);
|
||||
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 */
|
||||
free (out);
|
||||
free (err);
|
||||
free_strings (lines);
|
||||
|
||||
if (add_string(&ret, &size, &alloc, NULL) == -1) return NULL;
|
||||
if (end_stringsbuf (&ret) == -1)
|
||||
return NULL;
|
||||
|
||||
return ret;
|
||||
return ret.argv;
|
||||
|
||||
error:
|
||||
free(out);
|
||||
free(err);
|
||||
if (lines) free(lines);
|
||||
if (ret) free_strings(ret);
|
||||
free (out);
|
||||
free (err);
|
||||
if (lines)
|
||||
free_strings (lines);
|
||||
if (ret.argv != NULL)
|
||||
free_stringslen (ret.argv, ret.size);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -324,5 +326,178 @@ do_md_stop(const char *md)
|
||||
free(err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t
|
||||
count_spaces (const char *line)
|
||||
{
|
||||
size_t r = 0;
|
||||
while (*line) {
|
||||
if (*line == ' ')
|
||||
r++;
|
||||
line++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Parse a line like: "active raid1 sdb1[0] sdc1[1](F)" */
|
||||
static guestfs_int_mdstat_list *
|
||||
parse_md_stat_line (char *line)
|
||||
{
|
||||
guestfs_int_mdstat_list *ret;
|
||||
guestfs_int_mdstat *t;
|
||||
size_t spaces, n, i, len;
|
||||
char *next;
|
||||
char *p, *q;
|
||||
|
||||
ret = malloc (sizeof *ret);
|
||||
if (!ret) {
|
||||
reply_with_perror ("malloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We don't know exactly how many entries we will need yet, but we
|
||||
* can estimate it, and this will always be an over-estimate.
|
||||
*/
|
||||
spaces = count_spaces (line);
|
||||
ret->guestfs_int_mdstat_list_val =
|
||||
calloc (spaces+1, sizeof (struct guestfs_int_mdstat));
|
||||
if (ret->guestfs_int_mdstat_list_val == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (n = 0; *line; line = next) {
|
||||
len = strcspn (line, " ");
|
||||
if (line[len] == '\0')
|
||||
next = &line[len];
|
||||
else {
|
||||
line[len] = '\0';
|
||||
next = &line[len+1];
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
printf ("mdstat: %s\n", line);
|
||||
|
||||
/* Looking for entries that contain "[..]", skip ones which don't. */
|
||||
p = strchr (line, '[');
|
||||
if (p == NULL)
|
||||
continue;
|
||||
q = strchr (line, ']');
|
||||
if (q == NULL)
|
||||
continue;
|
||||
if (p > q)
|
||||
continue;
|
||||
|
||||
ret->guestfs_int_mdstat_list_len = n+1;
|
||||
t = &ret->guestfs_int_mdstat_list_val[n];
|
||||
|
||||
/* Device name is everything before the '[' character, but we
|
||||
* need to prefix with /dev/.
|
||||
*/
|
||||
if (p == line) {
|
||||
reply_with_error ("device entry is too short: %s", line);
|
||||
goto error;
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
if (asprintf (&t->mdstat_device, "/dev/%s", line) == -1) {
|
||||
reply_with_perror ("asprintf");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Device index is the number after '['. */
|
||||
line = p+1;
|
||||
*q = '\0';
|
||||
if (sscanf (line, "%" SCNi32, &t->mdstat_index) != 1) {
|
||||
reply_with_error ("not a device number: %s", line);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Looking for flags "(F)(S)...". */
|
||||
line = q+1;
|
||||
len = strlen (line);
|
||||
t->mdstat_flags = malloc (len+1);
|
||||
if (!t->mdstat_flags) {
|
||||
reply_with_error ("malloc");
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; *line; line++) {
|
||||
if (c_isalpha (*line))
|
||||
t->mdstat_flags[i++] = *line;
|
||||
}
|
||||
t->mdstat_flags[i] = '\0';
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
for (i = 0; i <= spaces; ++i) {
|
||||
free (ret->guestfs_int_mdstat_list_val[i].mdstat_device);
|
||||
free (ret->guestfs_int_mdstat_list_val[i].mdstat_flags);
|
||||
}
|
||||
free (ret->guestfs_int_mdstat_list_val);
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern guestfs_int_mdstat_list *
|
||||
do_md_stat (const char *md)
|
||||
{
|
||||
size_t mdlen;
|
||||
FILE *fp;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t n;
|
||||
guestfs_int_mdstat_list *ret = NULL;
|
||||
|
||||
if (STRPREFIX (md, "/dev/"))
|
||||
md += 5;
|
||||
mdlen = strlen (md);
|
||||
|
||||
fp = fopen ("/proc/mdstat", "r");
|
||||
if (fp == NULL) {
|
||||
reply_with_perror ("fopen: %s", "/proc/mdstat");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Search for a line which begins with "<md> : ". */
|
||||
while ((n = getline (&line, &len, fp)) != -1) {
|
||||
if (STRPREFIX (line, md) &&
|
||||
line[mdlen] == ' ' && line[mdlen+1] == ':' && line[mdlen+2] == ' ') {
|
||||
/* Found it. */
|
||||
ret = parse_md_stat_line (&line[mdlen+3]);
|
||||
if (!ret) {
|
||||
free (line);
|
||||
fclose (fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Stop parsing the mdstat file after we've found the line
|
||||
* we are interested in.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (line);
|
||||
|
||||
if (fclose (fp) == EOF) {
|
||||
reply_with_perror ("fclose: %s", "/proc/mdstat");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Did we find the line? */
|
||||
if (!ret) {
|
||||
reply_with_error ("%s: MD device not found", md);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 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
|
||||
@@ -44,13 +44,17 @@ 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;
|
||||
ADD_ARG (argv, i, mke2fs);
|
||||
@@ -64,8 +68,7 @@ do_mkfs_opts (const char *fstype, const char *device, int blocksize,
|
||||
/* 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"))
|
||||
if (extfs)
|
||||
ADD_ARG (argv, i, "-F");
|
||||
|
||||
/* mkfs.ntfs requires the -Q argument otherwise it writes zeroes
|
||||
@@ -77,16 +80,13 @@ do_mkfs_opts (const char *fstype, const char *device, int blocksize,
|
||||
|
||||
/* 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"))
|
||||
ADD_ARG (argv, i, "-f");
|
||||
|
||||
/* Same for JFS. */
|
||||
if (STREQ (fstype, "jfs"))
|
||||
ADD_ARG (argv, i, "-f");
|
||||
|
||||
if (STREQ (fstype, "xfs"))
|
||||
ADD_ARG (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")) {
|
||||
@@ -133,6 +133,11 @@ do_mkfs_opts (const char *fstype, const char *device, int blocksize,
|
||||
ADD_ARG (argv, i, "-c");
|
||||
ADD_ARG (argv, i, blocksize_str);
|
||||
}
|
||||
else if (STREQ (fstype, "btrfs")) {
|
||||
/* For btrfs, blocksize cannot be specified (RHBZ#807905). */
|
||||
reply_with_error ("blocksize cannot be set on btrfs filesystems, use 'mkfs-btrfs'");
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
/* For all other filesystem types, try the -b option. */
|
||||
snprintf (blocksize_str, sizeof blocksize_str, "%d", blocksize);
|
||||
@@ -147,8 +152,7 @@ do_mkfs_opts (const char *fstype, const char *device, int blocksize,
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -37,18 +37,10 @@ optgroup_mknod_available (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
int
|
||||
optgroup_mknod_available (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
do_mknod (int mode, int devmajor, int devminor, const char *path)
|
||||
{
|
||||
#ifdef HAVE_MKNOD
|
||||
int r;
|
||||
|
||||
if (mode < 0) {
|
||||
@@ -66,9 +58,6 @@ do_mknod (int mode, int devmajor, int devminor, const char *path)
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@@ -88,3 +77,37 @@ do_mknod_c (int mode, int devmajor, int devminor, const char *path)
|
||||
{
|
||||
return do_mknod (mode | S_IFCHR, devmajor, devminor, path);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int
|
||||
optgroup_mknod_available (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_mknod (int mode, int devmajor, int devminor, const char *path)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_mkfifo (int mode, const char *path)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_mknod_b (int mode, int devmajor, int devminor, const char *path)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_mknod_c (int mode, int devmajor, int devminor, const char *path)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -65,6 +65,49 @@ is_root_mounted (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return true iff 'device' is mounted under /sysroot.
|
||||
* 1 : true, device is mounted
|
||||
* 0 : false, device is not mounted
|
||||
* -1 : error, reply_with_* has been called
|
||||
*/
|
||||
int
|
||||
is_device_mounted (const char *device)
|
||||
{
|
||||
FILE *fp;
|
||||
struct mntent *m;
|
||||
struct stat stat1, stat2;
|
||||
|
||||
if (stat (device, &stat1) == -1) {
|
||||
reply_with_perror ("stat: %s", device);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* NB: Eventually we should aim to parse /proc/self/mountinfo, but
|
||||
* that requires custom parsing code.
|
||||
*/
|
||||
fp = setmntent ("/proc/mounts", "r");
|
||||
if (fp == NULL) {
|
||||
perror ("/proc/mounts");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while ((m = getmntent (fp)) != NULL) {
|
||||
if ((sysroot_len > 0 && STREQ (m->mnt_dir, sysroot)) ||
|
||||
(STRPREFIX (m->mnt_dir, sysroot) && m->mnt_dir[sysroot_len] == '/')) {
|
||||
if (stat (m->mnt_fsname, &stat2) == 0) {
|
||||
if (stat1.st_rdev == stat2.st_rdev) {
|
||||
/* found it */
|
||||
endmntent (fp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
endmntent (fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The "simple mount" call offers no complex options, you can just
|
||||
* mount a device on a mountpoint. The variations like mount_ro,
|
||||
* mount_options and mount_vfs let you set progressively more things.
|
||||
@@ -181,8 +224,7 @@ mounts_or_mountpoints (int mp)
|
||||
{
|
||||
FILE *fp;
|
||||
struct mntent *m;
|
||||
char **ret = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (ret);
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
@@ -198,42 +240,43 @@ mounts_or_mountpoints (int mp)
|
||||
while ((m = getmntent (fp)) != NULL) {
|
||||
/* Allow a mount directory like "/sysroot". */
|
||||
if (sysroot_len > 0 && STREQ (m->mnt_dir, sysroot)) {
|
||||
if (add_string (&ret, &size, &alloc, m->mnt_fsname) == -1) {
|
||||
if (add_string (&ret, m->mnt_fsname) == -1) {
|
||||
error:
|
||||
endmntent (fp);
|
||||
return NULL;
|
||||
}
|
||||
if (mp &&
|
||||
add_string (&ret, &size, &alloc, "/") == -1)
|
||||
add_string (&ret, "/") == -1)
|
||||
goto error;
|
||||
}
|
||||
/* Or allow a mount directory like "/sysroot/...". */
|
||||
if (STRPREFIX (m->mnt_dir, sysroot) && m->mnt_dir[sysroot_len] == '/') {
|
||||
if (add_string (&ret, &size, &alloc, m->mnt_fsname) == -1)
|
||||
if (add_string (&ret, m->mnt_fsname) == -1)
|
||||
goto error;
|
||||
if (mp &&
|
||||
add_string (&ret, &size, &alloc, &m->mnt_dir[sysroot_len]) == -1)
|
||||
add_string (&ret, &m->mnt_dir[sysroot_len]) == -1)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
endmntent (fp);
|
||||
|
||||
if (add_string (&ret, &size, &alloc, NULL) == -1)
|
||||
if (end_stringsbuf (&ret) == -1)
|
||||
return NULL;
|
||||
|
||||
/* Convert /dev/mapper LV paths into canonical paths (RHBZ#646432). */
|
||||
for (i = 0; ret[i] != NULL; i += mp ? 2 : 1) {
|
||||
if (STRPREFIX (ret[i], "/dev/mapper/") || STRPREFIX (ret[i], "/dev/dm-")) {
|
||||
for (i = 0; ret.argv[i] != NULL; i += mp ? 2 : 1) {
|
||||
if (STRPREFIX (ret.argv[i], "/dev/mapper/") ||
|
||||
STRPREFIX (ret.argv[i], "/dev/dm-")) {
|
||||
char *canonical;
|
||||
r = lv_canonical (ret[i], &canonical);
|
||||
r = lv_canonical (ret.argv[i], &canonical);
|
||||
if (r == -1) {
|
||||
free_strings (ret);
|
||||
free_stringslen (ret.argv, ret.size);
|
||||
return NULL;
|
||||
}
|
||||
if (r == 1) {
|
||||
free (ret[i]);
|
||||
ret[i] = canonical;
|
||||
free (ret.argv[i]);
|
||||
ret.argv[i] = canonical;
|
||||
}
|
||||
/* Ignore the case where r == 0. This might happen where
|
||||
* eg. a LUKS /dev/mapper device is mounted, but that won't
|
||||
@@ -242,7 +285,7 @@ mounts_or_mountpoints (int mp)
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.argv;
|
||||
}
|
||||
|
||||
char **
|
||||
@@ -282,10 +325,10 @@ do_umount_all (void)
|
||||
{
|
||||
FILE *fp;
|
||||
struct mntent *m;
|
||||
char **mounts = NULL;
|
||||
int size = 0, alloc = 0;
|
||||
DECLARE_STRINGSBUF (mounts);
|
||||
char *err;
|
||||
int i, r;
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
/* NB: Eventually we should aim to parse /proc/self/mountinfo, but
|
||||
* that requires custom parsing code.
|
||||
@@ -299,14 +342,14 @@ do_umount_all (void)
|
||||
while ((m = getmntent (fp)) != NULL) {
|
||||
/* Allow a mount directory like "/sysroot". */
|
||||
if (sysroot_len > 0 && STREQ (m->mnt_dir, sysroot)) {
|
||||
if (add_string (&mounts, &size, &alloc, m->mnt_dir) == -1) {
|
||||
if (add_string (&mounts, m->mnt_dir) == -1) {
|
||||
endmntent (fp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* Or allow a mount directory like "/sysroot/...". */
|
||||
if (STRPREFIX (m->mnt_dir, sysroot) && m->mnt_dir[sysroot_len] == '/') {
|
||||
if (add_string (&mounts, &size, &alloc, m->mnt_dir) == -1) {
|
||||
if (add_string (&mounts, m->mnt_dir) == -1) {
|
||||
endmntent (fp);
|
||||
return -1;
|
||||
}
|
||||
@@ -315,21 +358,22 @@ do_umount_all (void)
|
||||
|
||||
endmntent (fp);
|
||||
|
||||
qsort (mounts, size, sizeof (char *), compare_longest_first);
|
||||
if (mounts.size > 0)
|
||||
qsort (mounts.argv, mounts.size, sizeof (char *), compare_longest_first);
|
||||
|
||||
/* Unmount them. */
|
||||
for (i = 0; i < size; ++i) {
|
||||
r = command (NULL, &err, "umount", mounts[i], NULL);
|
||||
for (i = 0; i < mounts.size; ++i) {
|
||||
r = command (NULL, &err, "umount", mounts.argv[i], NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("umount: %s: %s", mounts[i], err);
|
||||
reply_with_error ("umount: %s: %s", mounts.argv[i], err);
|
||||
free (err);
|
||||
free_stringslen (mounts, size);
|
||||
free_stringslen (mounts.argv, mounts.size);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
}
|
||||
|
||||
free_stringslen (mounts, size);
|
||||
free_stringslen (mounts.argv, mounts.size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2010 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 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
|
||||
@@ -115,3 +115,32 @@ do_ntfsresize_size (const char *device, int64_t size)
|
||||
optargs_bitmask = GUESTFS_NTFSRESIZE_OPTS_SIZE_BITMASK;
|
||||
return do_ntfsresize_opts (device, size, 0);
|
||||
}
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_ntfsfix (const char *device, int clearbadsectors)
|
||||
{
|
||||
const char *argv[MAX_ARGS];
|
||||
size_t i = 0;
|
||||
int r;
|
||||
char *err;
|
||||
|
||||
ADD_ARG (argv, i, "ntfsfix");
|
||||
|
||||
if ((optargs_bitmask & GUESTFS_NTFSFIX_CLEARBADSECTORS_BITMASK) &&
|
||||
clearbadsectors)
|
||||
ADD_ARG (argv, i, "-b");
|
||||
|
||||
ADD_ARG (argv, i, device);
|
||||
ADD_ARG (argv, i, NULL);
|
||||
|
||||
r = commandv (NULL, &err, argv);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s: %s", device, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
212
daemon/ntfsclone.c
Normal file
212
daemon/ntfsclone.c
Normal file
@@ -0,0 +1,212 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2012 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 <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "read-file.h"
|
||||
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
#include "optgroups.h"
|
||||
|
||||
/* Read the error file. Returns a string that the caller must free. */
|
||||
static char *
|
||||
read_error_file (char *error_file)
|
||||
{
|
||||
size_t len;
|
||||
char *str;
|
||||
|
||||
str = read_file (error_file, &len);
|
||||
if (str == NULL) {
|
||||
str = strdup ("(no error)");
|
||||
if (str == NULL) {
|
||||
perror ("strdup");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
len = strlen (str);
|
||||
}
|
||||
|
||||
/* Remove trailing \n character if any. */
|
||||
if (len > 0 && str[len-1] == '\n')
|
||||
str[--len] = '\0';
|
||||
|
||||
return str; /* caller frees */
|
||||
}
|
||||
|
||||
static int
|
||||
write_cb (void *fd_ptr, const void *buf, size_t len)
|
||||
{
|
||||
int fd = *(int *)fd_ptr;
|
||||
return xwrite (fd, buf, len);
|
||||
}
|
||||
|
||||
/* Has one FileIn parameter. */
|
||||
int
|
||||
do_ntfsclone_in (const char *device)
|
||||
{
|
||||
int err, r;
|
||||
FILE *fp;
|
||||
char *cmd;
|
||||
char error_file[] = "/tmp/ntfscloneXXXXXX";
|
||||
int fd;
|
||||
|
||||
fd = mkstemp (error_file);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("mkstemp");
|
||||
return -1;
|
||||
}
|
||||
|
||||
close (fd);
|
||||
|
||||
/* Construct the command. */
|
||||
if (asprintf_nowarn (&cmd, "ntfsclone -O %s --restore-image - 2> %s",
|
||||
device, error_file) == -1) {
|
||||
err = errno;
|
||||
r = cancel_receive ();
|
||||
errno = err;
|
||||
reply_with_perror ("asprintf");
|
||||
unlink (error_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
fprintf (stderr, "%s\n", cmd);
|
||||
|
||||
fp = popen (cmd, "w");
|
||||
if (fp == NULL) {
|
||||
err = errno;
|
||||
r = cancel_receive ();
|
||||
errno = err;
|
||||
reply_with_perror ("%s", cmd);
|
||||
unlink (error_file);
|
||||
free (cmd);
|
||||
return -1;
|
||||
}
|
||||
free (cmd);
|
||||
|
||||
/* The semantics of fwrite are too undefined, so write to the
|
||||
* file descriptor directly instead.
|
||||
*/
|
||||
fd = fileno (fp);
|
||||
|
||||
r = receive_file (write_cb, &fd);
|
||||
if (r == -1) { /* write error */
|
||||
cancel_receive ();
|
||||
char *errstr = read_error_file (error_file);
|
||||
reply_with_error ("write error on device: %s: %s", device, errstr);
|
||||
free (errstr);
|
||||
unlink (error_file);
|
||||
pclose (fp);
|
||||
return -1;
|
||||
}
|
||||
if (r == -2) { /* cancellation from library */
|
||||
/* This error is ignored by the library since it initiated the
|
||||
* cancel. Nevertheless we must send an error reply here.
|
||||
*/
|
||||
reply_with_error ("ntfsclone cancelled");
|
||||
pclose (fp);
|
||||
unlink (error_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pclose (fp) != 0) {
|
||||
char *errstr = read_error_file (error_file);
|
||||
reply_with_error ("ntfsclone subcommand failed on device: %s: %s",
|
||||
device, errstr);
|
||||
free (errstr);
|
||||
unlink (error_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
unlink (error_file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Has one FileOut parameter. */
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_ntfsclone_out (const char *device,
|
||||
int metadataonly, int rescue, int ignorefscheck,
|
||||
int preservetimestamps, int force)
|
||||
{
|
||||
int r;
|
||||
FILE *fp;
|
||||
char *cmd;
|
||||
char buf[GUESTFS_MAX_CHUNK_SIZE];
|
||||
|
||||
/* Construct the ntfsclone command. */
|
||||
if (asprintf (&cmd, "ntfsclone -o - --save-image%s%s%s%s%s %s",
|
||||
(optargs_bitmask & GUESTFS_NTFSCLONE_OUT_METADATAONLY_BITMASK) && metadataonly ? " --metadata" : "",
|
||||
(optargs_bitmask & GUESTFS_NTFSCLONE_OUT_RESCUE_BITMASK) && rescue ? " --rescue" : "",
|
||||
(optargs_bitmask & GUESTFS_NTFSCLONE_OUT_IGNOREFSCHECK_BITMASK) && ignorefscheck ? " --ignore-fs-check" : "",
|
||||
(optargs_bitmask & GUESTFS_NTFSCLONE_OUT_PRESERVETIMESTAMPS_BITMASK) && preservetimestamps ? " --preserve-timestamps" : "",
|
||||
(optargs_bitmask & GUESTFS_NTFSCLONE_OUT_FORCE_BITMASK) && force ? " --force" : "",
|
||||
device) == -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 (device);
|
||||
send_file_end (1); /* Cancel. */
|
||||
pclose (fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pclose (fp) != 0) {
|
||||
perror (device);
|
||||
send_file_end (1); /* Cancel. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (send_file_end (0)) /* Normal end of file. */
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
155
daemon/parted.c
155
daemon/parted.c
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 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
|
||||
@@ -33,45 +33,14 @@
|
||||
* Parted 1.9 sends error messages to stdout, hence use of the
|
||||
* COMMAND_FLAG_FOLD_STDOUT_ON_STDERR flag.
|
||||
*
|
||||
* parted occasionally fails to do ioctl(BLKRRPART) on the device,
|
||||
* apparently because of some internal race in the code. We attempt
|
||||
* to detect and recover from this error if we can.
|
||||
* There is a reason why we call udev_settle both before and after
|
||||
* each command. When you call close on any block device, udev kicks
|
||||
* off a rule which runs blkid to reexamine the device. We need to
|
||||
* wait for this rule to finish running (from a previous operation)
|
||||
* since it holds the device open. Since parted also closes the block
|
||||
* device, it can cause udev to run again, hence the call to
|
||||
* udev_settle afterwards.
|
||||
*/
|
||||
static int
|
||||
recover_blkrrpart (const char *device, const char *err)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!strstr (err,
|
||||
"Error informing the kernel about modifications to partition"))
|
||||
return -1;
|
||||
|
||||
r = command (NULL, NULL, "blockdev", "--rereadpt", device, NULL);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
|
||||
udev_settle ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RUN_PARTED(error,device,...) \
|
||||
do { \
|
||||
int r; \
|
||||
char *err; \
|
||||
\
|
||||
r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, \
|
||||
"parted", "-s", "--", (device), __VA_ARGS__); \
|
||||
if (r == -1) { \
|
||||
if (recover_blkrrpart ((device), err) == -1) { \
|
||||
reply_with_error ("%s: parted: %s: %s", __func__, (device), err); \
|
||||
free (err); \
|
||||
error; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
free (err); \
|
||||
} while (0)
|
||||
|
||||
static const char *
|
||||
check_parttype (const char *parttype)
|
||||
@@ -101,13 +70,25 @@ check_parttype (const char *parttype)
|
||||
int
|
||||
do_part_init (const char *device, const char *parttype)
|
||||
{
|
||||
int r;
|
||||
char *err;
|
||||
|
||||
parttype = check_parttype (parttype);
|
||||
if (!parttype) {
|
||||
reply_with_error ("unknown partition type: common choices are \"gpt\" and \"msdos\"");
|
||||
return -1;
|
||||
}
|
||||
|
||||
RUN_PARTED (return -1, device, "mklabel", parttype, NULL);
|
||||
udev_settle ();
|
||||
|
||||
r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
|
||||
"parted", "-s", "--", device, "mklabel", parttype, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("parted: %s: %s", device, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
udev_settle ();
|
||||
|
||||
@@ -118,6 +99,8 @@ int
|
||||
do_part_add (const char *device, const char *prlogex,
|
||||
int64_t startsect, int64_t endsect)
|
||||
{
|
||||
int r;
|
||||
char *err;
|
||||
char startstr[32];
|
||||
char endstr[32];
|
||||
|
||||
@@ -146,12 +129,22 @@ do_part_add (const char *device, const char *prlogex,
|
||||
snprintf (startstr, sizeof startstr, "%" PRIi64 "s", startsect);
|
||||
snprintf (endstr, sizeof endstr, "%" PRIi64 "s", endsect);
|
||||
|
||||
udev_settle ();
|
||||
|
||||
/* XXX Bug: If the partition table type (which we don't know in this
|
||||
* function) is GPT, then this parted command sets the _partition
|
||||
* name_ to prlogex, eg. "primary". I would essentially describe
|
||||
* this as a bug in the parted mkpart command.
|
||||
*/
|
||||
RUN_PARTED (return -1, device, "mkpart", prlogex, startstr, endstr, NULL);
|
||||
r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
|
||||
"parted", "-s", "--",
|
||||
device, "mkpart", prlogex, startstr, endstr, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("parted: %s: %s", device, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
udev_settle ();
|
||||
|
||||
@@ -161,6 +154,9 @@ do_part_add (const char *device, const char *prlogex,
|
||||
int
|
||||
do_part_del (const char *device, int partnum)
|
||||
{
|
||||
int r;
|
||||
char *err;
|
||||
|
||||
if (partnum <= 0) {
|
||||
reply_with_error ("partition number must be >= 1");
|
||||
return -1;
|
||||
@@ -169,15 +165,28 @@ do_part_del (const char *device, int partnum)
|
||||
char partnum_str[16];
|
||||
snprintf (partnum_str, sizeof partnum_str, "%d", partnum);
|
||||
|
||||
RUN_PARTED (return -1, device, "rm", partnum_str, NULL);
|
||||
udev_settle ();
|
||||
|
||||
r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
|
||||
"parted", "-s", "--", device, "rm", partnum_str, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("parted: %s: %s", device, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
udev_settle ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_part_disk (const char *device, const char *parttype)
|
||||
{
|
||||
int r;
|
||||
char *err;
|
||||
|
||||
parttype = check_parttype (parttype);
|
||||
if (!parttype) {
|
||||
reply_with_error ("unknown partition type: common choices are \"gpt\" and \"msdos\"");
|
||||
@@ -195,12 +204,21 @@ do_part_disk (const char *device, const char *parttype)
|
||||
const char *startstr = "128s";
|
||||
const char *endstr = "-128s";
|
||||
|
||||
RUN_PARTED (return -1,
|
||||
device,
|
||||
"mklabel", parttype,
|
||||
/* See comment about about the parted mkpart command. */
|
||||
"mkpart", STREQ (parttype, "gpt") ? "p1" : "primary",
|
||||
startstr, endstr, NULL);
|
||||
udev_settle ();
|
||||
|
||||
r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
|
||||
"parted", "-s", "--",
|
||||
device,
|
||||
"mklabel", parttype,
|
||||
/* See comment about about the parted mkpart command. */
|
||||
"mkpart", STREQ (parttype, "gpt") ? "p1" : "primary",
|
||||
startstr, endstr, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("parted: %s: %s", device, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
udev_settle ();
|
||||
|
||||
@@ -210,6 +228,9 @@ do_part_disk (const char *device, const char *parttype)
|
||||
int
|
||||
do_part_set_bootable (const char *device, int partnum, int bootable)
|
||||
{
|
||||
int r;
|
||||
char *err;
|
||||
|
||||
if (partnum <= 0) {
|
||||
reply_with_error ("partition number must be >= 1");
|
||||
return -1;
|
||||
@@ -219,8 +240,17 @@ do_part_set_bootable (const char *device, int partnum, int bootable)
|
||||
|
||||
snprintf (partstr, sizeof partstr, "%d", partnum);
|
||||
|
||||
RUN_PARTED (return -1,
|
||||
device, "set", partstr, "boot", bootable ? "on" : "off", NULL);
|
||||
udev_settle ();
|
||||
|
||||
r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
|
||||
"parted", "-s", "--",
|
||||
device, "set", partstr, "boot", bootable ? "on" : "off", NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("parted: %s: %s", device, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
udev_settle ();
|
||||
|
||||
@@ -230,6 +260,9 @@ do_part_set_bootable (const char *device, int partnum, int bootable)
|
||||
int
|
||||
do_part_set_name (const char *device, int partnum, const char *name)
|
||||
{
|
||||
int r;
|
||||
char *err;
|
||||
|
||||
if (partnum <= 0) {
|
||||
reply_with_error ("partition number must be >= 1");
|
||||
return -1;
|
||||
@@ -239,7 +272,16 @@ do_part_set_name (const char *device, int partnum, const char *name)
|
||||
|
||||
snprintf (partstr, sizeof partstr, "%d", partnum);
|
||||
|
||||
RUN_PARTED (return -1, device, "name", partstr, name, NULL);
|
||||
udev_settle ();
|
||||
|
||||
r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
|
||||
"parted", "-s", "--", device, "name", partstr, name, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("parted: %s: %s", device, err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
free (err);
|
||||
|
||||
udev_settle ();
|
||||
|
||||
@@ -686,6 +728,8 @@ do_part_get_mbr_id (const char *device, int partnum)
|
||||
char *out, *err;
|
||||
int r;
|
||||
|
||||
udev_settle ();
|
||||
|
||||
r = command (&out, &err, "sfdisk", "--print-id", device, partnum_str, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("sfdisk --print-id: %s", err);
|
||||
@@ -693,9 +737,10 @@ do_part_get_mbr_id (const char *device, int partnum)
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
|
||||
udev_settle ();
|
||||
|
||||
/* It's printed in hex ... */
|
||||
int id;
|
||||
if (sscanf (out, "%x", &id) != 1) {
|
||||
@@ -725,6 +770,8 @@ do_part_set_mbr_id (const char *device, int partnum, int idbyte)
|
||||
char *err;
|
||||
int r;
|
||||
|
||||
udev_settle ();
|
||||
|
||||
r = command (NULL, &err, "sfdisk",
|
||||
"--change-id", device, partnum_str, idbyte_str, NULL);
|
||||
if (r == -1) {
|
||||
@@ -732,7 +779,9 @@ do_part_set_mbr_id (const char *device, int partnum, int idbyte)
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
|
||||
udev_settle ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 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
|
||||
@@ -71,7 +71,7 @@ static struct timeval start_t;
|
||||
static struct timeval last_progress_t;
|
||||
|
||||
/* Counts the number of progress notifications sent during this call. */
|
||||
static int count_progress;
|
||||
static size_t count_progress;
|
||||
|
||||
/* The daemon communications socket. */
|
||||
static int sock;
|
||||
@@ -221,16 +221,16 @@ main_loop (int _sock)
|
||||
static void send_error (int errnum, const char *msg);
|
||||
|
||||
void
|
||||
reply_with_error (const char *fs, ...)
|
||||
reply_with_error_errno (int err, const char *fs, ...)
|
||||
{
|
||||
char err[GUESTFS_ERROR_LEN];
|
||||
char buf[GUESTFS_ERROR_LEN];
|
||||
va_list args;
|
||||
|
||||
va_start (args, fs);
|
||||
vsnprintf (err, sizeof err, fs, args);
|
||||
vsnprintf (buf, sizeof buf, fs, args);
|
||||
va_end (args);
|
||||
|
||||
send_error (0, err);
|
||||
send_error (err, buf);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -263,6 +263,7 @@ send_error (int errnum, const char *msg)
|
||||
|
||||
xdrmem_create (&xdr, buf, sizeof buf, XDR_ENCODE);
|
||||
|
||||
memset (&hdr, 0, sizeof hdr);
|
||||
hdr.prog = GUESTFS_PROGRAM;
|
||||
hdr.vers = GUESTFS_PROTOCOL_VERSION;
|
||||
hdr.direction = GUESTFS_DIRECTION_REPLY;
|
||||
@@ -311,10 +312,11 @@ reply (xdrproc_t xdrp, char *ret)
|
||||
char buf[GUESTFS_MESSAGE_MAX];
|
||||
char lenbuf[4];
|
||||
struct guestfs_message_header hdr;
|
||||
unsigned len;
|
||||
uint32_t len;
|
||||
|
||||
xdrmem_create (&xdr, buf, sizeof buf, XDR_ENCODE);
|
||||
|
||||
memset (&hdr, 0, sizeof hdr);
|
||||
hdr.prog = GUESTFS_PROGRAM;
|
||||
hdr.vers = GUESTFS_PROTOCOL_VERSION;
|
||||
hdr.direction = GUESTFS_DIRECTION_REPLY;
|
||||
@@ -350,7 +352,7 @@ reply (xdrproc_t xdrp, char *ret)
|
||||
fprintf (stderr, "guestfsd: xwrite failed\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
if (xwrite (sock, buf, len) == -1) {
|
||||
if (xwrite (sock, buf, (size_t) len) == -1) {
|
||||
fprintf (stderr, "guestfsd: xwrite failed\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
@@ -475,13 +477,13 @@ static int send_chunk (const guestfs_chunk *);
|
||||
|
||||
/* Also check if the library sends us a cancellation message. */
|
||||
int
|
||||
send_file_write (const void *buf, int len)
|
||||
send_file_write (const void *buf, size_t len)
|
||||
{
|
||||
guestfs_chunk chunk;
|
||||
int cancel;
|
||||
|
||||
if (len > GUESTFS_MAX_CHUNK_SIZE) {
|
||||
fprintf (stderr, "guestfsd: send_file_write: len (%d) > GUESTFS_MAX_CHUNK_SIZE (%d)\n",
|
||||
fprintf (stderr, "guestfsd: send_file_write: len (%zu) > GUESTFS_MAX_CHUNK_SIZE (%d)\n",
|
||||
len, GUESTFS_MAX_CHUNK_SIZE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ do_readdir (const char *path)
|
||||
guestfs_int_dirent v;
|
||||
DIR *dir;
|
||||
struct dirent *d;
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
ret = malloc (sizeof *ret);
|
||||
if (ret == NULL) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 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
|
||||
@@ -27,6 +27,8 @@
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "cloexec.h"
|
||||
|
||||
#include "daemon.h"
|
||||
#include "optgroups.h"
|
||||
#include "actions.h"
|
||||
@@ -36,20 +38,17 @@
|
||||
#define NAME_MAX FILENAME_MAX
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_REALPATH
|
||||
|
||||
int
|
||||
optgroup_realpath_available (void)
|
||||
{
|
||||
#ifdef HAVE_REALPATH
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
char *
|
||||
do_realpath (const char *path)
|
||||
{
|
||||
#ifdef HAVE_REALPATH
|
||||
char *ret;
|
||||
|
||||
CHROOT_IN;
|
||||
@@ -61,11 +60,26 @@ do_realpath (const char *path)
|
||||
}
|
||||
|
||||
return ret; /* caller frees */
|
||||
#else
|
||||
NOT_AVAILABLE (NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* !HAVE_REALPATH */
|
||||
|
||||
int
|
||||
optgroup_realpath_available (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
do_realpath (const char *path)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
#endif /* !HAVE_REALPATH */
|
||||
|
||||
static int find_path_element (int fd_cwd, char *name, size_t *name_len_ret);
|
||||
|
||||
char *
|
||||
do_case_sensitive_path (const char *path)
|
||||
{
|
||||
@@ -76,7 +90,7 @@ do_case_sensitive_path (const char *path)
|
||||
/* 'fd_cwd' here is a surrogate for the current working directory, so
|
||||
* that we don't have to actually call chdir(2).
|
||||
*/
|
||||
fd_cwd = open (sysroot, O_RDONLY | O_DIRECTORY);
|
||||
fd_cwd = open (sysroot, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
|
||||
if (fd_cwd == -1) {
|
||||
reply_with_perror ("%s", sysroot);
|
||||
return NULL;
|
||||
@@ -110,57 +124,26 @@ do_case_sensitive_path (const char *path)
|
||||
path += i;
|
||||
|
||||
/* Read the current directory looking (case insensitively) for
|
||||
* this element of the path.
|
||||
* this element of the path. This replaces 'name' with the
|
||||
* correct case version.
|
||||
*/
|
||||
int fd2 = dup (fd_cwd); /* because closedir will close it */
|
||||
if (fd2 == -1) {
|
||||
reply_with_perror ("dup");
|
||||
if (find_path_element (fd_cwd, name, &i) == -1)
|
||||
goto error;
|
||||
}
|
||||
DIR *dir = fdopendir (fd2);
|
||||
if (dir == NULL) {
|
||||
reply_with_perror ("opendir");
|
||||
goto error;
|
||||
}
|
||||
|
||||
struct dirent *d = NULL;
|
||||
|
||||
errno = 0;
|
||||
while ((d = readdir (dir)) != NULL) {
|
||||
if (STRCASEEQ (d->d_name, name))
|
||||
break;
|
||||
}
|
||||
|
||||
if (d == NULL && errno != 0) {
|
||||
reply_with_perror ("readdir");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (closedir (dir) == -1) {
|
||||
reply_with_perror ("closedir");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (d == NULL) {
|
||||
reply_with_error ("%s: no file or directory found with this name", name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Add the real name of this path element to the return value. */
|
||||
if (next > 1)
|
||||
ret[next++] = '/';
|
||||
|
||||
i = strlen (d->d_name);
|
||||
if (next + i >= PATH_MAX) {
|
||||
reply_with_error ("final path too long");
|
||||
goto error;
|
||||
}
|
||||
|
||||
strcpy (&ret[next], d->d_name);
|
||||
strcpy (&ret[next], name);
|
||||
next += i;
|
||||
|
||||
/* Is it a directory? Try going into it. */
|
||||
fd2 = openat (fd_cwd, d->d_name, O_RDONLY | O_DIRECTORY);
|
||||
int fd2 = openat (fd_cwd, name, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
|
||||
int err = errno;
|
||||
close (fd_cwd);
|
||||
fd_cwd = fd2;
|
||||
@@ -168,12 +151,12 @@ do_case_sensitive_path (const char *path)
|
||||
if (fd_cwd == -1) {
|
||||
/* ENOTDIR is OK provided we've reached the end of the path. */
|
||||
if (errno != ENOTDIR) {
|
||||
reply_with_perror ("openat: %s", d->d_name);
|
||||
reply_with_perror ("openat: %s", name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (*path) {
|
||||
reply_with_error ("%s: non-directory element in path", d->d_name);
|
||||
reply_with_error ("%s: non-directory element in path", name);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -196,3 +179,75 @@ do_case_sensitive_path (const char *path)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 'fd_cwd' is a file descriptor pointing to an open directory.
|
||||
* 'name' is a buffer of NAME_MAX+1 characters in size which initially
|
||||
* contains the path element to search for.
|
||||
*
|
||||
* We search the directory looking for a path element that case
|
||||
* insensitively matches 'name' and update the 'name' buffer.
|
||||
*
|
||||
* If this is successful, return 0. If it fails, reply with an error
|
||||
* and return -1.
|
||||
*/
|
||||
static int
|
||||
find_path_element (int fd_cwd, char *name, size_t *name_len_ret)
|
||||
{
|
||||
int fd2;
|
||||
DIR *dir;
|
||||
struct dirent *d;
|
||||
|
||||
fd2 = dup_cloexec (fd_cwd); /* because closedir will close it */
|
||||
if (fd2 == -1) {
|
||||
reply_with_perror ("dup");
|
||||
return -1;
|
||||
}
|
||||
dir = fdopendir (fd2);
|
||||
if (dir == NULL) {
|
||||
reply_with_perror ("opendir");
|
||||
close (fd2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
errno = 0;
|
||||
d = readdir (dir);
|
||||
if (d == NULL)
|
||||
break;
|
||||
if (STRCASEEQ (d->d_name, name))
|
||||
break;
|
||||
}
|
||||
|
||||
if (d == NULL && errno != 0) {
|
||||
reply_with_perror ("readdir");
|
||||
closedir (dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (d == NULL) {
|
||||
reply_with_error ("%s: no file or directory found with this name", name);
|
||||
closedir (dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*name_len_ret = strlen (d->d_name);
|
||||
if (*name_len_ret > NAME_MAX) {
|
||||
/* Should never happen? */
|
||||
reply_with_error ("path element longer than NAME_MAX");
|
||||
closedir (dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Safe because name is a buffer of NAME_MAX+1 characters. */
|
||||
strcpy (name, d->d_name);
|
||||
|
||||
/* NB: closedir frees the structure associated with 'd', so we must
|
||||
* do this last.
|
||||
*/
|
||||
if (closedir (dir) == -1) {
|
||||
reply_with_perror ("closedir");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -32,18 +32,12 @@
|
||||
#include "optgroups.h"
|
||||
|
||||
#if defined(HAVE_LIBSELINUX)
|
||||
|
||||
int
|
||||
optgroup_selinux_available (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#else /* !HAVE_LIBSELINUX */
|
||||
int
|
||||
optgroup_selinux_available (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* !HAVE_LIBSELINUX */
|
||||
|
||||
/* setcon is only valid under the following circumstances:
|
||||
* - single threaded
|
||||
@@ -52,7 +46,7 @@ optgroup_selinux_available (void)
|
||||
int
|
||||
do_setcon (const char *context)
|
||||
{
|
||||
#if defined(HAVE_LIBSELINUX) && defined(HAVE_SETCON)
|
||||
#if defined(HAVE_SETCON)
|
||||
if (setcon ((char *) context) == -1) {
|
||||
reply_with_perror ("setcon");
|
||||
return -1;
|
||||
@@ -60,14 +54,15 @@ do_setcon (const char *context)
|
||||
|
||||
return 0;
|
||||
#else
|
||||
NOT_AVAILABLE (-1);
|
||||
reply_with_error ("function not available");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
char *
|
||||
do_getcon (void)
|
||||
{
|
||||
#if defined(HAVE_LIBSELINUX) && defined(HAVE_GETCON)
|
||||
#if defined(HAVE_GETCON)
|
||||
security_context_t context;
|
||||
char *r;
|
||||
|
||||
@@ -85,6 +80,29 @@ do_getcon (void)
|
||||
|
||||
return r; /* caller frees */
|
||||
#else
|
||||
NOT_AVAILABLE (NULL);
|
||||
reply_with_error ("function not available");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* !HAVE_LIBSELINUX */
|
||||
|
||||
int
|
||||
optgroup_selinux_available (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_setcon (const char *context)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
char *
|
||||
do_getcon (void)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
#endif /* !HAVE_LIBSELINUX */
|
||||
|
||||
@@ -147,7 +147,7 @@ do_lstatlist (const char *path, char *const *names)
|
||||
}
|
||||
|
||||
CHROOT_IN;
|
||||
path_fd = open (path, O_RDONLY | O_DIRECTORY);
|
||||
path_fd = open (path, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (path_fd == -1) {
|
||||
|
||||
@@ -41,7 +41,7 @@ do_strings_e (const char *encoding, const char *path)
|
||||
}
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_RDONLY);
|
||||
fd = open (path, O_RDONLY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 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
|
||||
@@ -43,24 +43,6 @@ do_sync (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Older versions of libguestfs used to issue separate 'umount_all'
|
||||
* and 'sync' commands just before closing the handle. Since
|
||||
* libguestfs 1.9.7 the library issues this 'internal_autosync'
|
||||
* internal operation instead, allowing more control in the daemon.
|
||||
*/
|
||||
int
|
||||
do_internal_autosync (void)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
if (autosync_umount)
|
||||
r = do_umount_all ();
|
||||
|
||||
sync_disks ();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* This is a replacement for sync(2) which is called from
|
||||
* this file and from other places in the daemon. It works
|
||||
* on Windows too.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 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
|
||||
|
||||
@@ -35,7 +35,7 @@ do_truncate_size (const char *path, int64_t size)
|
||||
int r;
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_WRONLY | O_NOCTTY);
|
||||
fd = open (path, O_WRONLY|O_NOCTTY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
|
||||
@@ -114,7 +114,7 @@ upload (const char *filename, int flags, int64_t offset)
|
||||
int
|
||||
do_upload (const char *filename)
|
||||
{
|
||||
return upload (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0);
|
||||
return upload (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0);
|
||||
}
|
||||
|
||||
/* Has one FileIn parameter. */
|
||||
@@ -126,7 +126,7 @@ do_upload_offset (const char *filename, int64_t offset)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return upload (filename, O_WRONLY|O_CREAT|O_NOCTTY, offset);
|
||||
return upload (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, offset);
|
||||
}
|
||||
|
||||
/* Has one FileOut parameter. */
|
||||
@@ -139,7 +139,7 @@ do_download (const char *filename)
|
||||
is_dev = STRPREFIX (filename, "/dev/");
|
||||
|
||||
if (!is_dev) CHROOT_IN;
|
||||
fd = open (filename, O_RDONLY);
|
||||
fd = open (filename, O_RDONLY|O_CLOEXEC);
|
||||
if (!is_dev) CHROOT_OUT;
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("%s", filename);
|
||||
@@ -222,7 +222,7 @@ do_download_offset (const char *filename, int64_t offset, int64_t size)
|
||||
is_dev = STRPREFIX (filename, "/dev/");
|
||||
|
||||
if (!is_dev) CHROOT_IN;
|
||||
fd = open (filename, O_RDONLY);
|
||||
fd = open (filename, O_RDONLY|O_CLOEXEC);
|
||||
if (!is_dev) CHROOT_OUT;
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("%s", filename);
|
||||
@@ -232,6 +232,7 @@ do_download_offset (const char *filename, int64_t offset, int64_t size)
|
||||
if (offset) {
|
||||
if (lseek (fd, offset, SEEK_SET) == -1) {
|
||||
reply_with_perror ("lseek: %s", filename);
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ wc (const char *flag, const char *path)
|
||||
int fd, flags, r;
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_RDONLY);
|
||||
fd = open (path, O_RDONLY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 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
|
||||
@@ -120,7 +120,7 @@ getxattrs (const char *path,
|
||||
{
|
||||
ssize_t len, vlen;
|
||||
char *buf = NULL;
|
||||
int i, j;
|
||||
size_t i, j;
|
||||
guestfs_int_xattr_list *r = NULL;
|
||||
|
||||
CHROOT_IN;
|
||||
@@ -155,7 +155,7 @@ getxattrs (const char *path,
|
||||
* len. First count the strings.
|
||||
*/
|
||||
r->guestfs_int_xattr_list_len = 0;
|
||||
for (i = 0; i < len; i += strlen (&buf[i]) + 1)
|
||||
for (i = 0; i < (size_t) len; i += strlen (&buf[i]) + 1)
|
||||
r->guestfs_int_xattr_list_len++;
|
||||
|
||||
r->guestfs_int_xattr_list_val =
|
||||
@@ -165,7 +165,7 @@ getxattrs (const char *path,
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; i < len; i += strlen (&buf[i]) + 1, ++j) {
|
||||
for (i = 0, j = 0; i < (size_t) len; i += strlen (&buf[i]) + 1, ++j) {
|
||||
CHROOT_IN;
|
||||
vlen = getxattr (path, &buf[i], NULL, 0);
|
||||
CHROOT_OUT;
|
||||
@@ -203,7 +203,7 @@ getxattrs (const char *path,
|
||||
free (buf);
|
||||
if (r) {
|
||||
if (r->guestfs_int_xattr_list_val) {
|
||||
unsigned int k;
|
||||
size_t k;
|
||||
for (k = 0; k < r->guestfs_int_xattr_list_len; ++k) {
|
||||
free (r->guestfs_int_xattr_list_val[k].attrname);
|
||||
free (r->guestfs_int_xattr_list_val[k].attrval.attrval_val);
|
||||
@@ -260,7 +260,7 @@ do_lxattrlist (const char *path, char *const *names)
|
||||
char pathname[PATH_MAX];
|
||||
size_t path_len = strlen (path);
|
||||
guestfs_int_xattr_list *ret = NULL;
|
||||
int i, j;
|
||||
size_t i, j;
|
||||
size_t k, m, nr_attrs;
|
||||
ssize_t len, vlen;
|
||||
char *buf = NULL;
|
||||
@@ -339,7 +339,7 @@ do_lxattrlist (const char *path, char *const *names)
|
||||
* len. First count the strings.
|
||||
*/
|
||||
nr_attrs = 0;
|
||||
for (i = 0; i < len; i += strlen (&buf[i]) + 1)
|
||||
for (i = 0; i < (size_t) len; i += strlen (&buf[i]) + 1)
|
||||
nr_attrs++;
|
||||
|
||||
newptr =
|
||||
@@ -363,7 +363,7 @@ do_lxattrlist (const char *path, char *const *names)
|
||||
entry[m].attrval.attrval_val = NULL;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; i < len; i += strlen (&buf[i]) + 1, ++j) {
|
||||
for (i = 0, j = 0; i < (size_t) len; i += strlen (&buf[i]) + 1, ++j) {
|
||||
CHROOT_IN;
|
||||
vlen = lgetxattr (pathname, &buf[i], NULL, 0);
|
||||
CHROOT_OUT;
|
||||
@@ -511,6 +511,11 @@ do_lgetxattr (const char *path, const char *name, size_t *size_r)
|
||||
}
|
||||
|
||||
#else /* no xattr.h */
|
||||
|
||||
/* Note that the wrapper code (daemon/stubs.c) ensures that the
|
||||
* functions below are never called because
|
||||
* optgroup_linuxxattrs_available returns false.
|
||||
*/
|
||||
int
|
||||
optgroup_linuxxattrs_available (void)
|
||||
{
|
||||
@@ -520,55 +525,55 @@ optgroup_linuxxattrs_available (void)
|
||||
guestfs_int_xattr_list *
|
||||
do_getxattrs (const char *path)
|
||||
{
|
||||
NOT_AVAILABLE (NULL);
|
||||
abort ();
|
||||
}
|
||||
|
||||
guestfs_int_xattr_list *
|
||||
do_lgetxattrs (const char *path)
|
||||
{
|
||||
NOT_AVAILABLE (NULL);
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_setxattr (const char *xattr, const char *val, int vallen, const char *path)
|
||||
{
|
||||
NOT_AVAILABLE (-1);
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_lsetxattr (const char *xattr, const char *val, int vallen, const char *path)
|
||||
{
|
||||
NOT_AVAILABLE (-1);
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_removexattr (const char *xattr, const char *path)
|
||||
{
|
||||
NOT_AVAILABLE (-1);
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
do_lremovexattr (const char *xattr, const char *path)
|
||||
{
|
||||
NOT_AVAILABLE (-1);
|
||||
abort ();
|
||||
}
|
||||
|
||||
guestfs_int_xattr_list *
|
||||
do_lxattrlist (const char *path, char *const *names)
|
||||
{
|
||||
NOT_AVAILABLE (NULL);
|
||||
abort ();
|
||||
}
|
||||
|
||||
char *
|
||||
do_getxattr (const char *path, const char *name, size_t *size_r)
|
||||
{
|
||||
NOT_AVAILABLE (NULL);
|
||||
abort ();
|
||||
}
|
||||
|
||||
char *
|
||||
do_lgetxattr (const char *path, const char *name, size_t *size_r)
|
||||
{
|
||||
NOT_AVAILABLE (NULL);
|
||||
abort ();
|
||||
}
|
||||
|
||||
#endif /* no xattr.h */
|
||||
|
||||
139
daemon/zero.c
139
daemon/zero.c
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2009-2011 Red Hat Inc.
|
||||
* Copyright (C) 2009-2012 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -24,9 +24,11 @@
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
#include "optgroups.h"
|
||||
|
||||
static const char zero_buf[4096];
|
||||
|
||||
@@ -37,7 +39,7 @@ do_zero (const char *device)
|
||||
int fd;
|
||||
size_t i, offset;
|
||||
|
||||
fd = open (device, O_RDWR);
|
||||
fd = open (device, O_RDWR|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("%s", device);
|
||||
return -1;
|
||||
@@ -72,6 +74,30 @@ do_zero (const char *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
optgroup_wipefs_available (void)
|
||||
{
|
||||
return prog_exists ("wipefs");
|
||||
}
|
||||
|
||||
int
|
||||
do_wipefs (const char *device)
|
||||
{
|
||||
int r;
|
||||
char *err = NULL;
|
||||
|
||||
const char *wipefs[] = {"wipefs", "-a", device, NULL};
|
||||
r = commandv (NULL, &err, wipefs);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s", err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free (err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_zero_device (const char *device)
|
||||
{
|
||||
@@ -80,7 +106,7 @@ do_zero_device (const char *device)
|
||||
return -1;
|
||||
uint64_t size = (uint64_t) ssize;
|
||||
|
||||
int fd = open (device, O_RDWR);
|
||||
int fd = open (device, O_RDWR|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("%s", device);
|
||||
return -1;
|
||||
@@ -139,7 +165,7 @@ do_is_zero (const char *path)
|
||||
ssize_t r;
|
||||
|
||||
CHROOT_IN;
|
||||
fd = open (path, O_RDONLY);
|
||||
fd = open (path, O_RDONLY|O_CLOEXEC);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (fd == -1) {
|
||||
@@ -175,7 +201,7 @@ do_is_zero_device (const char *device)
|
||||
char buf[1024*1024];
|
||||
ssize_t r;
|
||||
|
||||
fd = open (device, O_RDONLY);
|
||||
fd = open (device, O_RDONLY|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("open: %s", device);
|
||||
return -1;
|
||||
@@ -201,3 +227,106 @@ do_is_zero_device (const char *device)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
random_name (char *p)
|
||||
{
|
||||
int fd;
|
||||
unsigned char c;
|
||||
|
||||
fd = open ("/dev/urandom", O_RDONLY|O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("/dev/urandom");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (*p) {
|
||||
if (*p == 'X') {
|
||||
if (read (fd, &c, 1) != 1) {
|
||||
reply_with_perror ("read: /dev/urandom");
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
*p = "0123456789abcdefghijklmnopqrstuvwxyz"[c % 36];
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
close (fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Current implementation is to create a file of all zeroes, then
|
||||
* delete it. The description of this function is left open in order
|
||||
* to allow better implementations in future, including
|
||||
* sparsification.
|
||||
*/
|
||||
int
|
||||
do_zero_free_space (const char *dir)
|
||||
{
|
||||
size_t len = strlen (dir);
|
||||
char filename[sysroot_len+len+14]; /* sysroot + dir + "/" + 8.3 + "\0" */
|
||||
int fd;
|
||||
unsigned skip = 0;
|
||||
struct statvfs statbuf;
|
||||
fsblkcnt_t bfree_initial;
|
||||
|
||||
/* Choose a randomly named 8.3 file. Because of the random name,
|
||||
* this won't conflict with existing files, and it should be
|
||||
* compatible with any filesystem type inc. FAT.
|
||||
*/
|
||||
snprintf (filename, sysroot_len+len+14, "%s%s/XXXXXXXX.XXX", sysroot, dir);
|
||||
if (random_name (&filename[sysroot_len+len]) == -1)
|
||||
return -1;
|
||||
|
||||
if (verbose)
|
||||
printf ("random filename: %s\n", filename);
|
||||
|
||||
/* Open file and fill with zeroes until we run out of space. */
|
||||
fd = open (filename, O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0600);
|
||||
if (fd == -1) {
|
||||
reply_with_perror ("open: %s", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* To estimate progress in this operation, we're going to track
|
||||
* free blocks in this filesystem down to zero.
|
||||
*/
|
||||
if (fstatvfs (fd, &statbuf) == -1) {
|
||||
reply_with_perror ("fstatvfs");
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
bfree_initial = statbuf.f_bfree;
|
||||
|
||||
for (;;) {
|
||||
if (write (fd, zero_buf, sizeof zero_buf) == -1) {
|
||||
if (errno == ENOSPC) /* expected error */
|
||||
break;
|
||||
reply_with_perror ("write: %s", filename);
|
||||
close (fd);
|
||||
unlink (filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
skip++;
|
||||
if ((skip & 256) == 0 && fstatvfs (fd, &statbuf) == 0)
|
||||
notify_progress (bfree_initial - statbuf.f_bfree, bfree_initial);
|
||||
}
|
||||
|
||||
/* Make sure the file is completely written to disk. */
|
||||
close (fd); /* expect this to give an error, don't check it */
|
||||
|
||||
sync_disks ();
|
||||
|
||||
notify_progress (bfree_initial, bfree_initial);
|
||||
|
||||
/* Remove the file. */
|
||||
if (unlink (filename) == -1) {
|
||||
reply_with_perror ("unlink: %s", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
26
debian/.gitignore
vendored
26
debian/.gitignore
vendored
@@ -1,26 +0,0 @@
|
||||
*.debhelper
|
||||
*.debhelper.log
|
||||
*.substvars
|
||||
changelog
|
||||
files
|
||||
guestfsd/
|
||||
guestfish/
|
||||
guestmount/
|
||||
libguestfs-dev/
|
||||
libguestfs-doc/
|
||||
libguestfs-ocaml/
|
||||
libguestfs-ocaml.install
|
||||
libguestfs-ocaml-dev/
|
||||
libguestfs-ocaml-dev.install
|
||||
libguestfs-perl/
|
||||
libguestfs-tools/
|
||||
libguestfs0-dbg/
|
||||
libguestfs0/
|
||||
python-guestfs/
|
||||
python-module-stampdir/
|
||||
stamp-makefile-install
|
||||
stamp-autotools
|
||||
stamp-autotools-files
|
||||
stamp-makefile-build
|
||||
stamp-patched
|
||||
tmp/
|
||||
148
debian/changelog.in
vendored
148
debian/changelog.in
vendored
@@ -1,148 +0,0 @@
|
||||
libguestfs (@VERSION@-1) unstable; urgency=low
|
||||
|
||||
* release: New upstream version @VERSION@.
|
||||
|
||||
-- Richard W.M. Jones <rjones@redhat.com> Thu, 9 Dec 2010 12:00:00 +0000
|
||||
|
||||
libguestfs (1.0.84-4) unstable; urgency=low
|
||||
|
||||
* [2c44147] Build-depend on aptitude since Ubuntu needs it.
|
||||
* [d50fd25] New patch 0005-Check-for-service-and-use-it-if-it-s- there.patch
|
||||
Check for service and use it if it's there
|
||||
* [40dc6b0] New patch 0006-Check-for-grub-menu.lst-if-etc-grub.conf-
|
||||
can-t-be-fo.patch Check for grub/menu.lst if /etc/grub.conf can't be found
|
||||
* [465def2] New patch 0007-Debina-package-format-is-called-deb-not-
|
||||
dpkg.patch Debina package format is called 'deb' not 'dpkg'
|
||||
* [1b7efb4] New patch 0008-Add-application-listing-for-Debian.patch Add
|
||||
application listing for Debian
|
||||
* [5dd34c9] Add series file
|
||||
* [647fd84] Don't remove gmo files (Closes: #571117)
|
||||
|
||||
-- Guido Günther <agx@sigxcpu.org> Wed, 24 Feb 2010 18:22:58 +0100
|
||||
|
||||
libguestfs (1.0.84-3) unstable; urgency=low
|
||||
|
||||
* [307bd4e] Add hivex commands.
|
||||
* [7fac596] Build and install fuse helper
|
||||
* [09ea683] Include all virt-* tools including virt-win-reg
|
||||
* [ae3ee70] New patch 0004-Disable-fuser-tests-if-dev-fuse-doesn-t-
|
||||
exist.patch Disable fuse tests if /dev/fuse doesn't exist
|
||||
|
||||
-- Guido Günther <agx@sigxcpu.org> Sun, 21 Feb 2010 19:40:43 +0100
|
||||
|
||||
libguestfs (1.0.84-2) unstable; urgency=low
|
||||
|
||||
* [0195df4] Add vendor detection for Ubuntu
|
||||
* [2fa535e] {Build-,}Depend on bochsbios and vgabios These are only
|
||||
recommends but needed to run qemu during the tests.
|
||||
* [ee483bf] Reenable tests
|
||||
* [67fd975] New patch 0003-scrub-now-available-on-Debian.patch scrub now
|
||||
available on Debian
|
||||
* [2e9c89d] New patch 0004-Adjust-error-output-for-regressions-
|
||||
rhbz557655.patch Adjust error output for regressions/rhbz557655
|
||||
* [c5d5f9e] Adjust install-kernel to new debirf version
|
||||
* [9c1fbdf] Drop Hardcode-kernel-version.patch - superflous due to previous
|
||||
commit.
|
||||
|
||||
-- Guido Günther <agx@sigxcpu.org> Sun, 21 Feb 2010 13:24:01 +0100
|
||||
|
||||
libguestfs (1.0.84-1) unstable; urgency=low
|
||||
|
||||
[ Guido Günther ]
|
||||
* [1149b4a] add missing modules for vfat
|
||||
|
||||
[ Laurent Léonard ]
|
||||
* [397dbf3] Imported Upstream version 1.0.80
|
||||
* [ca95c7a] Drop patch 0001-add-nls_base.ko-and-nls_cp437.ko-for-
|
||||
vfat.patch. Fixed upstream.
|
||||
* [344c7e6] Add dependency on mkisofs.
|
||||
|
||||
[ Guido Günther ]
|
||||
* [5aa8061] Add missing build-deps needed for ./configure
|
||||
* [f8a682d] Imported Upstream version 1.0.84
|
||||
* [e35175c] No need to manually install virt-inspector anymore
|
||||
* [de6ddf1] Depend on python-all-dev since libguestfs handles python
|
||||
2.6 too
|
||||
* [a2be87e] don't use the host's MAC address
|
||||
* [88b70ef] New patch 0001-Disable-checks-for-now.patch Disable checks for
|
||||
now
|
||||
* [2b59394] New patch 0002-Run-debirf-as-root.patch Run debirf as root
|
||||
* [e798002] New patch 0003-Hardcode-kernel-version.patch Hardcode kernel
|
||||
version
|
||||
* [602fab3] reenable patch system
|
||||
|
||||
-- Guido Günther <agx@sigxcpu.org> Sat, 20 Feb 2010 14:11:50 +0100
|
||||
|
||||
libguestfs (1.0.61-1) unstable; urgency=low
|
||||
|
||||
* [831bc5f] Imported Upstream version 1.0.61
|
||||
* [b85412e] run checks but disable currently failing tests
|
||||
* [21d7e00] add missing qemu build-dep
|
||||
* [0636bb4] add missing build-dep for perl bindings
|
||||
* [5585a82] add missing build-deps for perl based tools
|
||||
* [e09005c] install virt-df and virt-cat
|
||||
* [342f8e4] install Lib.pm for perl bindings
|
||||
|
||||
-- Guido Günther <agx@sigxcpu.org> Fri, 17 Jul 2009 22:32:07 +0200
|
||||
|
||||
libguestfs (1.0.56-1) unstable; urgency=low
|
||||
|
||||
* [1b77dc8] Imported Upstream version 1.0.56
|
||||
* [0ca461d] drop a all patches merged upstream or superfluous since
|
||||
we're building from a released version now.
|
||||
* [474dc39] no need to call autogen.sh
|
||||
* [32c3d61] amke sure the symlinks get created in time
|
||||
|
||||
-- Guido Günther <agx@sigxcpu.org> Thu, 09 Jul 2009 16:44:21 +0200
|
||||
|
||||
libguestfs (1.0.54+44git127ad3-3) unstable; urgency=low
|
||||
|
||||
* [a6e6cc7] add virt-inspector
|
||||
* [1446178] build-dep on libaugeas-dev for augeas support in guestfsd
|
||||
* [b3769ed] select kernel by architecture
|
||||
* [103069f] speed up appliance startup
|
||||
* [aa02c11] document changes and release 1.0.54+44git127ad3-3
|
||||
|
||||
-- Guido Günther <agx@sigxcpu.org> Sat, 04 Jul 2009 17:58:04 +0200
|
||||
|
||||
libguestfs (1.0.54+44git127ad3-2) unstable; urgency=low
|
||||
|
||||
* [8f1cea9] add missing shlibs dependency
|
||||
* [35663fe] shorten long descriptions a bit
|
||||
* [1631e0e] add watch file
|
||||
* [adebbd1] drop lib from python package name
|
||||
* [a24e6b9] add perl bindings
|
||||
* [cc2117e] don't run dh_makeshlibs on python lib to avoid ldconfig call
|
||||
* [d361e06] add missing ${misc:Depends}, {perl:Depends} and tighten
|
||||
dependency on libguestfs
|
||||
|
||||
-- Guido Günther <agx@sigxcpu.org> Fri, 03 Jul 2009 12:03:14 +0200
|
||||
|
||||
libguestfs (1.0.54+44git127ad3-1) unstable; urgency=low
|
||||
|
||||
* [4cea8bd] Imported Upstream version 1.0.54+44git127ad3
|
||||
* [c01721f] switch to cdbs:
|
||||
* add doc package
|
||||
* add debug package
|
||||
* add python bindings
|
||||
* drop README.Debian
|
||||
* set maintainer to pkg-libvirt team
|
||||
* [91fafca] don't call configure, leave this to cdbs and make autoconf copy
|
||||
files instead of symlinking so dpkg-source can create a proper .diff.gz
|
||||
* [13207b9] drop .gitignore
|
||||
* [967d228] touch fakeroot.log to indicate the appliance has been built
|
||||
* [3477d95] use AM_MAINTAINER_MODE
|
||||
|
||||
-- Guido Günther <agx@sigxcpu.org> Thu, 02 Jul 2009 21:49:44 +0200
|
||||
|
||||
libguestfs (1.0.41-1) unstable; urgency=low
|
||||
|
||||
* New upstream release 1.0.41.
|
||||
|
||||
-- Richard Jones <rjones@redhat.com> Thu, 04 Jun 2009 16:10:38 +0100
|
||||
|
||||
libguestfs (1.0.31-1) unstable; urgency=low
|
||||
|
||||
* Initial release (Closes: #530427)
|
||||
|
||||
-- Richard Jones <rjones@redhat.com> Sun, 24 May 2009 21:43:45 +0100
|
||||
1
debian/compat
vendored
1
debian/compat
vendored
@@ -1 +0,0 @@
|
||||
7
|
||||
295
debian/control
vendored
295
debian/control
vendored
@@ -1,295 +0,0 @@
|
||||
Source: libguestfs
|
||||
Section: libs
|
||||
Priority: extra
|
||||
Maintainer: Debian Libvirt Maintainers <pkg-libvirt-maintainers@lists.alioth.debian.org>
|
||||
Uploaders: Richard Jones <rjones@redhat.com>, Guido Günther <agx@sigxcpu.org>
|
||||
Build-Depends: debhelper (>= 7), dpkg-dev, devscripts, autotools-dev,
|
||||
febootstrap (>= 3.2),
|
||||
libreadline-dev, cdbs, libaugeas-dev, libhivex-dev, libvirt-dev,
|
||||
libmagic-dev, libncurses5-dev, libpcre3-dev, libxml2-dev,
|
||||
gperf,
|
||||
# XXX libconfig-dev, but it is not in Debian
|
||||
qemu-system (>= 0.13) | kvm (>= 0.13) | qemu-kvm (>= 0.13) | qemu (>= 0.13),
|
||||
# XXX how to say we need Linux >= 2.6.36?
|
||||
genisoimage, pkg-config,
|
||||
# when building from git:
|
||||
automake, autoconf, libtool, ocaml, ocaml-findlib,
|
||||
# for python bindings:
|
||||
python-all-dev, python-support,
|
||||
# for the perl bindings:
|
||||
libtest-pod-coverage-perl, libextutils-command-perl,
|
||||
libintl-perl, libtest-pod-perl,
|
||||
libstring-shellquote-perl,
|
||||
# for Perl virt tools
|
||||
libsys-virt-perl, libwin-hivex-perl,
|
||||
# FUSE
|
||||
libfuse-dev, fuse-utils,
|
||||
# Debian OCaml
|
||||
dh-ocaml,
|
||||
# to create images in the test suite
|
||||
db4.8-util
|
||||
Homepage: http://libguestfs.org
|
||||
Standards-Version: 3.8.2
|
||||
|
||||
Package: libguestfs0
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends},
|
||||
febootstrap (>= 3.2),
|
||||
# These are needed for virtio-serial:
|
||||
qemu-system (>= 0.13) | kvm (>= 0.13) | qemu-kvm (>= 0.13) | qemu (>= 0.13),
|
||||
# XXX how to say we need Linux >= 2.6.36?
|
||||
# For the supermin appliance (see appliance/packagelist):
|
||||
bsdmainutils,
|
||||
btrfs-tools,
|
||||
cryptsetup,
|
||||
diff,
|
||||
# gfs-tools,
|
||||
# gfs2-tools,
|
||||
grub-pc,
|
||||
# hfsplus,
|
||||
iproute,
|
||||
libaugeas0,
|
||||
# nilfs2-tools,
|
||||
ntfs-3g,
|
||||
ntfsprogs,
|
||||
reiserfsprogs,
|
||||
udev,
|
||||
vim-tiny,
|
||||
xz-utils,
|
||||
zfs-fuse,
|
||||
binutils,
|
||||
cpio,
|
||||
dosfstools,
|
||||
file,
|
||||
jfsutils,
|
||||
lsof,
|
||||
lvm2,
|
||||
module-init-tools,
|
||||
net-tools,
|
||||
parted,
|
||||
procps,
|
||||
scrub,
|
||||
strace,
|
||||
xfsprogs,
|
||||
zerofree
|
||||
Description: library for accessing and modifying guest disk images
|
||||
libguestfs is a library for accessing and modifying guest disk images. Amongst
|
||||
the things this is good for: making batch configuration changes to guests,
|
||||
viewing and editing files inside guests, getting disk used/free statistics,
|
||||
migrating between virtualization systems, performing partial backups,
|
||||
performing partial guest clones, cloning guests and changing
|
||||
registry/UUID/hostname info, and much else besides.
|
||||
.
|
||||
It uses Linux kernel and qemu code, and can access any type of guest
|
||||
filesystem that Linux and qemu can, including but not limited to: ext2/3/4,
|
||||
btrfs, FAT and NTFS, LVM, many different disk partition schemes, qcow, qcow2,
|
||||
vmdk.
|
||||
.
|
||||
libguestfs provides ways to enumerate guest storage (eg. partitions, LVs, what
|
||||
filesystem is in each LV, etc.). It can also run commands in the context of
|
||||
the guest. Also you can upload and download files and directories.
|
||||
|
||||
Package: guestfish
|
||||
Section: devel
|
||||
Architecture: any
|
||||
Depends: libguestfs0 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: libguestfs filesystem interactive shell
|
||||
Guestfish is a shell and command-line tool for examining and modifying
|
||||
virtual machine filesystems. It uses libguestfs and exposes all of the
|
||||
functionality of the guestfs API, see guestfs(3).
|
||||
|
||||
Package: guestfsd
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends},
|
||||
bsdmainutils, diff, grub-pc, iproute,
|
||||
libaugeas0, udev, binutils, cpio, dosfstools,
|
||||
file, lsof, module-init-tools, net-tools, parted,
|
||||
procps, scrub, strace, zerofree
|
||||
Description: Daemon to access to guest virtual machine through virtio serial
|
||||
Daemon to access to guest virtual machine through virtio serial
|
||||
|
||||
Package: guestmount
|
||||
Section: devel
|
||||
Architecture: any
|
||||
Depends: libguestfs0 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: mount guest filesystem using libguestfs and FUSE
|
||||
The guestmount program can be used to mount virtual machine filesystems
|
||||
and other disk images on the host. It uses libguestfs for access to
|
||||
the guest filesystem, and FUSE (the "filesystem in userspace") to make
|
||||
it appear as a mountable device.
|
||||
|
||||
Package: libguestfs-tools
|
||||
Section: devel
|
||||
Architecture: any
|
||||
Depends: libguestfs0 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends},
|
||||
libsys-virt-perl, libguestfs-perl (= ${binary:Version})
|
||||
Description: libguestfs virt tools
|
||||
This package contains virt tools including virt-cat, virt-df, virt-edit,
|
||||
virt-filesystems, virt-inspector, virt-ls, virt-make-fs, virt-rescue,
|
||||
virt-resize, virt-tar and virt-win-reg.
|
||||
|
||||
Package: libguestfs-dev
|
||||
Section: libdevel
|
||||
Architecture: any
|
||||
Depends: libguestfs0 (= ${binary:Version}), ${misc:Depends}
|
||||
Description: library for accessing and modifying guest disk images
|
||||
libguestfs is a library for accessing and modifying guest disk images. Amongst
|
||||
the things this is good for: making batch configuration changes to guests,
|
||||
viewing and editing files inside guests, getting disk used/free statistics,
|
||||
migrating between virtualization systems, performing partial backups,
|
||||
performing partial guest clones, cloning guests and changing
|
||||
registry/UUID/hostname info, and much else besides.
|
||||
.
|
||||
It uses Linux kernel and qemu code, and can access any type of guest
|
||||
filesystem that Linux and qemu can, including but not limited to: ext2/3/4,
|
||||
btrfs, FAT and NTFS, LVM, many different disk partition schemes, qcow, qcow2,
|
||||
vmdk.
|
||||
.
|
||||
libguestfs provides ways to enumerate guest storage (eg. partitions, LVs, what
|
||||
filesystem is in each LV, etc.). It can also run commands in the context of
|
||||
the guest. Also you can upload and download files and directories.
|
||||
.
|
||||
This package contains the development headers.
|
||||
|
||||
Package: libguestfs0-dbg
|
||||
Section: debug
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, libguestfs0 (= ${binary:Version})
|
||||
Description: library for accessing and modifying guest disk images
|
||||
libguestfs is a library for accessing and modifying guest disk images. Amongst
|
||||
the things this is good for: making batch configuration changes to guests,
|
||||
viewing and editing files inside guests, getting disk used/free statistics,
|
||||
migrating between virtualization systems, performing partial backups,
|
||||
performing partial guest clones, cloning guests and changing
|
||||
registry/UUID/hostname info, and much else besides.
|
||||
.
|
||||
It uses Linux kernel and qemu code, and can access any type of guest
|
||||
filesystem that Linux and qemu can, including but not limited to: ext2/3/4,
|
||||
btrfs, FAT and NTFS, LVM, many different disk partition schemes, qcow, qcow2,
|
||||
vmdk.
|
||||
.
|
||||
libguestfs provides ways to enumerate guest storage (eg. partitions, LVs, what
|
||||
filesystem is in each LV, etc.). It can also run commands in the context of
|
||||
the guest. Also you can upload and download files and directories.
|
||||
.
|
||||
This package contains the debugging symbols.
|
||||
|
||||
Package: libguestfs-doc
|
||||
Section: doc
|
||||
Architecture: all
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: library for accessing and modifying guest disk images
|
||||
libguestfs is a library for accessing and modifying guest disk images. Amongst
|
||||
the things this is good for: making batch configuration changes to guests,
|
||||
viewing and editing files inside guests, getting disk used/free statistics,
|
||||
migrating between virtualization systems, performing partial backups,
|
||||
performing partial guest clones, cloning guests and changing
|
||||
registry/UUID/hostname info, and much else besides.
|
||||
.
|
||||
It uses Linux kernel and qemu code, and can access any type of guest
|
||||
filesystem that Linux and qemu can, including but not limited to: ext2/3/4,
|
||||
btrfs, FAT and NTFS, LVM, many different disk partition schemes, qcow, qcow2,
|
||||
vmdk.
|
||||
.
|
||||
libguestfs provides ways to enumerate guest storage (eg. partitions, LVs, what
|
||||
filesystem is in each LV, etc.). It can also run commands in the context of
|
||||
the guest. Also you can upload and download files and directories.
|
||||
.
|
||||
This package contains the documentation.
|
||||
|
||||
Package: python-guestfs
|
||||
Section: python
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, libguestfs0 (= ${binary:Version})
|
||||
Provides: python-libguestfs
|
||||
Conflicts: python-libguestfs
|
||||
Description: library for accessing and modifying guest disk images
|
||||
libguestfs is a library for accessing and modifying guest disk images. Amongst
|
||||
the things this is good for: making batch configuration changes to guests,
|
||||
viewing and editing files inside guests, getting disk used/free statistics,
|
||||
migrating between virtualization systems, performing partial backups,
|
||||
performing partial guest clones, cloning guests and changing
|
||||
registry/UUID/hostname info, and much else besides.
|
||||
.
|
||||
It uses Linux kernel and qemu code, and can access any type of guest
|
||||
filesystem that Linux and qemu can, including but not limited to: ext2/3/4,
|
||||
btrfs, FAT and NTFS, LVM, many different disk partition schemes, qcow, qcow2,
|
||||
vmdk.
|
||||
.
|
||||
libguestfs provides ways to enumerate guest storage (eg. partitions, LVs, what
|
||||
filesystem is in each LV, etc.). It can also run commands in the context of
|
||||
the guest. Also you can upload and download files and directories.
|
||||
.
|
||||
This package contains the Python bindings.
|
||||
|
||||
Package: libguestfs-perl
|
||||
Section: perl
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, libguestfs0 (= ${binary:Version}),
|
||||
${perl:Depends}
|
||||
Description: library for accessing and modifying guest disk images
|
||||
libguestfs is a library for accessing and modifying guest disk images. Amongst
|
||||
the things this is good for: making batch configuration changes to guests,
|
||||
viewing and editing files inside guests, getting disk used/free statistics,
|
||||
migrating between virtualization systems, performing partial backups,
|
||||
performing partial guest clones, cloning guests and changing
|
||||
registry/UUID/hostname info, and much else besides.
|
||||
.
|
||||
It uses Linux kernel and qemu code, and can access any type of guest
|
||||
filesystem that Linux and qemu can, including but not limited to: ext2/3/4,
|
||||
btrfs, FAT and NTFS, LVM, many different disk partition schemes, qcow, qcow2,
|
||||
vmdk.
|
||||
.
|
||||
libguestfs provides ways to enumerate guest storage (eg. partitions, LVs, what
|
||||
filesystem is in each LV, etc.). It can also run commands in the context of
|
||||
the guest. Also you can upload and download files and directories.
|
||||
.
|
||||
This package contains the Perl bindings.
|
||||
|
||||
Package: libguestfs-ocaml
|
||||
Architecture: any
|
||||
Depends: ${ocaml:Depends}, ${shlibs:Depends}, ${misc:Depends}
|
||||
Provides: ${ocaml:Provides}
|
||||
Description: library for accessing and modifying guest disk images
|
||||
libguestfs is a library for accessing and modifying guest disk images. Amongst
|
||||
the things this is good for: making batch configuration changes to guests,
|
||||
viewing and editing files inside guests, getting disk used/free statistics,
|
||||
migrating between virtualization systems, performing partial backups,
|
||||
performing partial guest clones, cloning guests and changing
|
||||
registry/UUID/hostname info, and much else besides.
|
||||
.
|
||||
It uses Linux kernel and qemu code, and can access any type of guest
|
||||
filesystem that Linux and qemu can, including but not limited to: ext2/3/4,
|
||||
btrfs, FAT and NTFS, LVM, many different disk partition schemes, qcow, qcow2,
|
||||
vmdk.
|
||||
.
|
||||
libguestfs provides ways to enumerate guest storage (eg. partitions, LVs, what
|
||||
filesystem is in each LV, etc.). It can also run commands in the context of
|
||||
the guest. Also you can upload and download files and directories.
|
||||
.
|
||||
This package contains the OCaml bindings (runtime).
|
||||
|
||||
Package: libguestfs-ocaml-dev
|
||||
Architecture: any
|
||||
Depends: libguestfs-ocaml, libguestfs-dev, ocaml-findlib,
|
||||
${ocaml:Depends},
|
||||
${misc:Depends}
|
||||
Provides: ${ocaml:Provides}
|
||||
Description: library for accessing and modifying guest disk images
|
||||
libguestfs is a library for accessing and modifying guest disk images. Amongst
|
||||
the things this is good for: making batch configuration changes to guests,
|
||||
viewing and editing files inside guests, getting disk used/free statistics,
|
||||
migrating between virtualization systems, performing partial backups,
|
||||
performing partial guest clones, cloning guests and changing
|
||||
registry/UUID/hostname info, and much else besides.
|
||||
.
|
||||
It uses Linux kernel and qemu code, and can access any type of guest
|
||||
filesystem that Linux and qemu can, including but not limited to: ext2/3/4,
|
||||
btrfs, FAT and NTFS, LVM, many different disk partition schemes, qcow, qcow2,
|
||||
vmdk.
|
||||
.
|
||||
libguestfs provides ways to enumerate guest storage (eg. partitions, LVs, what
|
||||
filesystem is in each LV, etc.). It can also run commands in the context of
|
||||
the guest. Also you can upload and download files and directories.
|
||||
.
|
||||
This package contains the OCaml bindings.
|
||||
24
debian/copyright
vendored
24
debian/copyright
vendored
@@ -1,24 +0,0 @@
|
||||
This package was debianized by Richard Jones <rjones@redhat.com> on
|
||||
Sun, 24 May 2009 21:43:45 +0100.
|
||||
|
||||
It was downloaded from http://et.redhat.com/~rjones/libguestfs/
|
||||
|
||||
Upstream Authors:
|
||||
|
||||
Richard W.M. Jones <rjones@redhat.com>
|
||||
Red Hat Inc.
|
||||
|
||||
Copyright:
|
||||
|
||||
Copyright (C) 2009 Red Hat Inc.
|
||||
|
||||
License:
|
||||
|
||||
LGPL (v2+)
|
||||
|
||||
The Debian packaging is:
|
||||
|
||||
Copyright (C) 2009 Richard Jones <rjones@redhat.com>
|
||||
|
||||
and is licensed under the GPL version 3,
|
||||
see `/usr/share/common-licenses/GPL-3'.
|
||||
2
debian/docs
vendored
2
debian/docs
vendored
@@ -1,2 +0,0 @@
|
||||
README
|
||||
TODO
|
||||
2
debian/guestfish.dirs
vendored
2
debian/guestfish.dirs
vendored
@@ -1,2 +0,0 @@
|
||||
usr/bin
|
||||
usr/share/man/man1
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user