3 * Copyright (C) 2009 Red Hat Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 (* This script generates a large amount of code and documentation for
21 * all the daemon actions.
23 * To add a new action there are only two files you need to change,
24 * this one to describe the interface (see the big table below), and
25 * daemon/<somefile>.c to write the implementation.
27 * After editing this file, run it (./src/generator.ml) to regenerate
28 * all the output files.
30 * IMPORTANT: This script should NOT print any warnings. If it prints
31 * warnings, you should treat them as errors.
32 * [Need to add -warn-error to ocaml command line]
40 type style = ret * args
42 (* "RErr" as a return value means an int used as a simple error
43 * indication, ie. 0 or -1.
46 (* "RInt" as a return value means an int which is -1 for error
47 * or any value >= 0 on success. Only use this for smallish
48 * positive ints (0 <= i < 2^30).
51 (* "RInt64" is the same as RInt, but is guaranteed to be able
52 * to return a full 64 bit value, _except_ that -1 means error
53 * (so -1 cannot be a valid, non-error return value).
56 (* "RBool" is a bool return value which can be true/false or
60 (* "RConstString" is a string that refers to a constant value.
61 * Try to avoid using this. In particular you cannot use this
62 * for values returned from the daemon, because there is no
63 * thread-safe way to return them in the C API.
65 | RConstString of string
66 (* "RString" and "RStringList" are caller-frees. *)
68 | RStringList of string
69 (* Some limited tuples are possible: *)
70 | RIntBool of string * string
71 (* LVM PVs, VGs and LVs. *)
78 (* Key-value pairs of untyped strings. Turns into a hashtable or
79 * dictionary in languages which support it. DON'T use this as a
80 * general "bucket" for results. Prefer a stronger typed return
81 * value if one is available, or write a custom struct. Don't use
82 * this if the list could potentially be very long, since it is
83 * inefficient. Keys should be unique. NULLs are not permitted.
85 | RHashtable of string
87 and args = argt list (* Function parameters, guestfs handle is implicit. *)
89 (* Note in future we should allow a "variable args" parameter as
90 * the final parameter, to allow commands like
91 * chmod mode file [file(s)...]
92 * This is not implemented yet, but many commands (such as chmod)
93 * are currently defined with the argument order keeping this future
94 * possibility in mind.
97 | String of string (* const char *name, cannot be NULL *)
98 | OptString of string (* const char *name, may be NULL *)
99 | StringList of string(* list of strings (each string cannot be NULL) *)
100 | Bool of string (* boolean *)
101 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
102 (* These are treated as filenames (simple string parameters) in
103 * the C API and bindings. But in the RPC protocol, we transfer
104 * the actual file content up to or down from the daemon.
105 * FileIn: local machine -> daemon (in request)
106 * FileOut: daemon -> local machine (in reply)
107 * In guestfish (only), the special name "-" means read from
108 * stdin or write to stdout.
114 | ProtocolLimitWarning (* display warning about protocol size limits *)
115 | DangerWillRobinson (* flags particularly dangerous commands *)
116 | FishAlias of string (* provide an alias for this cmd in guestfish *)
117 | FishAction of string (* call this function in guestfish *)
118 | NotInFish (* do not export via guestfish *)
120 let protocol_limit_warning =
121 "Because of the message protocol, there is a transfer limit
122 of somewhere between 2MB and 4MB. To transfer large files you should use
125 let danger_will_robinson =
126 "B<This command is dangerous. Without careful use you
127 can easily destroy all your data>."
129 (* You can supply zero or as many tests as you want per API call.
131 * Note that the test environment has 3 block devices, of size 500MB,
132 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc).
133 * Note for partitioning purposes, the 500MB device has 63 cylinders.
135 * To be able to run the tests in a reasonable amount of time,
136 * the virtual machine and block devices are reused between tests.
137 * So don't try testing kill_subprocess :-x
139 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
141 * If the appliance is running an older Linux kernel (eg. RHEL 5) then
142 * devices are named /dev/hda etc. To cope with this, the test suite
143 * adds some hairly logic to detect this case, and then automagically
144 * replaces all strings which match "/dev/sd.*" with "/dev/hd.*".
145 * When writing test cases you shouldn't have to worry about this
148 * Don't assume anything about the previous contents of the block
149 * devices. Use 'Init*' to create some initial scenarios.
151 * You can add a prerequisite clause to any individual test. This
152 * is a run-time check, which, if it fails, causes the test to be
153 * skipped. Useful if testing a command which might not work on
154 * all variations of libguestfs builds. A test that has prerequisite
155 * of 'Always' is run unconditionally.
157 * In addition, packagers can skip individual tests by setting the
158 * environment variables: eg:
159 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
160 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
162 type tests = (test_init * test_prereq * test) list
164 (* Run the command sequence and just expect nothing to fail. *)
166 (* Run the command sequence and expect the output of the final
167 * command to be the string.
169 | TestOutput of seq * string
170 (* Run the command sequence and expect the output of the final
171 * command to be the list of strings.
173 | TestOutputList of seq * string list
174 (* Run the command sequence and expect the output of the final
175 * command to be the integer.
177 | TestOutputInt of seq * int
178 (* Run the command sequence and expect the output of the final
179 * command to be a true value (!= 0 or != NULL).
181 | TestOutputTrue of seq
182 (* Run the command sequence and expect the output of the final
183 * command to be a false value (== 0 or == NULL, but not an error).
185 | TestOutputFalse of seq
186 (* Run the command sequence and expect the output of the final
187 * command to be a list of the given length (but don't care about
190 | TestOutputLength of seq * int
191 (* Run the command sequence and expect the output of the final
192 * command to be a structure.
194 | TestOutputStruct of seq * test_field_compare list
195 (* Run the command sequence and expect the final command (only)
198 | TestLastFail of seq
200 and test_field_compare =
201 | CompareWithInt of string * int
202 | CompareWithString of string * string
203 | CompareFieldsIntEq of string * string
204 | CompareFieldsStrEq of string * string
206 (* Test prerequisites. *)
208 (* Test always runs. *)
210 (* Test is currently disabled - eg. it fails, or it tests some
211 * unimplemented feature.
214 (* 'string' is some C code (a function body) that should return
215 * true or false. The test will run if the code returns true.
218 (* As for 'If' but the test runs _unless_ the code returns true. *)
221 (* Some initial scenarios for testing. *)
223 (* Do nothing, block devices could contain random stuff including
224 * LVM PVs, and some filesystems might be mounted. This is usually
228 (* Block devices are empty and no filesystems are mounted. *)
230 (* /dev/sda contains a single partition /dev/sda1, which is formatted
231 * as ext2, empty [except for lost+found] and mounted on /.
232 * /dev/sdb and /dev/sdc may have random content.
237 * /dev/sda1 (is a PV):
238 * /dev/VG/LV (size 8MB):
239 * formatted as ext2, empty [except for lost+found], mounted on /
240 * /dev/sdb and /dev/sdc may have random content.
244 (* Sequence of commands for testing. *)
246 and cmd = string list
248 (* Note about long descriptions: When referring to another
249 * action, use the format C<guestfs_other> (ie. the full name of
250 * the C function). This will be replaced as appropriate in other
253 * Apart from that, long descriptions are just perldoc paragraphs.
256 let non_daemon_functions = [
257 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
259 "launch the qemu subprocess",
261 Internally libguestfs is implemented by running a virtual machine
264 You should call this after configuring the handle
265 (eg. adding drives) but before performing any actions.");
267 ("wait_ready", (RErr, []), -1, [NotInFish],
269 "wait until the qemu subprocess launches",
271 Internally libguestfs is implemented by running a virtual machine
274 You should call this after C<guestfs_launch> to wait for the launch
277 ("kill_subprocess", (RErr, []), -1, [],
279 "kill the qemu subprocess",
281 This kills the qemu subprocess. You should never need to call this.");
283 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
285 "add an image to examine or modify",
287 This function adds a virtual machine disk image C<filename> to the
288 guest. The first time you call this function, the disk appears as IDE
289 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
292 You don't necessarily need to be root when using libguestfs. However
293 you obviously do need sufficient permissions to access the filename
294 for whatever operations you want to perform (ie. read access if you
295 just want to read the image or write access if you want to modify the
298 This is equivalent to the qemu parameter C<-drive file=filename>.");
300 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
302 "add a CD-ROM disk image to examine",
304 This function adds a virtual CD-ROM disk image to the guest.
306 This is equivalent to the qemu parameter C<-cdrom filename>.");
308 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
310 "add qemu parameters",
312 This can be used to add arbitrary qemu command line parameters
313 of the form C<-param value>. Actually it's not quite arbitrary - we
314 prevent you from setting some parameters which would interfere with
315 parameters that we use.
317 The first character of C<param> string must be a C<-> (dash).
319 C<value> can be NULL.");
321 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
323 "set the qemu binary",
325 Set the qemu binary that we will use.
327 The default is chosen when the library was compiled by the
330 You can also override this by setting the C<LIBGUESTFS_QEMU>
331 environment variable.
333 Setting C<qemu> to C<NULL> restores the default qemu binary.");
335 ("get_qemu", (RConstString "qemu", []), -1, [],
337 "get the qemu binary",
339 Return the current qemu binary.
341 This is always non-NULL. If it wasn't set already, then this will
342 return the default qemu binary name.");
344 ("set_path", (RErr, [String "path"]), -1, [FishAlias "path"],
346 "set the search path",
348 Set the path that libguestfs searches for kernel and initrd.img.
350 The default is C<$libdir/guestfs> unless overridden by setting
351 C<LIBGUESTFS_PATH> environment variable.
353 Setting C<path> to C<NULL> restores the default path.");
355 ("get_path", (RConstString "path", []), -1, [],
357 "get the search path",
359 Return the current search path.
361 This is always non-NULL. If it wasn't set already, then this will
362 return the default path.");
364 ("set_append", (RErr, [String "append"]), -1, [FishAlias "append"],
366 "add options to kernel command line",
368 This function is used to add additional options to the
369 guest kernel command line.
371 The default is C<NULL> unless overridden by setting
372 C<LIBGUESTFS_APPEND> environment variable.
374 Setting C<append> to C<NULL> means I<no> additional options
375 are passed (libguestfs always adds a few of its own).");
377 ("get_append", (RConstString "append", []), -1, [],
379 "get the additional kernel options",
381 Return the additional kernel options which are added to the
382 guest kernel command line.
384 If C<NULL> then no options are added.");
386 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
390 If C<autosync> is true, this enables autosync. Libguestfs will make a
391 best effort attempt to run C<guestfs_umount_all> followed by
392 C<guestfs_sync> when the handle is closed
393 (also if the program exits without closing handles).
395 This is disabled by default (except in guestfish where it is
396 enabled by default).");
398 ("get_autosync", (RBool "autosync", []), -1, [],
402 Get the autosync flag.");
404 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
408 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
410 Verbose messages are disabled unless the environment variable
411 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
413 ("get_verbose", (RBool "verbose", []), -1, [],
417 This returns the verbose messages flag.");
419 ("is_ready", (RBool "ready", []), -1, [],
421 "is ready to accept commands",
423 This returns true iff this handle is ready to accept commands
424 (in the C<READY> state).
426 For more information on states, see L<guestfs(3)>.");
428 ("is_config", (RBool "config", []), -1, [],
430 "is in configuration state",
432 This returns true iff this handle is being configured
433 (in the C<CONFIG> state).
435 For more information on states, see L<guestfs(3)>.");
437 ("is_launching", (RBool "launching", []), -1, [],
439 "is launching subprocess",
441 This returns true iff this handle is launching the subprocess
442 (in the C<LAUNCHING> state).
444 For more information on states, see L<guestfs(3)>.");
446 ("is_busy", (RBool "busy", []), -1, [],
448 "is busy processing a command",
450 This returns true iff this handle is busy processing a command
451 (in the C<BUSY> state).
453 For more information on states, see L<guestfs(3)>.");
455 ("get_state", (RInt "state", []), -1, [],
457 "get the current state",
459 This returns the current state as an opaque integer. This is
460 only useful for printing debug and internal error messages.
462 For more information on states, see L<guestfs(3)>.");
464 ("set_busy", (RErr, []), -1, [NotInFish],
468 This sets the state to C<BUSY>. This is only used when implementing
469 actions using the low-level API.
471 For more information on states, see L<guestfs(3)>.");
473 ("set_ready", (RErr, []), -1, [NotInFish],
475 "set state to ready",
477 This sets the state to C<READY>. This is only used when implementing
478 actions using the low-level API.
480 For more information on states, see L<guestfs(3)>.");
482 ("end_busy", (RErr, []), -1, [NotInFish],
484 "leave the busy state",
486 This sets the state to C<READY>, or if in C<CONFIG> then it leaves the
487 state as is. This is only used when implementing
488 actions using the low-level API.
490 For more information on states, see L<guestfs(3)>.");
494 let daemon_functions = [
495 ("mount", (RErr, [String "device"; String "mountpoint"]), 1, [],
496 [InitEmpty, Always, TestOutput (
497 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
498 ["mkfs"; "ext2"; "/dev/sda1"];
499 ["mount"; "/dev/sda1"; "/"];
500 ["write_file"; "/new"; "new file contents"; "0"];
501 ["cat"; "/new"]], "new file contents")],
502 "mount a guest disk at a position in the filesystem",
504 Mount a guest disk at a position in the filesystem. Block devices
505 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
506 the guest. If those block devices contain partitions, they will have
507 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
510 The rules are the same as for L<mount(2)>: A filesystem must
511 first be mounted on C</> before others can be mounted. Other
512 filesystems can only be mounted on directories which already
515 The mounted filesystem is writable, if we have sufficient permissions
516 on the underlying device.
518 The filesystem options C<sync> and C<noatime> are set with this
519 call, in order to improve reliability.");
521 ("sync", (RErr, []), 2, [],
522 [ InitEmpty, Always, TestRun [["sync"]]],
523 "sync disks, writes are flushed through to the disk image",
525 This syncs the disk, so that any writes are flushed through to the
526 underlying disk image.
528 You should always call this if you have modified a disk image, before
529 closing the handle.");
531 ("touch", (RErr, [String "path"]), 3, [],
532 [InitBasicFS, Always, TestOutputTrue (
534 ["exists"; "/new"]])],
535 "update file timestamps or create a new file",
537 Touch acts like the L<touch(1)> command. It can be used to
538 update the timestamps on a file, or, if the file does not exist,
539 to create a new zero-length file.");
541 ("cat", (RString "content", [String "path"]), 4, [ProtocolLimitWarning],
542 [InitBasicFS, Always, TestOutput (
543 [["write_file"; "/new"; "new file contents"; "0"];
544 ["cat"; "/new"]], "new file contents")],
545 "list the contents of a file",
547 Return the contents of the file named C<path>.
549 Note that this function cannot correctly handle binary files
550 (specifically, files containing C<\\0> character which is treated
551 as end of string). For those you need to use the C<guestfs_download>
552 function which has a more complex interface.");
554 ("ll", (RString "listing", [String "directory"]), 5, [],
555 [], (* XXX Tricky to test because it depends on the exact format
556 * of the 'ls -l' command, which changes between F10 and F11.
558 "list the files in a directory (long format)",
560 List the files in C<directory> (relative to the root directory,
561 there is no cwd) in the format of 'ls -la'.
563 This command is mostly useful for interactive sessions. It
564 is I<not> intended that you try to parse the output string.");
566 ("ls", (RStringList "listing", [String "directory"]), 6, [],
567 [InitBasicFS, Always, TestOutputList (
570 ["touch"; "/newest"];
571 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
572 "list the files in a directory",
574 List the files in C<directory> (relative to the root directory,
575 there is no cwd). The '.' and '..' entries are not returned, but
576 hidden files are shown.
578 This command is mostly useful for interactive sessions. Programs
579 should probably use C<guestfs_readdir> instead.");
581 ("list_devices", (RStringList "devices", []), 7, [],
582 [InitEmpty, Always, TestOutputList (
583 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"])],
584 "list the block devices",
586 List all the block devices.
588 The full block device names are returned, eg. C</dev/sda>");
590 ("list_partitions", (RStringList "partitions", []), 8, [],
591 [InitBasicFS, Always, TestOutputList (
592 [["list_partitions"]], ["/dev/sda1"]);
593 InitEmpty, Always, TestOutputList (
594 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
595 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
596 "list the partitions",
598 List all the partitions detected on all block devices.
600 The full partition device names are returned, eg. C</dev/sda1>
602 This does not return logical volumes. For that you will need to
603 call C<guestfs_lvs>.");
605 ("pvs", (RStringList "physvols", []), 9, [],
606 [InitBasicFSonLVM, Always, TestOutputList (
607 [["pvs"]], ["/dev/sda1"]);
608 InitEmpty, Always, TestOutputList (
609 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
610 ["pvcreate"; "/dev/sda1"];
611 ["pvcreate"; "/dev/sda2"];
612 ["pvcreate"; "/dev/sda3"];
613 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
614 "list the LVM physical volumes (PVs)",
616 List all the physical volumes detected. This is the equivalent
617 of the L<pvs(8)> command.
619 This returns a list of just the device names that contain
620 PVs (eg. C</dev/sda2>).
622 See also C<guestfs_pvs_full>.");
624 ("vgs", (RStringList "volgroups", []), 10, [],
625 [InitBasicFSonLVM, Always, TestOutputList (
627 InitEmpty, Always, TestOutputList (
628 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
629 ["pvcreate"; "/dev/sda1"];
630 ["pvcreate"; "/dev/sda2"];
631 ["pvcreate"; "/dev/sda3"];
632 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
633 ["vgcreate"; "VG2"; "/dev/sda3"];
634 ["vgs"]], ["VG1"; "VG2"])],
635 "list the LVM volume groups (VGs)",
637 List all the volumes groups detected. This is the equivalent
638 of the L<vgs(8)> command.
640 This returns a list of just the volume group names that were
641 detected (eg. C<VolGroup00>).
643 See also C<guestfs_vgs_full>.");
645 ("lvs", (RStringList "logvols", []), 11, [],
646 [InitBasicFSonLVM, Always, TestOutputList (
647 [["lvs"]], ["/dev/VG/LV"]);
648 InitEmpty, Always, TestOutputList (
649 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
650 ["pvcreate"; "/dev/sda1"];
651 ["pvcreate"; "/dev/sda2"];
652 ["pvcreate"; "/dev/sda3"];
653 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
654 ["vgcreate"; "VG2"; "/dev/sda3"];
655 ["lvcreate"; "LV1"; "VG1"; "50"];
656 ["lvcreate"; "LV2"; "VG1"; "50"];
657 ["lvcreate"; "LV3"; "VG2"; "50"];
658 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
659 "list the LVM logical volumes (LVs)",
661 List all the logical volumes detected. This is the equivalent
662 of the L<lvs(8)> command.
664 This returns a list of the logical volume device names
665 (eg. C</dev/VolGroup00/LogVol00>).
667 See also C<guestfs_lvs_full>.");
669 ("pvs_full", (RPVList "physvols", []), 12, [],
670 [], (* XXX how to test? *)
671 "list the LVM physical volumes (PVs)",
673 List all the physical volumes detected. This is the equivalent
674 of the L<pvs(8)> command. The \"full\" version includes all fields.");
676 ("vgs_full", (RVGList "volgroups", []), 13, [],
677 [], (* XXX how to test? *)
678 "list the LVM volume groups (VGs)",
680 List all the volumes groups detected. This is the equivalent
681 of the L<vgs(8)> command. The \"full\" version includes all fields.");
683 ("lvs_full", (RLVList "logvols", []), 14, [],
684 [], (* XXX how to test? *)
685 "list the LVM logical volumes (LVs)",
687 List all the logical volumes detected. This is the equivalent
688 of the L<lvs(8)> command. The \"full\" version includes all fields.");
690 ("read_lines", (RStringList "lines", [String "path"]), 15, [],
691 [InitBasicFS, Always, TestOutputList (
692 [["write_file"; "/new"; "line1\r\nline2\nline3"; "0"];
693 ["read_lines"; "/new"]], ["line1"; "line2"; "line3"]);
694 InitBasicFS, Always, TestOutputList (
695 [["write_file"; "/new"; ""; "0"];
696 ["read_lines"; "/new"]], [])],
697 "read file as lines",
699 Return the contents of the file named C<path>.
701 The file contents are returned as a list of lines. Trailing
702 C<LF> and C<CRLF> character sequences are I<not> returned.
704 Note that this function cannot correctly handle binary files
705 (specifically, files containing C<\\0> character which is treated
706 as end of line). For those you need to use the C<guestfs_read_file>
707 function which has a more complex interface.");
709 ("aug_init", (RErr, [String "root"; Int "flags"]), 16, [],
710 [], (* XXX Augeas code needs tests. *)
711 "create a new Augeas handle",
713 Create a new Augeas handle for editing configuration files.
714 If there was any previous Augeas handle associated with this
715 guestfs session, then it is closed.
717 You must call this before using any other C<guestfs_aug_*>
720 C<root> is the filesystem root. C<root> must not be NULL,
723 The flags are the same as the flags defined in
724 E<lt>augeas.hE<gt>, the logical I<or> of the following
729 =item C<AUG_SAVE_BACKUP> = 1
731 Keep the original file with a C<.augsave> extension.
733 =item C<AUG_SAVE_NEWFILE> = 2
735 Save changes into a file with extension C<.augnew>, and
736 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
738 =item C<AUG_TYPE_CHECK> = 4
740 Typecheck lenses (can be expensive).
742 =item C<AUG_NO_STDINC> = 8
744 Do not use standard load path for modules.
746 =item C<AUG_SAVE_NOOP> = 16
748 Make save a no-op, just record what would have been changed.
750 =item C<AUG_NO_LOAD> = 32
752 Do not load the tree in C<guestfs_aug_init>.
756 To close the handle, you can call C<guestfs_aug_close>.
758 To find out more about Augeas, see L<http://augeas.net/>.");
760 ("aug_close", (RErr, []), 26, [],
761 [], (* XXX Augeas code needs tests. *)
762 "close the current Augeas handle",
764 Close the current Augeas handle and free up any resources
765 used by it. After calling this, you have to call
766 C<guestfs_aug_init> again before you can use any other
769 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
770 [], (* XXX Augeas code needs tests. *)
771 "define an Augeas variable",
773 Defines an Augeas variable C<name> whose value is the result
774 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
777 On success this returns the number of nodes in C<expr>, or
778 C<0> if C<expr> evaluates to something which is not a nodeset.");
780 ("aug_defnode", (RIntBool ("nrnodes", "created"), [String "name"; String "expr"; String "val"]), 18, [],
781 [], (* XXX Augeas code needs tests. *)
782 "define an Augeas node",
784 Defines a variable C<name> whose value is the result of
787 If C<expr> evaluates to an empty nodeset, a node is created,
788 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
789 C<name> will be the nodeset containing that single node.
791 On success this returns a pair containing the
792 number of nodes in the nodeset, and a boolean flag
793 if a node was created.");
795 ("aug_get", (RString "val", [String "path"]), 19, [],
796 [], (* XXX Augeas code needs tests. *)
797 "look up the value of an Augeas path",
799 Look up the value associated with C<path>. If C<path>
800 matches exactly one node, the C<value> is returned.");
802 ("aug_set", (RErr, [String "path"; String "val"]), 20, [],
803 [], (* XXX Augeas code needs tests. *)
804 "set Augeas path to value",
806 Set the value associated with C<path> to C<value>.");
808 ("aug_insert", (RErr, [String "path"; String "label"; Bool "before"]), 21, [],
809 [], (* XXX Augeas code needs tests. *)
810 "insert a sibling Augeas node",
812 Create a new sibling C<label> for C<path>, inserting it into
813 the tree before or after C<path> (depending on the boolean
816 C<path> must match exactly one existing node in the tree, and
817 C<label> must be a label, ie. not contain C</>, C<*> or end
818 with a bracketed index C<[N]>.");
820 ("aug_rm", (RInt "nrnodes", [String "path"]), 22, [],
821 [], (* XXX Augeas code needs tests. *)
822 "remove an Augeas path",
824 Remove C<path> and all of its children.
826 On success this returns the number of entries which were removed.");
828 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
829 [], (* XXX Augeas code needs tests. *)
832 Move the node C<src> to C<dest>. C<src> must match exactly
833 one node. C<dest> is overwritten if it exists.");
835 ("aug_match", (RStringList "matches", [String "path"]), 24, [],
836 [], (* XXX Augeas code needs tests. *)
837 "return Augeas nodes which match path",
839 Returns a list of paths which match the path expression C<path>.
840 The returned paths are sufficiently qualified so that they match
841 exactly one node in the current tree.");
843 ("aug_save", (RErr, []), 25, [],
844 [], (* XXX Augeas code needs tests. *)
845 "write all pending Augeas changes to disk",
847 This writes all pending changes to disk.
849 The flags which were passed to C<guestfs_aug_init> affect exactly
850 how files are saved.");
852 ("aug_load", (RErr, []), 27, [],
853 [], (* XXX Augeas code needs tests. *)
854 "load files into the tree",
856 Load files into the tree.
858 See C<aug_load> in the Augeas documentation for the full gory
861 ("aug_ls", (RStringList "matches", [String "path"]), 28, [],
862 [], (* XXX Augeas code needs tests. *)
863 "list Augeas nodes under a path",
865 This is just a shortcut for listing C<guestfs_aug_match>
866 C<path/*> and sorting the resulting nodes into alphabetical order.");
868 ("rm", (RErr, [String "path"]), 29, [],
869 [InitBasicFS, Always, TestRun
872 InitBasicFS, Always, TestLastFail
874 InitBasicFS, Always, TestLastFail
879 Remove the single file C<path>.");
881 ("rmdir", (RErr, [String "path"]), 30, [],
882 [InitBasicFS, Always, TestRun
885 InitBasicFS, Always, TestLastFail
887 InitBasicFS, Always, TestLastFail
890 "remove a directory",
892 Remove the single directory C<path>.");
894 ("rm_rf", (RErr, [String "path"]), 31, [],
895 [InitBasicFS, Always, TestOutputFalse
897 ["mkdir"; "/new/foo"];
898 ["touch"; "/new/foo/bar"];
900 ["exists"; "/new"]]],
901 "remove a file or directory recursively",
903 Remove the file or directory C<path>, recursively removing the
904 contents if its a directory. This is like the C<rm -rf> shell
907 ("mkdir", (RErr, [String "path"]), 32, [],
908 [InitBasicFS, Always, TestOutputTrue
911 InitBasicFS, Always, TestLastFail
912 [["mkdir"; "/new/foo/bar"]]],
913 "create a directory",
915 Create a directory named C<path>.");
917 ("mkdir_p", (RErr, [String "path"]), 33, [],
918 [InitBasicFS, Always, TestOutputTrue
919 [["mkdir_p"; "/new/foo/bar"];
920 ["is_dir"; "/new/foo/bar"]];
921 InitBasicFS, Always, TestOutputTrue
922 [["mkdir_p"; "/new/foo/bar"];
923 ["is_dir"; "/new/foo"]];
924 InitBasicFS, Always, TestOutputTrue
925 [["mkdir_p"; "/new/foo/bar"];
926 ["is_dir"; "/new"]]],
927 "create a directory and parents",
929 Create a directory named C<path>, creating any parent directories
930 as necessary. This is like the C<mkdir -p> shell command.");
932 ("chmod", (RErr, [Int "mode"; String "path"]), 34, [],
933 [], (* XXX Need stat command to test *)
936 Change the mode (permissions) of C<path> to C<mode>. Only
937 numeric modes are supported.");
939 ("chown", (RErr, [Int "owner"; Int "group"; String "path"]), 35, [],
940 [], (* XXX Need stat command to test *)
941 "change file owner and group",
943 Change the file owner to C<owner> and group to C<group>.
945 Only numeric uid and gid are supported. If you want to use
946 names, you will need to locate and parse the password file
947 yourself (Augeas support makes this relatively easy).");
949 ("exists", (RBool "existsflag", [String "path"]), 36, [],
950 [InitBasicFS, Always, TestOutputTrue (
952 ["exists"; "/new"]]);
953 InitBasicFS, Always, TestOutputTrue (
955 ["exists"; "/new"]])],
956 "test if file or directory exists",
958 This returns C<true> if and only if there is a file, directory
959 (or anything) with the given C<path> name.
961 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
963 ("is_file", (RBool "fileflag", [String "path"]), 37, [],
964 [InitBasicFS, Always, TestOutputTrue (
966 ["is_file"; "/new"]]);
967 InitBasicFS, Always, TestOutputFalse (
969 ["is_file"; "/new"]])],
970 "test if file exists",
972 This returns C<true> if and only if there is a file
973 with the given C<path> name. Note that it returns false for
974 other objects like directories.
976 See also C<guestfs_stat>.");
978 ("is_dir", (RBool "dirflag", [String "path"]), 38, [],
979 [InitBasicFS, Always, TestOutputFalse (
981 ["is_dir"; "/new"]]);
982 InitBasicFS, Always, TestOutputTrue (
984 ["is_dir"; "/new"]])],
985 "test if file exists",
987 This returns C<true> if and only if there is a directory
988 with the given C<path> name. Note that it returns false for
989 other objects like files.
991 See also C<guestfs_stat>.");
993 ("pvcreate", (RErr, [String "device"]), 39, [],
994 [InitEmpty, Always, TestOutputList (
995 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
996 ["pvcreate"; "/dev/sda1"];
997 ["pvcreate"; "/dev/sda2"];
998 ["pvcreate"; "/dev/sda3"];
999 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1000 "create an LVM physical volume",
1002 This creates an LVM physical volume on the named C<device>,
1003 where C<device> should usually be a partition name such
1006 ("vgcreate", (RErr, [String "volgroup"; StringList "physvols"]), 40, [],
1007 [InitEmpty, Always, TestOutputList (
1008 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
1009 ["pvcreate"; "/dev/sda1"];
1010 ["pvcreate"; "/dev/sda2"];
1011 ["pvcreate"; "/dev/sda3"];
1012 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1013 ["vgcreate"; "VG2"; "/dev/sda3"];
1014 ["vgs"]], ["VG1"; "VG2"])],
1015 "create an LVM volume group",
1017 This creates an LVM volume group called C<volgroup>
1018 from the non-empty list of physical volumes C<physvols>.");
1020 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1021 [InitEmpty, Always, TestOutputList (
1022 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
1023 ["pvcreate"; "/dev/sda1"];
1024 ["pvcreate"; "/dev/sda2"];
1025 ["pvcreate"; "/dev/sda3"];
1026 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1027 ["vgcreate"; "VG2"; "/dev/sda3"];
1028 ["lvcreate"; "LV1"; "VG1"; "50"];
1029 ["lvcreate"; "LV2"; "VG1"; "50"];
1030 ["lvcreate"; "LV3"; "VG2"; "50"];
1031 ["lvcreate"; "LV4"; "VG2"; "50"];
1032 ["lvcreate"; "LV5"; "VG2"; "50"];
1034 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1035 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1036 "create an LVM volume group",
1038 This creates an LVM volume group called C<logvol>
1039 on the volume group C<volgroup>, with C<size> megabytes.");
1041 ("mkfs", (RErr, [String "fstype"; String "device"]), 42, [],
1042 [InitEmpty, Always, TestOutput (
1043 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1044 ["mkfs"; "ext2"; "/dev/sda1"];
1045 ["mount"; "/dev/sda1"; "/"];
1046 ["write_file"; "/new"; "new file contents"; "0"];
1047 ["cat"; "/new"]], "new file contents")],
1048 "make a filesystem",
1050 This creates a filesystem on C<device> (usually a partition
1051 or LVM logical volume). The filesystem type is C<fstype>, for
1054 ("sfdisk", (RErr, [String "device";
1055 Int "cyls"; Int "heads"; Int "sectors";
1056 StringList "lines"]), 43, [DangerWillRobinson],
1058 "create partitions on a block device",
1060 This is a direct interface to the L<sfdisk(8)> program for creating
1061 partitions on block devices.
1063 C<device> should be a block device, for example C</dev/sda>.
1065 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1066 and sectors on the device, which are passed directly to sfdisk as
1067 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1068 of these, then the corresponding parameter is omitted. Usually for
1069 'large' disks, you can just pass C<0> for these, but for small
1070 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1071 out the right geometry and you will need to tell it.
1073 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1074 information refer to the L<sfdisk(8)> manpage.
1076 To create a single partition occupying the whole disk, you would
1077 pass C<lines> as a single element list, when the single element being
1078 the string C<,> (comma).
1080 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1082 ("write_file", (RErr, [String "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1083 [InitBasicFS, Always, TestOutput (
1084 [["write_file"; "/new"; "new file contents"; "0"];
1085 ["cat"; "/new"]], "new file contents");
1086 InitBasicFS, Always, TestOutput (
1087 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1088 ["cat"; "/new"]], "\nnew file contents\n");
1089 InitBasicFS, Always, TestOutput (
1090 [["write_file"; "/new"; "\n\n"; "0"];
1091 ["cat"; "/new"]], "\n\n");
1092 InitBasicFS, Always, TestOutput (
1093 [["write_file"; "/new"; ""; "0"];
1094 ["cat"; "/new"]], "");
1095 InitBasicFS, Always, TestOutput (
1096 [["write_file"; "/new"; "\n\n\n"; "0"];
1097 ["cat"; "/new"]], "\n\n\n");
1098 InitBasicFS, Always, TestOutput (
1099 [["write_file"; "/new"; "\n"; "0"];
1100 ["cat"; "/new"]], "\n")],
1103 This call creates a file called C<path>. The contents of the
1104 file is the string C<content> (which can contain any 8 bit data),
1105 with length C<size>.
1107 As a special case, if C<size> is C<0>
1108 then the length is calculated using C<strlen> (so in this case
1109 the content cannot contain embedded ASCII NULs).
1111 I<NB.> Owing to a bug, writing content containing ASCII NUL
1112 characters does I<not> work, even if the length is specified.
1113 We hope to resolve this bug in a future version. In the meantime
1114 use C<guestfs_upload>.");
1116 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1117 [InitEmpty, Always, TestOutputList (
1118 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1119 ["mkfs"; "ext2"; "/dev/sda1"];
1120 ["mount"; "/dev/sda1"; "/"];
1121 ["mounts"]], ["/dev/sda1"]);
1122 InitEmpty, Always, TestOutputList (
1123 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1124 ["mkfs"; "ext2"; "/dev/sda1"];
1125 ["mount"; "/dev/sda1"; "/"];
1128 "unmount a filesystem",
1130 This unmounts the given filesystem. The filesystem may be
1131 specified either by its mountpoint (path) or the device which
1132 contains the filesystem.");
1134 ("mounts", (RStringList "devices", []), 46, [],
1135 [InitBasicFS, Always, TestOutputList (
1136 [["mounts"]], ["/dev/sda1"])],
1137 "show mounted filesystems",
1139 This returns the list of currently mounted filesystems. It returns
1140 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1142 Some internal mounts are not shown.");
1144 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1145 [InitBasicFS, Always, TestOutputList (
1148 (* check that umount_all can unmount nested mounts correctly: *)
1149 InitEmpty, Always, TestOutputList (
1150 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
1151 ["mkfs"; "ext2"; "/dev/sda1"];
1152 ["mkfs"; "ext2"; "/dev/sda2"];
1153 ["mkfs"; "ext2"; "/dev/sda3"];
1154 ["mount"; "/dev/sda1"; "/"];
1156 ["mount"; "/dev/sda2"; "/mp1"];
1157 ["mkdir"; "/mp1/mp2"];
1158 ["mount"; "/dev/sda3"; "/mp1/mp2"];
1159 ["mkdir"; "/mp1/mp2/mp3"];
1162 "unmount all filesystems",
1164 This unmounts all mounted filesystems.
1166 Some internal mounts are not unmounted by this call.");
1168 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1170 "remove all LVM LVs, VGs and PVs",
1172 This command removes all LVM logical volumes, volume groups
1173 and physical volumes.");
1175 ("file", (RString "description", [String "path"]), 49, [],
1176 [InitBasicFS, Always, TestOutput (
1178 ["file"; "/new"]], "empty");
1179 InitBasicFS, Always, TestOutput (
1180 [["write_file"; "/new"; "some content\n"; "0"];
1181 ["file"; "/new"]], "ASCII text");
1182 InitBasicFS, Always, TestLastFail (
1183 [["file"; "/nofile"]])],
1184 "determine file type",
1186 This call uses the standard L<file(1)> command to determine
1187 the type or contents of the file. This also works on devices,
1188 for example to find out whether a partition contains a filesystem.
1190 The exact command which runs is C<file -bsL path>. Note in
1191 particular that the filename is not prepended to the output
1192 (the C<-b> option).");
1194 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1195 [InitBasicFS, Always, TestOutput (
1196 [["upload"; "test-command"; "/test-command"];
1197 ["chmod"; "493"; "/test-command"];
1198 ["command"; "/test-command 1"]], "Result1");
1199 InitBasicFS, Always, TestOutput (
1200 [["upload"; "test-command"; "/test-command"];
1201 ["chmod"; "493"; "/test-command"];
1202 ["command"; "/test-command 2"]], "Result2\n");
1203 InitBasicFS, Always, TestOutput (
1204 [["upload"; "test-command"; "/test-command"];
1205 ["chmod"; "493"; "/test-command"];
1206 ["command"; "/test-command 3"]], "\nResult3");
1207 InitBasicFS, Always, TestOutput (
1208 [["upload"; "test-command"; "/test-command"];
1209 ["chmod"; "493"; "/test-command"];
1210 ["command"; "/test-command 4"]], "\nResult4\n");
1211 InitBasicFS, Always, TestOutput (
1212 [["upload"; "test-command"; "/test-command"];
1213 ["chmod"; "493"; "/test-command"];
1214 ["command"; "/test-command 5"]], "\nResult5\n\n");
1215 InitBasicFS, Always, TestOutput (
1216 [["upload"; "test-command"; "/test-command"];
1217 ["chmod"; "493"; "/test-command"];
1218 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1219 InitBasicFS, Always, TestOutput (
1220 [["upload"; "test-command"; "/test-command"];
1221 ["chmod"; "493"; "/test-command"];
1222 ["command"; "/test-command 7"]], "");
1223 InitBasicFS, Always, TestOutput (
1224 [["upload"; "test-command"; "/test-command"];
1225 ["chmod"; "493"; "/test-command"];
1226 ["command"; "/test-command 8"]], "\n");
1227 InitBasicFS, Always, TestOutput (
1228 [["upload"; "test-command"; "/test-command"];
1229 ["chmod"; "493"; "/test-command"];
1230 ["command"; "/test-command 9"]], "\n\n");
1231 InitBasicFS, Always, TestOutput (
1232 [["upload"; "test-command"; "/test-command"];
1233 ["chmod"; "493"; "/test-command"];
1234 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1235 InitBasicFS, Always, TestOutput (
1236 [["upload"; "test-command"; "/test-command"];
1237 ["chmod"; "493"; "/test-command"];
1238 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1239 InitBasicFS, Always, TestLastFail (
1240 [["upload"; "test-command"; "/test-command"];
1241 ["chmod"; "493"; "/test-command"];
1242 ["command"; "/test-command"]])],
1243 "run a command from the guest filesystem",
1245 This call runs a command from the guest filesystem. The
1246 filesystem must be mounted, and must contain a compatible
1247 operating system (ie. something Linux, with the same
1248 or compatible processor architecture).
1250 The single parameter is an argv-style list of arguments.
1251 The first element is the name of the program to run.
1252 Subsequent elements are parameters. The list must be
1253 non-empty (ie. must contain a program name).
1255 The return value is anything printed to I<stdout> by
1258 If the command returns a non-zero exit status, then
1259 this function returns an error message. The error message
1260 string is the content of I<stderr> from the command.
1262 The C<$PATH> environment variable will contain at least
1263 C</usr/bin> and C</bin>. If you require a program from
1264 another location, you should provide the full path in the
1267 Shared libraries and data files required by the program
1268 must be available on filesystems which are mounted in the
1269 correct places. It is the caller's responsibility to ensure
1270 all filesystems that are needed are mounted at the right
1273 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1274 [InitBasicFS, Always, TestOutputList (
1275 [["upload"; "test-command"; "/test-command"];
1276 ["chmod"; "493"; "/test-command"];
1277 ["command_lines"; "/test-command 1"]], ["Result1"]);
1278 InitBasicFS, Always, TestOutputList (
1279 [["upload"; "test-command"; "/test-command"];
1280 ["chmod"; "493"; "/test-command"];
1281 ["command_lines"; "/test-command 2"]], ["Result2"]);
1282 InitBasicFS, Always, TestOutputList (
1283 [["upload"; "test-command"; "/test-command"];
1284 ["chmod"; "493"; "/test-command"];
1285 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1286 InitBasicFS, Always, TestOutputList (
1287 [["upload"; "test-command"; "/test-command"];
1288 ["chmod"; "493"; "/test-command"];
1289 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1290 InitBasicFS, Always, TestOutputList (
1291 [["upload"; "test-command"; "/test-command"];
1292 ["chmod"; "493"; "/test-command"];
1293 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1294 InitBasicFS, Always, TestOutputList (
1295 [["upload"; "test-command"; "/test-command"];
1296 ["chmod"; "493"; "/test-command"];
1297 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1298 InitBasicFS, Always, TestOutputList (
1299 [["upload"; "test-command"; "/test-command"];
1300 ["chmod"; "493"; "/test-command"];
1301 ["command_lines"; "/test-command 7"]], []);
1302 InitBasicFS, Always, TestOutputList (
1303 [["upload"; "test-command"; "/test-command"];
1304 ["chmod"; "493"; "/test-command"];
1305 ["command_lines"; "/test-command 8"]], [""]);
1306 InitBasicFS, Always, TestOutputList (
1307 [["upload"; "test-command"; "/test-command"];
1308 ["chmod"; "493"; "/test-command"];
1309 ["command_lines"; "/test-command 9"]], ["";""]);
1310 InitBasicFS, Always, TestOutputList (
1311 [["upload"; "test-command"; "/test-command"];
1312 ["chmod"; "493"; "/test-command"];
1313 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1314 InitBasicFS, Always, TestOutputList (
1315 [["upload"; "test-command"; "/test-command"];
1316 ["chmod"; "493"; "/test-command"];
1317 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1318 "run a command, returning lines",
1320 This is the same as C<guestfs_command>, but splits the
1321 result into a list of lines.");
1323 ("stat", (RStat "statbuf", [String "path"]), 52, [],
1324 [InitBasicFS, Always, TestOutputStruct (
1326 ["stat"; "/new"]], [CompareWithInt ("size", 0)])],
1327 "get file information",
1329 Returns file information for the given C<path>.
1331 This is the same as the C<stat(2)> system call.");
1333 ("lstat", (RStat "statbuf", [String "path"]), 53, [],
1334 [InitBasicFS, Always, TestOutputStruct (
1336 ["lstat"; "/new"]], [CompareWithInt ("size", 0)])],
1337 "get file information for a symbolic link",
1339 Returns file information for the given C<path>.
1341 This is the same as C<guestfs_stat> except that if C<path>
1342 is a symbolic link, then the link is stat-ed, not the file it
1345 This is the same as the C<lstat(2)> system call.");
1347 ("statvfs", (RStatVFS "statbuf", [String "path"]), 54, [],
1348 [InitBasicFS, Always, TestOutputStruct (
1349 [["statvfs"; "/"]], [CompareWithInt ("bfree", 487702);
1350 CompareWithInt ("blocks", 490020);
1351 CompareWithInt ("bsize", 1024)])],
1352 "get file system statistics",
1354 Returns file system statistics for any mounted file system.
1355 C<path> should be a file or directory in the mounted file system
1356 (typically it is the mount point itself, but it doesn't need to be).
1358 This is the same as the C<statvfs(2)> system call.");
1360 ("tune2fs_l", (RHashtable "superblock", [String "device"]), 55, [],
1362 "get ext2/ext3/ext4 superblock details",
1364 This returns the contents of the ext2, ext3 or ext4 filesystem
1365 superblock on C<device>.
1367 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1368 manpage for more details. The list of fields returned isn't
1369 clearly defined, and depends on both the version of C<tune2fs>
1370 that libguestfs was built against, and the filesystem itself.");
1372 ("blockdev_setro", (RErr, [String "device"]), 56, [],
1373 [InitEmpty, Always, TestOutputTrue (
1374 [["blockdev_setro"; "/dev/sda"];
1375 ["blockdev_getro"; "/dev/sda"]])],
1376 "set block device to read-only",
1378 Sets the block device named C<device> to read-only.
1380 This uses the L<blockdev(8)> command.");
1382 ("blockdev_setrw", (RErr, [String "device"]), 57, [],
1383 [InitEmpty, Always, TestOutputFalse (
1384 [["blockdev_setrw"; "/dev/sda"];
1385 ["blockdev_getro"; "/dev/sda"]])],
1386 "set block device to read-write",
1388 Sets the block device named C<device> to read-write.
1390 This uses the L<blockdev(8)> command.");
1392 ("blockdev_getro", (RBool "ro", [String "device"]), 58, [],
1393 [InitEmpty, Always, TestOutputTrue (
1394 [["blockdev_setro"; "/dev/sda"];
1395 ["blockdev_getro"; "/dev/sda"]])],
1396 "is block device set to read-only",
1398 Returns a boolean indicating if the block device is read-only
1399 (true if read-only, false if not).
1401 This uses the L<blockdev(8)> command.");
1403 ("blockdev_getss", (RInt "sectorsize", [String "device"]), 59, [],
1404 [InitEmpty, Always, TestOutputInt (
1405 [["blockdev_getss"; "/dev/sda"]], 512)],
1406 "get sectorsize of block device",
1408 This returns the size of sectors on a block device.
1409 Usually 512, but can be larger for modern devices.
1411 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1414 This uses the L<blockdev(8)> command.");
1416 ("blockdev_getbsz", (RInt "blocksize", [String "device"]), 60, [],
1417 [InitEmpty, Always, TestOutputInt (
1418 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1419 "get blocksize of block device",
1421 This returns the block size of a device.
1423 (Note this is different from both I<size in blocks> and
1424 I<filesystem block size>).
1426 This uses the L<blockdev(8)> command.");
1428 ("blockdev_setbsz", (RErr, [String "device"; Int "blocksize"]), 61, [],
1430 "set blocksize of block device",
1432 This sets the block size of a device.
1434 (Note this is different from both I<size in blocks> and
1435 I<filesystem block size>).
1437 This uses the L<blockdev(8)> command.");
1439 ("blockdev_getsz", (RInt64 "sizeinsectors", [String "device"]), 62, [],
1440 [InitEmpty, Always, TestOutputInt (
1441 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1442 "get total size of device in 512-byte sectors",
1444 This returns the size of the device in units of 512-byte sectors
1445 (even if the sectorsize isn't 512 bytes ... weird).
1447 See also C<guestfs_blockdev_getss> for the real sector size of
1448 the device, and C<guestfs_blockdev_getsize64> for the more
1449 useful I<size in bytes>.
1451 This uses the L<blockdev(8)> command.");
1453 ("blockdev_getsize64", (RInt64 "sizeinbytes", [String "device"]), 63, [],
1454 [InitEmpty, Always, TestOutputInt (
1455 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1456 "get total size of device in bytes",
1458 This returns the size of the device in bytes.
1460 See also C<guestfs_blockdev_getsz>.
1462 This uses the L<blockdev(8)> command.");
1464 ("blockdev_flushbufs", (RErr, [String "device"]), 64, [],
1465 [InitEmpty, Always, TestRun
1466 [["blockdev_flushbufs"; "/dev/sda"]]],
1467 "flush device buffers",
1469 This tells the kernel to flush internal buffers associated
1472 This uses the L<blockdev(8)> command.");
1474 ("blockdev_rereadpt", (RErr, [String "device"]), 65, [],
1475 [InitEmpty, Always, TestRun
1476 [["blockdev_rereadpt"; "/dev/sda"]]],
1477 "reread partition table",
1479 Reread the partition table on C<device>.
1481 This uses the L<blockdev(8)> command.");
1483 ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1484 [InitBasicFS, Always, TestOutput (
1485 (* Pick a file from cwd which isn't likely to change. *)
1486 [["upload"; "COPYING.LIB"; "/COPYING.LIB"];
1487 ["checksum"; "md5"; "/COPYING.LIB"]], "e3eda01d9815f8d24aae2dbd89b68b06")],
1488 "upload a file from the local machine",
1490 Upload local file C<filename> to C<remotefilename> on the
1493 C<filename> can also be a named pipe.
1495 See also C<guestfs_download>.");
1497 ("download", (RErr, [String "remotefilename"; FileOut "filename"]), 67, [],
1498 [InitBasicFS, Always, TestOutput (
1499 (* Pick a file from cwd which isn't likely to change. *)
1500 [["upload"; "COPYING.LIB"; "/COPYING.LIB"];
1501 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1502 ["upload"; "testdownload.tmp"; "/upload"];
1503 ["checksum"; "md5"; "/upload"]], "e3eda01d9815f8d24aae2dbd89b68b06")],
1504 "download a file to the local machine",
1506 Download file C<remotefilename> and save it as C<filename>
1507 on the local machine.
1509 C<filename> can also be a named pipe.
1511 See also C<guestfs_upload>, C<guestfs_cat>.");
1513 ("checksum", (RString "checksum", [String "csumtype"; String "path"]), 68, [],
1514 [InitBasicFS, Always, TestOutput (
1515 [["write_file"; "/new"; "test\n"; "0"];
1516 ["checksum"; "crc"; "/new"]], "935282863");
1517 InitBasicFS, Always, TestLastFail (
1518 [["checksum"; "crc"; "/new"]]);
1519 InitBasicFS, Always, TestOutput (
1520 [["write_file"; "/new"; "test\n"; "0"];
1521 ["checksum"; "md5"; "/new"]], "d8e8fca2dc0f896fd7cb4cb0031ba249");
1522 InitBasicFS, Always, TestOutput (
1523 [["write_file"; "/new"; "test\n"; "0"];
1524 ["checksum"; "sha1"; "/new"]], "4e1243bd22c66e76c2ba9eddc1f91394e57f9f83");
1525 InitBasicFS, Always, TestOutput (
1526 [["write_file"; "/new"; "test\n"; "0"];
1527 ["checksum"; "sha224"; "/new"]], "52f1bf093f4b7588726035c176c0cdb4376cfea53819f1395ac9e6ec");
1528 InitBasicFS, Always, TestOutput (
1529 [["write_file"; "/new"; "test\n"; "0"];
1530 ["checksum"; "sha256"; "/new"]], "f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2");
1531 InitBasicFS, Always, TestOutput (
1532 [["write_file"; "/new"; "test\n"; "0"];
1533 ["checksum"; "sha384"; "/new"]], "109bb6b5b6d5547c1ce03c7a8bd7d8f80c1cb0957f50c4f7fda04692079917e4f9cad52b878f3d8234e1a170b154b72d");
1534 InitBasicFS, Always, TestOutput (
1535 [["write_file"; "/new"; "test\n"; "0"];
1536 ["checksum"; "sha512"; "/new"]], "0e3e75234abc68f4378a86b3f4b32a198ba301845b0cd6e50106e874345700cc6663a86c1ea125dc5e92be17c98f9a0f85ca9d5f595db2012f7cc3571945c123")],
1537 "compute MD5, SHAx or CRC checksum of file",
1539 This call computes the MD5, SHAx or CRC checksum of the
1542 The type of checksum to compute is given by the C<csumtype>
1543 parameter which must have one of the following values:
1549 Compute the cyclic redundancy check (CRC) specified by POSIX
1550 for the C<cksum> command.
1554 Compute the MD5 hash (using the C<md5sum> program).
1558 Compute the SHA1 hash (using the C<sha1sum> program).
1562 Compute the SHA224 hash (using the C<sha224sum> program).
1566 Compute the SHA256 hash (using the C<sha256sum> program).
1570 Compute the SHA384 hash (using the C<sha384sum> program).
1574 Compute the SHA512 hash (using the C<sha512sum> program).
1578 The checksum is returned as a printable string.");
1580 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1581 [InitBasicFS, Always, TestOutput (
1582 [["tar_in"; "images/helloworld.tar"; "/"];
1583 ["cat"; "/hello"]], "hello\n")],
1584 "unpack tarfile to directory",
1586 This command uploads and unpacks local file C<tarfile> (an
1587 I<uncompressed> tar file) into C<directory>.
1589 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1591 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1593 "pack directory into tarfile",
1595 This command packs the contents of C<directory> and downloads
1596 it to local file C<tarfile>.
1598 To download a compressed tarball, use C<guestfs_tgz_out>.");
1600 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1601 [InitBasicFS, Always, TestOutput (
1602 [["tgz_in"; "images/helloworld.tar.gz"; "/"];
1603 ["cat"; "/hello"]], "hello\n")],
1604 "unpack compressed tarball to directory",
1606 This command uploads and unpacks local file C<tarball> (a
1607 I<gzip compressed> tar file) into C<directory>.
1609 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1611 ("tgz_out", (RErr, [String "directory"; FileOut "tarball"]), 72, [],
1613 "pack directory into compressed tarball",
1615 This command packs the contents of C<directory> and downloads
1616 it to local file C<tarball>.
1618 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1620 ("mount_ro", (RErr, [String "device"; String "mountpoint"]), 73, [],
1621 [InitBasicFS, Always, TestLastFail (
1623 ["mount_ro"; "/dev/sda1"; "/"];
1624 ["touch"; "/new"]]);
1625 InitBasicFS, Always, TestOutput (
1626 [["write_file"; "/new"; "data"; "0"];
1628 ["mount_ro"; "/dev/sda1"; "/"];
1629 ["cat"; "/new"]], "data")],
1630 "mount a guest disk, read-only",
1632 This is the same as the C<guestfs_mount> command, but it
1633 mounts the filesystem with the read-only (I<-o ro>) flag.");
1635 ("mount_options", (RErr, [String "options"; String "device"; String "mountpoint"]), 74, [],
1637 "mount a guest disk with mount options",
1639 This is the same as the C<guestfs_mount> command, but it
1640 allows you to set the mount options as for the
1641 L<mount(8)> I<-o> flag.");
1643 ("mount_vfs", (RErr, [String "options"; String "vfstype"; String "device"; String "mountpoint"]), 75, [],
1645 "mount a guest disk with mount options and vfstype",
1647 This is the same as the C<guestfs_mount> command, but it
1648 allows you to set both the mount options and the vfstype
1649 as for the L<mount(8)> I<-o> and I<-t> flags.");
1651 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1653 "debugging and internals",
1655 The C<guestfs_debug> command exposes some internals of
1656 C<guestfsd> (the guestfs daemon) that runs inside the
1659 There is no comprehensive help for this command. You have
1660 to look at the file C<daemon/debug.c> in the libguestfs source
1661 to find out what you can do.");
1663 ("lvremove", (RErr, [String "device"]), 77, [],
1664 [InitEmpty, Always, TestOutputList (
1665 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1666 ["pvcreate"; "/dev/sda1"];
1667 ["vgcreate"; "VG"; "/dev/sda1"];
1668 ["lvcreate"; "LV1"; "VG"; "50"];
1669 ["lvcreate"; "LV2"; "VG"; "50"];
1670 ["lvremove"; "/dev/VG/LV1"];
1671 ["lvs"]], ["/dev/VG/LV2"]);
1672 InitEmpty, Always, TestOutputList (
1673 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1674 ["pvcreate"; "/dev/sda1"];
1675 ["vgcreate"; "VG"; "/dev/sda1"];
1676 ["lvcreate"; "LV1"; "VG"; "50"];
1677 ["lvcreate"; "LV2"; "VG"; "50"];
1678 ["lvremove"; "/dev/VG"];
1680 InitEmpty, Always, TestOutputList (
1681 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1682 ["pvcreate"; "/dev/sda1"];
1683 ["vgcreate"; "VG"; "/dev/sda1"];
1684 ["lvcreate"; "LV1"; "VG"; "50"];
1685 ["lvcreate"; "LV2"; "VG"; "50"];
1686 ["lvremove"; "/dev/VG"];
1688 "remove an LVM logical volume",
1690 Remove an LVM logical volume C<device>, where C<device> is
1691 the path to the LV, such as C</dev/VG/LV>.
1693 You can also remove all LVs in a volume group by specifying
1694 the VG name, C</dev/VG>.");
1696 ("vgremove", (RErr, [String "vgname"]), 78, [],
1697 [InitEmpty, Always, TestOutputList (
1698 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1699 ["pvcreate"; "/dev/sda1"];
1700 ["vgcreate"; "VG"; "/dev/sda1"];
1701 ["lvcreate"; "LV1"; "VG"; "50"];
1702 ["lvcreate"; "LV2"; "VG"; "50"];
1705 InitEmpty, Always, TestOutputList (
1706 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1707 ["pvcreate"; "/dev/sda1"];
1708 ["vgcreate"; "VG"; "/dev/sda1"];
1709 ["lvcreate"; "LV1"; "VG"; "50"];
1710 ["lvcreate"; "LV2"; "VG"; "50"];
1713 "remove an LVM volume group",
1715 Remove an LVM volume group C<vgname>, (for example C<VG>).
1717 This also forcibly removes all logical volumes in the volume
1720 ("pvremove", (RErr, [String "device"]), 79, [],
1721 [InitEmpty, Always, TestOutputList (
1722 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1723 ["pvcreate"; "/dev/sda1"];
1724 ["vgcreate"; "VG"; "/dev/sda1"];
1725 ["lvcreate"; "LV1"; "VG"; "50"];
1726 ["lvcreate"; "LV2"; "VG"; "50"];
1728 ["pvremove"; "/dev/sda1"];
1730 InitEmpty, Always, TestOutputList (
1731 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1732 ["pvcreate"; "/dev/sda1"];
1733 ["vgcreate"; "VG"; "/dev/sda1"];
1734 ["lvcreate"; "LV1"; "VG"; "50"];
1735 ["lvcreate"; "LV2"; "VG"; "50"];
1737 ["pvremove"; "/dev/sda1"];
1739 InitEmpty, Always, TestOutputList (
1740 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1741 ["pvcreate"; "/dev/sda1"];
1742 ["vgcreate"; "VG"; "/dev/sda1"];
1743 ["lvcreate"; "LV1"; "VG"; "50"];
1744 ["lvcreate"; "LV2"; "VG"; "50"];
1746 ["pvremove"; "/dev/sda1"];
1748 "remove an LVM physical volume",
1750 This wipes a physical volume C<device> so that LVM will no longer
1753 The implementation uses the C<pvremove> command which refuses to
1754 wipe physical volumes that contain any volume groups, so you have
1755 to remove those first.");
1757 ("set_e2label", (RErr, [String "device"; String "label"]), 80, [],
1758 [InitBasicFS, Always, TestOutput (
1759 [["set_e2label"; "/dev/sda1"; "testlabel"];
1760 ["get_e2label"; "/dev/sda1"]], "testlabel")],
1761 "set the ext2/3/4 filesystem label",
1763 This sets the ext2/3/4 filesystem label of the filesystem on
1764 C<device> to C<label>. Filesystem labels are limited to
1767 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
1768 to return the existing label on a filesystem.");
1770 ("get_e2label", (RString "label", [String "device"]), 81, [],
1772 "get the ext2/3/4 filesystem label",
1774 This returns the ext2/3/4 filesystem label of the filesystem on
1777 ("set_e2uuid", (RErr, [String "device"; String "uuid"]), 82, [],
1778 [InitBasicFS, Always, TestOutput (
1779 [["set_e2uuid"; "/dev/sda1"; "a3a61220-882b-4f61-89f4-cf24dcc7297d"];
1780 ["get_e2uuid"; "/dev/sda1"]], "a3a61220-882b-4f61-89f4-cf24dcc7297d");
1781 InitBasicFS, Always, TestOutput (
1782 [["set_e2uuid"; "/dev/sda1"; "clear"];
1783 ["get_e2uuid"; "/dev/sda1"]], "");
1784 (* We can't predict what UUIDs will be, so just check the commands run. *)
1785 InitBasicFS, Always, TestRun (
1786 [["set_e2uuid"; "/dev/sda1"; "random"]]);
1787 InitBasicFS, Always, TestRun (
1788 [["set_e2uuid"; "/dev/sda1"; "time"]])],
1789 "set the ext2/3/4 filesystem UUID",
1791 This sets the ext2/3/4 filesystem UUID of the filesystem on
1792 C<device> to C<uuid>. The format of the UUID and alternatives
1793 such as C<clear>, C<random> and C<time> are described in the
1794 L<tune2fs(8)> manpage.
1796 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
1797 to return the existing UUID of a filesystem.");
1799 ("get_e2uuid", (RString "uuid", [String "device"]), 83, [],
1801 "get the ext2/3/4 filesystem UUID",
1803 This returns the ext2/3/4 filesystem UUID of the filesystem on
1806 ("fsck", (RInt "status", [String "fstype"; String "device"]), 84, [],
1807 [InitBasicFS, Always, TestOutputInt (
1808 [["umount"; "/dev/sda1"];
1809 ["fsck"; "ext2"; "/dev/sda1"]], 0);
1810 InitBasicFS, Always, TestOutputInt (
1811 [["umount"; "/dev/sda1"];
1812 ["zero"; "/dev/sda1"];
1813 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
1814 "run the filesystem checker",
1816 This runs the filesystem checker (fsck) on C<device> which
1817 should have filesystem type C<fstype>.
1819 The returned integer is the status. See L<fsck(8)> for the
1820 list of status codes from C<fsck>.
1828 Multiple status codes can be summed together.
1832 A non-zero return code can mean \"success\", for example if
1833 errors have been corrected on the filesystem.
1837 Checking or repairing NTFS volumes is not supported
1842 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
1844 ("zero", (RErr, [String "device"]), 85, [],
1845 [InitBasicFS, Always, TestOutput (
1846 [["umount"; "/dev/sda1"];
1847 ["zero"; "/dev/sda1"];
1848 ["file"; "/dev/sda1"]], "data")],
1849 "write zeroes to the device",
1851 This command writes zeroes over the first few blocks of C<device>.
1853 How many blocks are zeroed isn't specified (but it's I<not> enough
1854 to securely wipe the device). It should be sufficient to remove
1855 any partition tables, filesystem superblocks and so on.");
1857 ("grub_install", (RErr, [String "root"; String "device"]), 86, [],
1858 [InitBasicFS, Always, TestOutputTrue (
1859 [["grub_install"; "/"; "/dev/sda1"];
1860 ["is_dir"; "/boot"]])],
1863 This command installs GRUB (the Grand Unified Bootloader) on
1864 C<device>, with the root directory being C<root>.");
1866 ("cp", (RErr, [String "src"; String "dest"]), 87, [],
1867 [InitBasicFS, Always, TestOutput (
1868 [["write_file"; "/old"; "file content"; "0"];
1869 ["cp"; "/old"; "/new"];
1870 ["cat"; "/new"]], "file content");
1871 InitBasicFS, Always, TestOutputTrue (
1872 [["write_file"; "/old"; "file content"; "0"];
1873 ["cp"; "/old"; "/new"];
1874 ["is_file"; "/old"]]);
1875 InitBasicFS, Always, TestOutput (
1876 [["write_file"; "/old"; "file content"; "0"];
1878 ["cp"; "/old"; "/dir/new"];
1879 ["cat"; "/dir/new"]], "file content")],
1882 This copies a file from C<src> to C<dest> where C<dest> is
1883 either a destination filename or destination directory.");
1885 ("cp_a", (RErr, [String "src"; String "dest"]), 88, [],
1886 [InitBasicFS, Always, TestOutput (
1887 [["mkdir"; "/olddir"];
1888 ["mkdir"; "/newdir"];
1889 ["write_file"; "/olddir/file"; "file content"; "0"];
1890 ["cp_a"; "/olddir"; "/newdir"];
1891 ["cat"; "/newdir/olddir/file"]], "file content")],
1892 "copy a file or directory recursively",
1894 This copies a file or directory from C<src> to C<dest>
1895 recursively using the C<cp -a> command.");
1897 ("mv", (RErr, [String "src"; String "dest"]), 89, [],
1898 [InitBasicFS, Always, TestOutput (
1899 [["write_file"; "/old"; "file content"; "0"];
1900 ["mv"; "/old"; "/new"];
1901 ["cat"; "/new"]], "file content");
1902 InitBasicFS, Always, TestOutputFalse (
1903 [["write_file"; "/old"; "file content"; "0"];
1904 ["mv"; "/old"; "/new"];
1905 ["is_file"; "/old"]])],
1908 This moves a file from C<src> to C<dest> where C<dest> is
1909 either a destination filename or destination directory.");
1911 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
1912 [InitEmpty, Always, TestRun (
1913 [["drop_caches"; "3"]])],
1914 "drop kernel page cache, dentries and inodes",
1916 This instructs the guest kernel to drop its page cache,
1917 and/or dentries and inode caches. The parameter C<whattodrop>
1918 tells the kernel what precisely to drop, see
1919 L<http://linux-mm.org/Drop_Caches>
1921 Setting C<whattodrop> to 3 should drop everything.
1923 This automatically calls L<sync(2)> before the operation,
1924 so that the maximum guest memory is freed.");
1926 ("dmesg", (RString "kmsgs", []), 91, [],
1927 [InitEmpty, Always, TestRun (
1929 "return kernel messages",
1931 This returns the kernel messages (C<dmesg> output) from
1932 the guest kernel. This is sometimes useful for extended
1933 debugging of problems.
1935 Another way to get the same information is to enable
1936 verbose messages with C<guestfs_set_verbose> or by setting
1937 the environment variable C<LIBGUESTFS_DEBUG=1> before
1938 running the program.");
1940 ("ping_daemon", (RErr, []), 92, [],
1941 [InitEmpty, Always, TestRun (
1942 [["ping_daemon"]])],
1943 "ping the guest daemon",
1945 This is a test probe into the guestfs daemon running inside
1946 the qemu subprocess. Calling this function checks that the
1947 daemon responds to the ping message, without affecting the daemon
1948 or attached block device(s) in any other way.");
1950 ("equal", (RBool "equality", [String "file1"; String "file2"]), 93, [],
1951 [InitBasicFS, Always, TestOutputTrue (
1952 [["write_file"; "/file1"; "contents of a file"; "0"];
1953 ["cp"; "/file1"; "/file2"];
1954 ["equal"; "/file1"; "/file2"]]);
1955 InitBasicFS, Always, TestOutputFalse (
1956 [["write_file"; "/file1"; "contents of a file"; "0"];
1957 ["write_file"; "/file2"; "contents of another file"; "0"];
1958 ["equal"; "/file1"; "/file2"]]);
1959 InitBasicFS, Always, TestLastFail (
1960 [["equal"; "/file1"; "/file2"]])],
1961 "test if two files have equal contents",
1963 This compares the two files C<file1> and C<file2> and returns
1964 true if their content is exactly equal, or false otherwise.
1966 The external L<cmp(1)> program is used for the comparison.");
1968 ("strings", (RStringList "stringsout", [String "path"]), 94, [ProtocolLimitWarning],
1969 [InitBasicFS, Always, TestOutputList (
1970 [["write_file"; "/new"; "hello\nworld\n"; "0"];
1971 ["strings"; "/new"]], ["hello"; "world"]);
1972 InitBasicFS, Always, TestOutputList (
1974 ["strings"; "/new"]], [])],
1975 "print the printable strings in a file",
1977 This runs the L<strings(1)> command on a file and returns
1978 the list of printable strings found.");
1980 ("strings_e", (RStringList "stringsout", [String "encoding"; String "path"]), 95, [ProtocolLimitWarning],
1981 [InitBasicFS, Always, TestOutputList (
1982 [["write_file"; "/new"; "hello\nworld\n"; "0"];
1983 ["strings_e"; "b"; "/new"]], []);
1984 InitBasicFS, Disabled, TestOutputList (
1985 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
1986 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
1987 "print the printable strings in a file",
1989 This is like the C<guestfs_strings> command, but allows you to
1990 specify the encoding.
1992 See the L<strings(1)> manpage for the full list of encodings.
1994 Commonly useful encodings are C<l> (lower case L) which will
1995 show strings inside Windows/x86 files.
1997 The returned strings are transcoded to UTF-8.");
1999 ("hexdump", (RString "dump", [String "path"]), 96, [ProtocolLimitWarning],
2000 [InitBasicFS, Always, TestOutput (
2001 [["write_file"; "/new"; "hello\nworld\n"; "12"];
2002 ["hexdump"; "/new"]], "00000000 68 65 6c 6c 6f 0a 77 6f 72 6c 64 0a |hello.world.|\n0000000c\n")],
2003 "dump a file in hexadecimal",
2005 This runs C<hexdump -C> on the given C<path>. The result is
2006 the human-readable, canonical hex dump of the file.");
2008 ("zerofree", (RErr, [String "device"]), 97, [],
2009 [InitNone, Always, TestOutput (
2010 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
2011 ["mkfs"; "ext3"; "/dev/sda1"];
2012 ["mount"; "/dev/sda1"; "/"];
2013 ["write_file"; "/new"; "test file"; "0"];
2014 ["umount"; "/dev/sda1"];
2015 ["zerofree"; "/dev/sda1"];
2016 ["mount"; "/dev/sda1"; "/"];
2017 ["cat"; "/new"]], "test file")],
2018 "zero unused inodes and disk blocks on ext2/3 filesystem",
2020 This runs the I<zerofree> program on C<device>. This program
2021 claims to zero unused inodes and disk blocks on an ext2/3
2022 filesystem, thus making it possible to compress the filesystem
2025 You should B<not> run this program if the filesystem is
2028 It is possible that using this program can damage the filesystem
2029 or data on the filesystem.");
2031 ("pvresize", (RErr, [String "device"]), 98, [],
2033 "resize an LVM physical volume",
2035 This resizes (expands or shrinks) an existing LVM physical
2036 volume to match the new size of the underlying device.");
2038 ("sfdisk_N", (RErr, [String "device"; Int "n";
2039 Int "cyls"; Int "heads"; Int "sectors";
2040 String "line"]), 99, [DangerWillRobinson],
2042 "modify a single partition on a block device",
2044 This runs L<sfdisk(8)> option to modify just the single
2045 partition C<n> (note: C<n> counts from 1).
2047 For other parameters, see C<guestfs_sfdisk>. You should usually
2048 pass C<0> for the cyls/heads/sectors parameters.");
2050 ("sfdisk_l", (RString "partitions", [String "device"]), 100, [],
2052 "display the partition table",
2054 This displays the partition table on C<device>, in the
2055 human-readable output of the L<sfdisk(8)> command. It is
2056 not intended to be parsed.");
2058 ("sfdisk_kernel_geometry", (RString "partitions", [String "device"]), 101, [],
2060 "display the kernel geometry",
2062 This displays the kernel's idea of the geometry of C<device>.
2064 The result is in human-readable format, and not designed to
2067 ("sfdisk_disk_geometry", (RString "partitions", [String "device"]), 102, [],
2069 "display the disk geometry from the partition table",
2071 This displays the disk geometry of C<device> read from the
2072 partition table. Especially in the case where the underlying
2073 block device has been resized, this can be different from the
2074 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2076 The result is in human-readable format, and not designed to
2079 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2081 "activate or deactivate all volume groups",
2083 This command activates or (if C<activate> is false) deactivates
2084 all logical volumes in all volume groups.
2085 If activated, then they are made known to the
2086 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2087 then those devices disappear.
2089 This command is the same as running C<vgchange -a y|n>");
2091 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2093 "activate or deactivate some volume groups",
2095 This command activates or (if C<activate> is false) deactivates
2096 all logical volumes in the listed volume groups C<volgroups>.
2097 If activated, then they are made known to the
2098 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2099 then those devices disappear.
2101 This command is the same as running C<vgchange -a y|n volgroups...>
2103 Note that if C<volgroups> is an empty list then B<all> volume groups
2104 are activated or deactivated.");
2106 ("lvresize", (RErr, [String "device"; Int "mbytes"]), 105, [],
2107 [InitNone, Always, TestOutput (
2108 [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
2109 ["pvcreate"; "/dev/sda1"];
2110 ["vgcreate"; "VG"; "/dev/sda1"];
2111 ["lvcreate"; "LV"; "VG"; "10"];
2112 ["mkfs"; "ext2"; "/dev/VG/LV"];
2113 ["mount"; "/dev/VG/LV"; "/"];
2114 ["write_file"; "/new"; "test content"; "0"];
2116 ["lvresize"; "/dev/VG/LV"; "20"];
2117 ["e2fsck_f"; "/dev/VG/LV"];
2118 ["resize2fs"; "/dev/VG/LV"];
2119 ["mount"; "/dev/VG/LV"; "/"];
2120 ["cat"; "/new"]], "test content")],
2121 "resize an LVM logical volume",
2123 This resizes (expands or shrinks) an existing LVM logical
2124 volume to C<mbytes>. When reducing, data in the reduced part
2127 ("resize2fs", (RErr, [String "device"]), 106, [],
2128 [], (* lvresize tests this *)
2129 "resize an ext2/ext3 filesystem",
2131 This resizes an ext2 or ext3 filesystem to match the size of
2132 the underlying device.
2134 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2135 on the C<device> before calling this command. For unknown reasons
2136 C<resize2fs> sometimes gives an error about this and sometimes not.
2137 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2138 calling this function.");
2140 ("find", (RStringList "names", [String "directory"]), 107, [],
2141 [InitBasicFS, Always, TestOutputList (
2142 [["find"; "/"]], ["lost+found"]);
2143 InitBasicFS, Always, TestOutputList (
2147 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2148 InitBasicFS, Always, TestOutputList (
2149 [["mkdir_p"; "/a/b/c"];
2150 ["touch"; "/a/b/c/d"];
2151 ["find"; "/a/b/"]], ["c"; "c/d"])],
2152 "find all files and directories",
2154 This command lists out all files and directories, recursively,
2155 starting at C<directory>. It is essentially equivalent to
2156 running the shell command C<find directory -print> but some
2157 post-processing happens on the output, described below.
2159 This returns a list of strings I<without any prefix>. Thus
2160 if the directory structure was:
2166 then the returned list from C<guestfs_find> C</tmp> would be
2174 If C<directory> is not a directory, then this command returns
2177 The returned list is sorted.");
2179 ("e2fsck_f", (RErr, [String "device"]), 108, [],
2180 [], (* lvresize tests this *)
2181 "check an ext2/ext3 filesystem",
2183 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2184 filesystem checker on C<device>, noninteractively (C<-p>),
2185 even if the filesystem appears to be clean (C<-f>).
2187 This command is only needed because of C<guestfs_resize2fs>
2188 (q.v.). Normally you should use C<guestfs_fsck>.");
2192 let all_functions = non_daemon_functions @ daemon_functions
2194 (* In some places we want the functions to be displayed sorted
2195 * alphabetically, so this is useful:
2197 let all_functions_sorted =
2198 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
2199 compare n1 n2) all_functions
2201 (* Column names and types from LVM PVs/VGs/LVs. *)
2210 "pv_attr", `String (* XXX *);
2211 "pv_pe_count", `Int;
2212 "pv_pe_alloc_count", `Int;
2215 "pv_mda_count", `Int;
2216 "pv_mda_free", `Bytes;
2217 (* Not in Fedora 10:
2218 "pv_mda_size", `Bytes;
2225 "vg_attr", `String (* XXX *);
2228 "vg_sysid", `String;
2229 "vg_extent_size", `Bytes;
2230 "vg_extent_count", `Int;
2231 "vg_free_count", `Int;
2239 "vg_mda_count", `Int;
2240 "vg_mda_free", `Bytes;
2241 (* Not in Fedora 10:
2242 "vg_mda_size", `Bytes;
2248 "lv_attr", `String (* XXX *);
2251 "lv_kernel_major", `Int;
2252 "lv_kernel_minor", `Int;
2256 "snap_percent", `OptPercent;
2257 "copy_percent", `OptPercent;
2260 "mirror_log", `String;
2264 (* Column names and types from stat structures.
2265 * NB. Can't use things like 'st_atime' because glibc header files
2266 * define some of these as macros. Ugh.
2283 let statvfs_cols = [
2297 (* Useful functions.
2298 * Note we don't want to use any external OCaml libraries which
2299 * makes this a bit harder than it should be.
2301 let failwithf fs = ksprintf failwith fs
2303 let replace_char s c1 c2 =
2304 let s2 = String.copy s in
2305 let r = ref false in
2306 for i = 0 to String.length s2 - 1 do
2307 if String.unsafe_get s2 i = c1 then (
2308 String.unsafe_set s2 i c2;
2312 if not !r then s else s2
2316 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
2318 let triml ?(test = isspace) str =
2320 let n = ref (String.length str) in
2321 while !n > 0 && test str.[!i]; do
2326 else String.sub str !i !n
2328 let trimr ?(test = isspace) str =
2329 let n = ref (String.length str) in
2330 while !n > 0 && test str.[!n-1]; do
2333 if !n = String.length str then str
2334 else String.sub str 0 !n
2336 let trim ?(test = isspace) str =
2337 trimr ~test (triml ~test str)
2339 let rec find s sub =
2340 let len = String.length s in
2341 let sublen = String.length sub in
2343 if i <= len-sublen then (
2345 if j < sublen then (
2346 if s.[i+j] = sub.[j] then loop2 (j+1)
2352 if r = -1 then loop (i+1) else r
2358 let rec replace_str s s1 s2 =
2359 let len = String.length s in
2360 let sublen = String.length s1 in
2361 let i = find s s1 in
2364 let s' = String.sub s 0 i in
2365 let s'' = String.sub s (i+sublen) (len-i-sublen) in
2366 s' ^ s2 ^ replace_str s'' s1 s2
2369 let rec string_split sep str =
2370 let len = String.length str in
2371 let seplen = String.length sep in
2372 let i = find str sep in
2373 if i = -1 then [str]
2375 let s' = String.sub str 0 i in
2376 let s'' = String.sub str (i+seplen) (len-i-seplen) in
2377 s' :: string_split sep s''
2380 let files_equal n1 n2 =
2381 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
2382 match Sys.command cmd with
2385 | i -> failwithf "%s: failed with error code %d" cmd i
2387 let rec find_map f = function
2388 | [] -> raise Not_found
2392 | None -> find_map f xs
2395 let rec loop i = function
2397 | x :: xs -> f i x; loop (i+1) xs
2402 let rec loop i = function
2404 | x :: xs -> let r = f i x in r :: loop (i+1) xs
2408 let name_of_argt = function
2409 | String n | OptString n | StringList n | Bool n | Int n
2410 | FileIn n | FileOut n -> n
2412 let seq_of_test = function
2413 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
2414 | TestOutputInt (s, _) | TestOutputTrue s | TestOutputFalse s
2415 | TestOutputLength (s, _) | TestOutputStruct (s, _)
2416 | TestLastFail s -> s
2418 (* Check function names etc. for consistency. *)
2419 let check_functions () =
2420 let contains_uppercase str =
2421 let len = String.length str in
2423 if i >= len then false
2426 if c >= 'A' && c <= 'Z' then true
2433 (* Check function names. *)
2435 fun (name, _, _, _, _, _, _) ->
2436 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
2437 failwithf "function name %s does not need 'guestfs' prefix" name;
2439 failwithf "function name is empty";
2440 if name.[0] < 'a' || name.[0] > 'z' then
2441 failwithf "function name %s must start with lowercase a-z" name;
2442 if String.contains name '-' then
2443 failwithf "function name %s should not contain '-', use '_' instead."
2447 (* Check function parameter/return names. *)
2449 fun (name, style, _, _, _, _, _) ->
2450 let check_arg_ret_name n =
2451 if contains_uppercase n then
2452 failwithf "%s param/ret %s should not contain uppercase chars"
2454 if String.contains n '-' || String.contains n '_' then
2455 failwithf "%s param/ret %s should not contain '-' or '_'"
2458 failwithf "%s has a param/ret called 'value', which causes conflicts in the OCaml bindings, use something like 'val' or a more descriptive name" n;
2459 if n = "argv" || n = "args" then
2460 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" n
2463 (match fst style with
2465 | RInt n | RInt64 n | RBool n | RConstString n | RString n
2466 | RStringList n | RPVList n | RVGList n | RLVList n
2467 | RStat n | RStatVFS n
2469 check_arg_ret_name n
2471 check_arg_ret_name n;
2472 check_arg_ret_name m
2474 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
2477 (* Check short descriptions. *)
2479 fun (name, _, _, _, _, shortdesc, _) ->
2480 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
2481 failwithf "short description of %s should begin with lowercase." name;
2482 let c = shortdesc.[String.length shortdesc-1] in
2483 if c = '\n' || c = '.' then
2484 failwithf "short description of %s should not end with . or \\n." name
2487 (* Check long dscriptions. *)
2489 fun (name, _, _, _, _, _, longdesc) ->
2490 if longdesc.[String.length longdesc-1] = '\n' then
2491 failwithf "long description of %s should not end with \\n." name
2494 (* Check proc_nrs. *)
2496 fun (name, _, proc_nr, _, _, _, _) ->
2497 if proc_nr <= 0 then
2498 failwithf "daemon function %s should have proc_nr > 0" name
2502 fun (name, _, proc_nr, _, _, _, _) ->
2503 if proc_nr <> -1 then
2504 failwithf "non-daemon function %s should have proc_nr -1" name
2505 ) non_daemon_functions;
2508 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
2511 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
2512 let rec loop = function
2515 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
2517 | (name1,nr1) :: (name2,nr2) :: _ ->
2518 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
2526 (* Ignore functions that have no tests. We generate a
2527 * warning when the user does 'make check' instead.
2529 | name, _, _, _, [], _, _ -> ()
2530 | name, _, _, _, tests, _, _ ->
2534 match seq_of_test test with
2536 failwithf "%s has a test containing an empty sequence" name
2537 | cmds -> List.map List.hd cmds
2539 let funcs = List.flatten funcs in
2541 let tested = List.mem name funcs in
2544 failwithf "function %s has tests but does not test itself" name
2547 (* 'pr' prints to the current output file. *)
2548 let chan = ref stdout
2549 let pr fs = ksprintf (output_string !chan) fs
2551 (* Generate a header block in a number of standard styles. *)
2552 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
2553 type license = GPLv2 | LGPLv2
2555 let generate_header comment license =
2556 let c = match comment with
2557 | CStyle -> pr "/* "; " *"
2558 | HashStyle -> pr "# "; "#"
2559 | OCamlStyle -> pr "(* "; " *"
2560 | HaskellStyle -> pr "{- "; " " in
2561 pr "libguestfs generated file\n";
2562 pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
2563 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
2565 pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
2569 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
2570 pr "%s it under the terms of the GNU General Public License as published by\n" c;
2571 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
2572 pr "%s (at your option) any later version.\n" c;
2574 pr "%s This program is distributed in the hope that it will be useful,\n" c;
2575 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
2576 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
2577 pr "%s GNU General Public License for more details.\n" c;
2579 pr "%s You should have received a copy of the GNU General Public License along\n" c;
2580 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
2581 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
2584 pr "%s This library is free software; you can redistribute it and/or\n" c;
2585 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
2586 pr "%s License as published by the Free Software Foundation; either\n" c;
2587 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
2589 pr "%s This library is distributed in the hope that it will be useful,\n" c;
2590 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
2591 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
2592 pr "%s Lesser General Public License for more details.\n" c;
2594 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
2595 pr "%s License along with this library; if not, write to the Free Software\n" c;
2596 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
2599 | CStyle -> pr " */\n"
2601 | OCamlStyle -> pr " *)\n"
2602 | HaskellStyle -> pr "-}\n"
2606 (* Start of main code generation functions below this line. *)
2608 (* Generate the pod documentation for the C API. *)
2609 let rec generate_actions_pod () =
2611 fun (shortname, style, _, flags, _, _, longdesc) ->
2612 let name = "guestfs_" ^ shortname in
2613 pr "=head2 %s\n\n" name;
2615 generate_prototype ~extern:false ~handle:"handle" name style;
2617 pr "%s\n\n" longdesc;
2618 (match fst style with
2620 pr "This function returns 0 on success or -1 on error.\n\n"
2622 pr "On error this function returns -1.\n\n"
2624 pr "On error this function returns -1.\n\n"
2626 pr "This function returns a C truth value on success or -1 on error.\n\n"
2628 pr "This function returns a string, or NULL on error.
2629 The string is owned by the guest handle and must I<not> be freed.\n\n"
2631 pr "This function returns a string, or NULL on error.
2632 I<The caller must free the returned string after use>.\n\n"
2634 pr "This function returns a NULL-terminated array of strings
2635 (like L<environ(3)>), or NULL if there was an error.
2636 I<The caller must free the strings and the array after use>.\n\n"
2638 pr "This function returns a C<struct guestfs_int_bool *>,
2639 or NULL if there was an error.
2640 I<The caller must call C<guestfs_free_int_bool> after use>.\n\n"
2642 pr "This function returns a C<struct guestfs_lvm_pv_list *>
2643 (see E<lt>guestfs-structs.hE<gt>),
2644 or NULL if there was an error.
2645 I<The caller must call C<guestfs_free_lvm_pv_list> after use>.\n\n"
2647 pr "This function returns a C<struct guestfs_lvm_vg_list *>
2648 (see E<lt>guestfs-structs.hE<gt>),
2649 or NULL if there was an error.
2650 I<The caller must call C<guestfs_free_lvm_vg_list> after use>.\n\n"
2652 pr "This function returns a C<struct guestfs_lvm_lv_list *>
2653 (see E<lt>guestfs-structs.hE<gt>),
2654 or NULL if there was an error.
2655 I<The caller must call C<guestfs_free_lvm_lv_list> after use>.\n\n"
2657 pr "This function returns a C<struct guestfs_stat *>
2658 (see L<stat(2)> and E<lt>guestfs-structs.hE<gt>),
2659 or NULL if there was an error.
2660 I<The caller must call C<free> after use>.\n\n"
2662 pr "This function returns a C<struct guestfs_statvfs *>
2663 (see L<statvfs(2)> and E<lt>guestfs-structs.hE<gt>),
2664 or NULL if there was an error.
2665 I<The caller must call C<free> after use>.\n\n"
2667 pr "This function returns a NULL-terminated array of
2668 strings, or NULL if there was an error.
2669 The array of strings will always have length C<2n+1>, where
2670 C<n> keys and values alternate, followed by the trailing NULL entry.
2671 I<The caller must free the strings and the array after use>.\n\n"
2673 if List.mem ProtocolLimitWarning flags then
2674 pr "%s\n\n" protocol_limit_warning;
2675 if List.mem DangerWillRobinson flags then
2676 pr "%s\n\n" danger_will_robinson;
2677 ) all_functions_sorted
2679 and generate_structs_pod () =
2680 (* LVM structs documentation. *)
2683 pr "=head2 guestfs_lvm_%s\n" typ;
2685 pr " struct guestfs_lvm_%s {\n" typ;
2688 | name, `String -> pr " char *%s;\n" name
2690 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
2691 pr " char %s[32];\n" name
2692 | name, `Bytes -> pr " uint64_t %s;\n" name
2693 | name, `Int -> pr " int64_t %s;\n" name
2694 | name, `OptPercent ->
2695 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
2696 pr " float %s;\n" name
2699 pr " struct guestfs_lvm_%s_list {\n" typ;
2700 pr " uint32_t len; /* Number of elements in list. */\n";
2701 pr " struct guestfs_lvm_%s *val; /* Elements. */\n" typ;
2704 pr " void guestfs_free_lvm_%s_list (struct guestfs_free_lvm_%s_list *);\n"
2707 ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]
2709 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
2710 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
2712 * We have to use an underscore instead of a dash because otherwise
2713 * rpcgen generates incorrect code.
2715 * This header is NOT exported to clients, but see also generate_structs_h.
2717 and generate_xdr () =
2718 generate_header CStyle LGPLv2;
2720 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
2721 pr "typedef string str<>;\n";
2724 (* LVM internal structures. *)
2728 pr "struct guestfs_lvm_int_%s {\n" typ;
2730 | name, `String -> pr " string %s<>;\n" name
2731 | name, `UUID -> pr " opaque %s[32];\n" name
2732 | name, `Bytes -> pr " hyper %s;\n" name
2733 | name, `Int -> pr " hyper %s;\n" name
2734 | name, `OptPercent -> pr " float %s;\n" name
2738 pr "typedef struct guestfs_lvm_int_%s guestfs_lvm_int_%s_list<>;\n" typ typ;
2740 ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
2742 (* Stat internal structures. *)
2746 pr "struct guestfs_int_%s {\n" typ;
2748 | name, `Int -> pr " hyper %s;\n" name
2752 ) ["stat", stat_cols; "statvfs", statvfs_cols];
2755 fun (shortname, style, _, _, _, _, _) ->
2756 let name = "guestfs_" ^ shortname in
2758 (match snd style with
2761 pr "struct %s_args {\n" name;
2764 | String n -> pr " string %s<>;\n" n
2765 | OptString n -> pr " str *%s;\n" n
2766 | StringList n -> pr " str %s<>;\n" n
2767 | Bool n -> pr " bool %s;\n" n
2768 | Int n -> pr " int %s;\n" n
2769 | FileIn _ | FileOut _ -> ()
2773 (match fst style with
2776 pr "struct %s_ret {\n" name;
2780 pr "struct %s_ret {\n" name;
2781 pr " hyper %s;\n" n;
2784 pr "struct %s_ret {\n" name;
2788 failwithf "RConstString cannot be returned from a daemon function"
2790 pr "struct %s_ret {\n" name;
2791 pr " string %s<>;\n" n;
2794 pr "struct %s_ret {\n" name;
2795 pr " str %s<>;\n" n;
2798 pr "struct %s_ret {\n" name;
2803 pr "struct %s_ret {\n" name;
2804 pr " guestfs_lvm_int_pv_list %s;\n" n;
2807 pr "struct %s_ret {\n" name;
2808 pr " guestfs_lvm_int_vg_list %s;\n" n;
2811 pr "struct %s_ret {\n" name;
2812 pr " guestfs_lvm_int_lv_list %s;\n" n;
2815 pr "struct %s_ret {\n" name;
2816 pr " guestfs_int_stat %s;\n" n;
2819 pr "struct %s_ret {\n" name;
2820 pr " guestfs_int_statvfs %s;\n" n;
2823 pr "struct %s_ret {\n" name;
2824 pr " str %s<>;\n" n;
2829 (* Table of procedure numbers. *)
2830 pr "enum guestfs_procedure {\n";
2832 fun (shortname, _, proc_nr, _, _, _, _) ->
2833 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
2835 pr " GUESTFS_PROC_NR_PROCS\n";
2839 (* Having to choose a maximum message size is annoying for several
2840 * reasons (it limits what we can do in the API), but it (a) makes
2841 * the protocol a lot simpler, and (b) provides a bound on the size
2842 * of the daemon which operates in limited memory space. For large
2843 * file transfers you should use FTP.
2845 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
2848 (* Message header, etc. *)
2850 /* The communication protocol is now documented in the guestfs(3)
2854 const GUESTFS_PROGRAM = 0x2000F5F5;
2855 const GUESTFS_PROTOCOL_VERSION = 1;
2857 /* These constants must be larger than any possible message length. */
2858 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
2859 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
2861 enum guestfs_message_direction {
2862 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
2863 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
2866 enum guestfs_message_status {
2867 GUESTFS_STATUS_OK = 0,
2868 GUESTFS_STATUS_ERROR = 1
2871 const GUESTFS_ERROR_LEN = 256;
2873 struct guestfs_message_error {
2874 string error_message<GUESTFS_ERROR_LEN>;
2877 struct guestfs_message_header {
2878 unsigned prog; /* GUESTFS_PROGRAM */
2879 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
2880 guestfs_procedure proc; /* GUESTFS_PROC_x */
2881 guestfs_message_direction direction;
2882 unsigned serial; /* message serial number */
2883 guestfs_message_status status;
2886 const GUESTFS_MAX_CHUNK_SIZE = 8192;
2888 struct guestfs_chunk {
2889 int cancel; /* if non-zero, transfer is cancelled */
2890 /* data size is 0 bytes if the transfer has finished successfully */
2891 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
2895 (* Generate the guestfs-structs.h file. *)
2896 and generate_structs_h () =
2897 generate_header CStyle LGPLv2;
2899 (* This is a public exported header file containing various
2900 * structures. The structures are carefully written to have
2901 * exactly the same in-memory format as the XDR structures that
2902 * we use on the wire to the daemon. The reason for creating
2903 * copies of these structures here is just so we don't have to
2904 * export the whole of guestfs_protocol.h (which includes much
2905 * unrelated and XDR-dependent stuff that we don't want to be
2906 * public, or required by clients).
2908 * To reiterate, we will pass these structures to and from the
2909 * client with a simple assignment or memcpy, so the format
2910 * must be identical to what rpcgen / the RFC defines.
2913 (* guestfs_int_bool structure. *)
2914 pr "struct guestfs_int_bool {\n";
2920 (* LVM public structures. *)
2924 pr "struct guestfs_lvm_%s {\n" typ;
2927 | name, `String -> pr " char *%s;\n" name
2928 | name, `UUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
2929 | name, `Bytes -> pr " uint64_t %s;\n" name
2930 | name, `Int -> pr " int64_t %s;\n" name
2931 | name, `OptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
2935 pr "struct guestfs_lvm_%s_list {\n" typ;
2936 pr " uint32_t len;\n";
2937 pr " struct guestfs_lvm_%s *val;\n" typ;
2940 ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
2942 (* Stat structures. *)
2946 pr "struct guestfs_%s {\n" typ;
2949 | name, `Int -> pr " int64_t %s;\n" name
2953 ) ["stat", stat_cols; "statvfs", statvfs_cols]
2955 (* Generate the guestfs-actions.h file. *)
2956 and generate_actions_h () =
2957 generate_header CStyle LGPLv2;
2959 fun (shortname, style, _, _, _, _, _) ->
2960 let name = "guestfs_" ^ shortname in
2961 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
2965 (* Generate the client-side dispatch stubs. *)
2966 and generate_client_actions () =
2967 generate_header CStyle LGPLv2;
2973 #include \"guestfs.h\"
2974 #include \"guestfs_protocol.h\"
2976 #define error guestfs_error
2977 #define perrorf guestfs_perrorf
2978 #define safe_malloc guestfs_safe_malloc
2979 #define safe_realloc guestfs_safe_realloc
2980 #define safe_strdup guestfs_safe_strdup
2981 #define safe_memdup guestfs_safe_memdup
2983 /* Check the return message from a call for validity. */
2985 check_reply_header (guestfs_h *g,
2986 const struct guestfs_message_header *hdr,
2987 int proc_nr, int serial)
2989 if (hdr->prog != GUESTFS_PROGRAM) {
2990 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
2993 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
2994 error (g, \"wrong protocol version (%%d/%%d)\",
2995 hdr->vers, GUESTFS_PROTOCOL_VERSION);
2998 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
2999 error (g, \"unexpected message direction (%%d/%%d)\",
3000 hdr->direction, GUESTFS_DIRECTION_REPLY);
3003 if (hdr->proc != proc_nr) {
3004 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
3007 if (hdr->serial != serial) {
3008 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
3015 /* Check we are in the right state to run a high-level action. */
3017 check_state (guestfs_h *g, const char *caller)
3019 if (!guestfs_is_ready (g)) {
3020 if (guestfs_is_config (g))
3021 error (g, \"%%s: call launch() before using this function\",
3023 else if (guestfs_is_launching (g))
3024 error (g, \"%%s: call wait_ready() before using this function\",
3027 error (g, \"%%s called from the wrong state, %%d != READY\",
3028 caller, guestfs_get_state (g));
3036 (* Client-side stubs for each function. *)
3038 fun (shortname, style, _, _, _, _, _) ->
3039 let name = "guestfs_" ^ shortname in
3041 (* Generate the context struct which stores the high-level
3042 * state between callback functions.
3044 pr "struct %s_ctx {\n" shortname;
3045 pr " /* This flag is set by the callbacks, so we know we've done\n";
3046 pr " * the callbacks as expected, and in the right sequence.\n";
3047 pr " * 0 = not called, 1 = reply_cb called.\n";
3049 pr " int cb_sequence;\n";
3050 pr " struct guestfs_message_header hdr;\n";
3051 pr " struct guestfs_message_error err;\n";
3052 (match fst style with
3055 failwithf "RConstString cannot be returned from a daemon function"
3057 | RBool _ | RString _ | RStringList _
3059 | RPVList _ | RVGList _ | RLVList _
3060 | RStat _ | RStatVFS _
3062 pr " struct %s_ret ret;\n" name
3067 (* Generate the reply callback function. *)
3068 pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
3070 pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
3071 pr " struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
3073 pr " /* This should definitely not happen. */\n";
3074 pr " if (ctx->cb_sequence != 0) {\n";
3075 pr " ctx->cb_sequence = 9999;\n";
3076 pr " error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name;
3080 pr " ml->main_loop_quit (ml, g);\n";
3082 pr " if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n";
3083 pr " error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name;
3086 pr " if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n";
3087 pr " if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n";
3088 pr " error (g, \"%%s: failed to parse reply error\", \"%s\");\n"
3095 (match fst style with
3098 failwithf "RConstString cannot be returned from a daemon function"
3100 | RBool _ | RString _ | RStringList _
3102 | RPVList _ | RVGList _ | RLVList _
3103 | RStat _ | RStatVFS _
3105 pr " if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name;
3106 pr " error (g, \"%%s: failed to parse reply\", \"%s\");\n" name;
3112 pr " ctx->cb_sequence = 1;\n";
3115 (* Generate the action stub. *)
3116 generate_prototype ~extern:false ~semicolon:false ~newline:true
3117 ~handle:"g" name style;
3120 match fst style with
3121 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
3123 failwithf "RConstString cannot be returned from a daemon function"
3124 | RString _ | RStringList _ | RIntBool _
3125 | RPVList _ | RVGList _ | RLVList _
3126 | RStat _ | RStatVFS _
3132 (match snd style with
3134 | _ -> pr " struct %s_args args;\n" name
3137 pr " struct %s_ctx ctx;\n" shortname;
3138 pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
3139 pr " int serial;\n";
3141 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
3142 pr " guestfs_set_busy (g);\n";
3144 pr " memset (&ctx, 0, sizeof ctx);\n";
3147 (* Send the main header and arguments. *)
3148 (match snd style with
3150 pr " serial = guestfs__send_sync (g, GUESTFS_PROC_%s, NULL, NULL);\n"
3151 (String.uppercase shortname)
3156 pr " args.%s = (char *) %s;\n" n n
3158 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
3160 pr " args.%s.%s_val = (char **) %s;\n" n n n;
3161 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
3163 pr " args.%s = %s;\n" n n
3165 pr " args.%s = %s;\n" n n
3166 | FileIn _ | FileOut _ -> ()
3168 pr " serial = guestfs__send_sync (g, GUESTFS_PROC_%s,\n"
3169 (String.uppercase shortname);
3170 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
3173 pr " if (serial == -1) {\n";
3174 pr " guestfs_end_busy (g);\n";
3175 pr " return %s;\n" error_code;
3179 (* Send any additional files (FileIn) requested. *)
3180 let need_read_reply_label = ref false in
3187 pr " r = guestfs__send_file_sync (g, %s);\n" n;
3188 pr " if (r == -1) {\n";
3189 pr " guestfs_end_busy (g);\n";
3190 pr " return %s;\n" error_code;
3192 pr " if (r == -2) /* daemon cancelled */\n";
3193 pr " goto read_reply;\n";
3194 need_read_reply_label := true;
3200 (* Wait for the reply from the remote end. *)
3201 if !need_read_reply_label then pr " read_reply:\n";
3202 pr " guestfs__switch_to_receiving (g);\n";
3203 pr " ctx.cb_sequence = 0;\n";
3204 pr " guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname;
3205 pr " (void) ml->main_loop_run (ml, g);\n";
3206 pr " guestfs_set_reply_callback (g, NULL, NULL);\n";
3207 pr " if (ctx.cb_sequence != 1) {\n";
3208 pr " error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name;
3209 pr " guestfs_end_busy (g);\n";
3210 pr " return %s;\n" error_code;
3214 pr " if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
3215 (String.uppercase shortname);
3216 pr " guestfs_end_busy (g);\n";
3217 pr " return %s;\n" error_code;
3221 pr " if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n";
3222 pr " error (g, \"%%s\", ctx.err.error_message);\n";
3223 pr " free (ctx.err.error_message);\n";
3224 pr " guestfs_end_busy (g);\n";
3225 pr " return %s;\n" error_code;
3229 (* Expecting to receive further files (FileOut)? *)
3233 pr " if (guestfs__receive_file_sync (g, %s) == -1) {\n" n;
3234 pr " guestfs_end_busy (g);\n";
3235 pr " return %s;\n" error_code;
3241 pr " guestfs_end_busy (g);\n";
3243 (match fst style with
3244 | RErr -> pr " return 0;\n"
3245 | RInt n | RInt64 n | RBool n ->
3246 pr " return ctx.ret.%s;\n" n
3248 failwithf "RConstString cannot be returned from a daemon function"
3250 pr " return ctx.ret.%s; /* caller will free */\n" n
3251 | RStringList n | RHashtable n ->
3252 pr " /* caller will free this, but we need to add a NULL entry */\n";
3253 pr " ctx.ret.%s.%s_val =\n" n n;
3254 pr " safe_realloc (g, ctx.ret.%s.%s_val,\n" n n;
3255 pr " sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n"
3257 pr " ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n;
3258 pr " return ctx.ret.%s.%s_val;\n" n n
3260 pr " /* caller with free this */\n";
3261 pr " return safe_memdup (g, &ctx.ret, sizeof (ctx.ret));\n"
3262 | RPVList n | RVGList n | RLVList n
3263 | RStat n | RStatVFS n ->
3264 pr " /* caller will free this */\n";
3265 pr " return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
3271 (* Generate daemon/actions.h. *)
3272 and generate_daemon_actions_h () =
3273 generate_header CStyle GPLv2;
3275 pr "#include \"../src/guestfs_protocol.h\"\n";
3279 fun (name, style, _, _, _, _, _) ->
3281 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
3285 (* Generate the server-side stubs. *)
3286 and generate_daemon_actions () =
3287 generate_header CStyle GPLv2;
3289 pr "#include <config.h>\n";
3291 pr "#include <stdio.h>\n";
3292 pr "#include <stdlib.h>\n";
3293 pr "#include <string.h>\n";
3294 pr "#include <inttypes.h>\n";
3295 pr "#include <ctype.h>\n";
3296 pr "#include <rpc/types.h>\n";
3297 pr "#include <rpc/xdr.h>\n";
3299 pr "#include \"daemon.h\"\n";
3300 pr "#include \"../src/guestfs_protocol.h\"\n";
3301 pr "#include \"actions.h\"\n";
3305 fun (name, style, _, _, _, _, _) ->
3306 (* Generate server-side stubs. *)
3307 pr "static void %s_stub (XDR *xdr_in)\n" name;
3310 match fst style with
3311 | RErr | RInt _ -> pr " int r;\n"; "-1"
3312 | RInt64 _ -> pr " int64_t r;\n"; "-1"
3313 | RBool _ -> pr " int r;\n"; "-1"
3315 failwithf "RConstString cannot be returned from a daemon function"
3316 | RString _ -> pr " char *r;\n"; "NULL"
3317 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
3318 | RIntBool _ -> pr " guestfs_%s_ret *r;\n" name; "NULL"
3319 | RPVList _ -> pr " guestfs_lvm_int_pv_list *r;\n"; "NULL"
3320 | RVGList _ -> pr " guestfs_lvm_int_vg_list *r;\n"; "NULL"
3321 | RLVList _ -> pr " guestfs_lvm_int_lv_list *r;\n"; "NULL"
3322 | RStat _ -> pr " guestfs_int_stat *r;\n"; "NULL"
3323 | RStatVFS _ -> pr " guestfs_int_statvfs *r;\n"; "NULL" in
3325 (match snd style with
3328 pr " struct guestfs_%s_args args;\n" name;
3332 | OptString n -> pr " const char *%s;\n" n
3333 | StringList n -> pr " char **%s;\n" n
3334 | Bool n -> pr " int %s;\n" n
3335 | Int n -> pr " int %s;\n" n
3336 | FileIn _ | FileOut _ -> ()
3341 (match snd style with
3344 pr " memset (&args, 0, sizeof args);\n";
3346 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
3347 pr " reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
3352 | String n -> pr " %s = args.%s;\n" n n
3353 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
3355 pr " %s = realloc (args.%s.%s_val,\n" n n n;
3356 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
3357 pr " if (%s == NULL) {\n" n;
3358 pr " reply_with_perror (\"realloc\");\n";
3361 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
3362 pr " args.%s.%s_val = %s;\n" n n n;
3363 | Bool n -> pr " %s = args.%s;\n" n n
3364 | Int n -> pr " %s = args.%s;\n" n n
3365 | FileIn _ | FileOut _ -> ()
3370 (* Don't want to call the impl with any FileIn or FileOut
3371 * parameters, since these go "outside" the RPC protocol.
3374 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
3376 pr " r = do_%s " name;
3377 generate_call_args argsnofile;
3380 pr " if (r == %s)\n" error_code;
3381 pr " /* do_%s has already called reply_with_error */\n" name;
3385 (* If there are any FileOut parameters, then the impl must
3386 * send its own reply.
3389 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
3391 pr " /* do_%s has already sent a reply */\n" name
3393 match fst style with
3394 | RErr -> pr " reply (NULL, NULL);\n"
3395 | RInt n | RInt64 n | RBool n ->
3396 pr " struct guestfs_%s_ret ret;\n" name;
3397 pr " ret.%s = r;\n" n;
3398 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
3401 failwithf "RConstString cannot be returned from a daemon function"
3403 pr " struct guestfs_%s_ret ret;\n" name;
3404 pr " ret.%s = r;\n" n;
3405 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
3408 | RStringList n | RHashtable n ->
3409 pr " struct guestfs_%s_ret ret;\n" name;
3410 pr " ret.%s.%s_len = count_strings (r);\n" n n;
3411 pr " ret.%s.%s_val = r;\n" n n;
3412 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
3414 pr " free_strings (r);\n"
3416 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) r);\n"
3418 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) r);\n" name
3419 | RPVList n | RVGList n | RLVList n
3420 | RStat n | RStatVFS n ->
3421 pr " struct guestfs_%s_ret ret;\n" name;
3422 pr " ret.%s = *r;\n" n;
3423 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
3425 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
3429 (* Free the args. *)
3430 (match snd style with
3435 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
3442 (* Dispatch function. *)
3443 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
3445 pr " switch (proc_nr) {\n";
3448 fun (name, style, _, _, _, _, _) ->
3449 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
3450 pr " %s_stub (xdr_in);\n" name;
3455 pr " reply_with_error (\"dispatch_incoming_message: unknown procedure number %%d\", proc_nr);\n";
3460 (* LVM columns and tokenization functions. *)
3461 (* XXX This generates crap code. We should rethink how we
3467 pr "static const char *lvm_%s_cols = \"%s\";\n"
3468 typ (String.concat "," (List.map fst cols));
3471 pr "static int lvm_tokenize_%s (char *str, struct guestfs_lvm_int_%s *r)\n" typ typ;
3473 pr " char *tok, *p, *next;\n";
3477 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
3480 pr " if (!str) {\n";
3481 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
3484 pr " if (!*str || isspace (*str)) {\n";
3485 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
3490 fun (name, coltype) ->
3491 pr " if (!tok) {\n";
3492 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
3495 pr " p = strchrnul (tok, ',');\n";
3496 pr " if (*p) next = p+1; else next = NULL;\n";
3497 pr " *p = '\\0';\n";
3500 pr " r->%s = strdup (tok);\n" name;
3501 pr " if (r->%s == NULL) {\n" name;
3502 pr " perror (\"strdup\");\n";
3506 pr " for (i = j = 0; i < 32; ++j) {\n";
3507 pr " if (tok[j] == '\\0') {\n";
3508 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
3510 pr " } else if (tok[j] != '-')\n";
3511 pr " r->%s[i++] = tok[j];\n" name;
3514 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
3515 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
3519 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
3520 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
3524 pr " if (tok[0] == '\\0')\n";
3525 pr " r->%s = -1;\n" name;
3526 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
3527 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
3531 pr " tok = next;\n";
3534 pr " if (tok != NULL) {\n";
3535 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
3542 pr "guestfs_lvm_int_%s_list *\n" typ;
3543 pr "parse_command_line_%ss (void)\n" typ;
3545 pr " char *out, *err;\n";
3546 pr " char *p, *pend;\n";
3548 pr " guestfs_lvm_int_%s_list *ret;\n" typ;
3549 pr " void *newp;\n";
3551 pr " ret = malloc (sizeof *ret);\n";
3552 pr " if (!ret) {\n";
3553 pr " reply_with_perror (\"malloc\");\n";
3554 pr " return NULL;\n";
3557 pr " ret->guestfs_lvm_int_%s_list_len = 0;\n" typ;
3558 pr " ret->guestfs_lvm_int_%s_list_val = NULL;\n" typ;
3560 pr " r = command (&out, &err,\n";
3561 pr " \"/sbin/lvm\", \"%ss\",\n" typ;
3562 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
3563 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
3564 pr " if (r == -1) {\n";
3565 pr " reply_with_error (\"%%s\", err);\n";
3566 pr " free (out);\n";
3567 pr " free (err);\n";
3568 pr " free (ret);\n";
3569 pr " return NULL;\n";
3572 pr " free (err);\n";
3574 pr " /* Tokenize each line of the output. */\n";
3577 pr " while (p) {\n";
3578 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
3579 pr " if (pend) {\n";
3580 pr " *pend = '\\0';\n";
3584 pr " while (*p && isspace (*p)) /* Skip any leading whitespace. */\n";
3587 pr " if (!*p) { /* Empty line? Skip it. */\n";
3592 pr " /* Allocate some space to store this next entry. */\n";
3593 pr " newp = realloc (ret->guestfs_lvm_int_%s_list_val,\n" typ;
3594 pr " sizeof (guestfs_lvm_int_%s) * (i+1));\n" typ;
3595 pr " if (newp == NULL) {\n";
3596 pr " reply_with_perror (\"realloc\");\n";
3597 pr " free (ret->guestfs_lvm_int_%s_list_val);\n" typ;
3598 pr " free (ret);\n";
3599 pr " free (out);\n";
3600 pr " return NULL;\n";
3602 pr " ret->guestfs_lvm_int_%s_list_val = newp;\n" typ;
3604 pr " /* Tokenize the next entry. */\n";
3605 pr " r = lvm_tokenize_%s (p, &ret->guestfs_lvm_int_%s_list_val[i]);\n" typ typ;
3606 pr " if (r == -1) {\n";
3607 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
3608 pr " free (ret->guestfs_lvm_int_%s_list_val);\n" typ;
3609 pr " free (ret);\n";
3610 pr " free (out);\n";
3611 pr " return NULL;\n";
3618 pr " ret->guestfs_lvm_int_%s_list_len = i;\n" typ;
3620 pr " free (out);\n";
3621 pr " return ret;\n";
3624 ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]
3626 (* Generate the tests. *)
3627 and generate_tests () =
3628 generate_header CStyle GPLv2;
3635 #include <sys/types.h>
3638 #include \"guestfs.h\"
3640 static guestfs_h *g;
3641 static int suppress_error = 0;
3643 /* This will be 's' or 'h' depending on whether the guest kernel
3644 * names IDE devices /dev/sd* or /dev/hd*.
3646 static char devchar = 's';
3648 static void print_error (guestfs_h *g, void *data, const char *msg)
3650 if (!suppress_error)
3651 fprintf (stderr, \"%%s\\n\", msg);
3654 static void print_strings (char * const * const argv)
3658 for (argc = 0; argv[argc] != NULL; ++argc)
3659 printf (\"\\t%%s\\n\", argv[argc]);
3663 static void print_table (char * const * const argv)
3667 for (i = 0; argv[i] != NULL; i += 2)
3668 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
3672 static void no_test_warnings (void)
3678 | name, _, _, _, [], _, _ ->
3679 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
3680 | name, _, _, _, tests, _, _ -> ()
3686 (* Generate the actual tests. Note that we generate the tests
3687 * in reverse order, deliberately, so that (in general) the
3688 * newest tests run first. This makes it quicker and easier to
3693 fun (name, _, _, _, tests, _, _) ->
3694 mapi (generate_one_test name) tests
3695 ) (List.rev all_functions) in
3696 let test_names = List.concat test_names in
3697 let nr_tests = List.length test_names in
3700 int main (int argc, char *argv[])
3705 const char *filename;
3707 int nr_tests, test_num = 0;
3710 no_test_warnings ();
3712 g = guestfs_create ();
3714 printf (\"guestfs_create FAILED\\n\");
3718 guestfs_set_error_handler (g, print_error, NULL);
3720 srcdir = getenv (\"srcdir\");
3721 if (!srcdir) srcdir = \".\";
3723 guestfs_set_path (g, \".\");
3725 filename = \"test1.img\";
3726 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
3731 if (lseek (fd, %d, SEEK_SET) == -1) {
3737 if (write (fd, &c, 1) == -1) {
3743 if (close (fd) == -1) {
3748 if (guestfs_add_drive (g, filename) == -1) {
3749 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
3753 filename = \"test2.img\";
3754 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
3759 if (lseek (fd, %d, SEEK_SET) == -1) {
3765 if (write (fd, &c, 1) == -1) {
3771 if (close (fd) == -1) {
3776 if (guestfs_add_drive (g, filename) == -1) {
3777 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
3781 filename = \"test3.img\";
3782 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
3787 if (lseek (fd, %d, SEEK_SET) == -1) {
3793 if (write (fd, &c, 1) == -1) {
3799 if (close (fd) == -1) {
3804 if (guestfs_add_drive (g, filename) == -1) {
3805 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
3809 if (guestfs_launch (g) == -1) {
3810 printf (\"guestfs_launch FAILED\\n\");
3813 if (guestfs_wait_ready (g) == -1) {
3814 printf (\"guestfs_wait_ready FAILED\\n\");
3818 /* Detect if the appliance uses /dev/sd* or /dev/hd* in device
3819 * names. This changed between RHEL 5 and RHEL 6 so we have to
3822 devs = guestfs_list_devices (g);
3823 if (devs == NULL || devs[0] == NULL) {
3824 printf (\"guestfs_list_devices FAILED\\n\");
3827 if (strncmp (devs[0], \"/dev/sd\", 7) == 0)
3829 else if (strncmp (devs[0], \"/dev/hd\", 7) == 0)
3832 printf (\"guestfs_list_devices returned unexpected string '%%s'\\n\",
3836 for (i = 0; devs[i] != NULL; ++i)
3842 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
3846 pr " test_num++;\n";
3847 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
3848 pr " if (%s () == -1) {\n" test_name;
3849 pr " printf (\"%s FAILED\\n\");\n" test_name;
3855 pr " guestfs_close (g);\n";
3856 pr " unlink (\"test1.img\");\n";
3857 pr " unlink (\"test2.img\");\n";
3858 pr " unlink (\"test3.img\");\n";
3861 pr " if (failed > 0) {\n";
3862 pr " printf (\"***** %%d / %%d tests FAILED *****\\n\", failed, nr_tests);\n";
3870 and generate_one_test name i (init, prereq, test) =
3871 let test_name = sprintf "test_%s_%d" name i in
3874 static int %s_skip (void)
3878 str = getenv (\"SKIP_%s\");
3879 if (str && strcmp (str, \"1\") == 0) return 1;
3880 str = getenv (\"SKIP_TEST_%s\");
3881 if (str && strcmp (str, \"1\") == 0) return 1;
3885 " test_name (String.uppercase test_name) (String.uppercase name);
3888 | Disabled | Always -> ()
3889 | If code | Unless code ->
3890 pr "static int %s_prereq (void)\n" test_name;
3898 static int %s (void)
3901 printf (\"%%s skipped (reason: SKIP_TEST_* variable set)\\n\", \"%s\");
3905 " test_name test_name test_name;
3909 pr " printf (\"%%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
3911 pr " if (! %s_prereq ()) {\n" test_name;
3912 pr " printf (\"%%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
3916 generate_one_test_body name i test_name init test;
3918 pr " if (%s_prereq ()) {\n" test_name;
3919 pr " printf (\"%%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
3923 generate_one_test_body name i test_name init test;
3925 generate_one_test_body name i test_name init test
3933 and generate_one_test_body name i test_name init test =
3937 pr " /* InitNone|InitEmpty for %s */\n" test_name;
3938 List.iter (generate_test_command_call test_name)
3939 [["blockdev_setrw"; "/dev/sda"];
3943 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
3944 List.iter (generate_test_command_call test_name)
3945 [["blockdev_setrw"; "/dev/sda"];
3948 ["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
3949 ["mkfs"; "ext2"; "/dev/sda1"];
3950 ["mount"; "/dev/sda1"; "/"]]
3951 | InitBasicFSonLVM ->
3952 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
3954 List.iter (generate_test_command_call test_name)
3955 [["blockdev_setrw"; "/dev/sda"];
3958 ["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
3959 ["pvcreate"; "/dev/sda1"];
3960 ["vgcreate"; "VG"; "/dev/sda1"];
3961 ["lvcreate"; "LV"; "VG"; "8"];
3962 ["mkfs"; "ext2"; "/dev/VG/LV"];
3963 ["mount"; "/dev/VG/LV"; "/"]]
3966 let get_seq_last = function
3968 failwithf "%s: you cannot use [] (empty list) when expecting a command"
3971 let seq = List.rev seq in
3972 List.rev (List.tl seq), List.hd seq
3977 pr " /* TestRun for %s (%d) */\n" name i;
3978 List.iter (generate_test_command_call test_name) seq
3979 | TestOutput (seq, expected) ->
3980 pr " /* TestOutput for %s (%d) */\n" name i;
3981 pr " char expected[] = \"%s\";\n" (c_quote expected);
3982 if String.length expected > 7 &&
3983 String.sub expected 0 7 = "/dev/sd" then
3984 pr " expected[5] = devchar;\n";
3985 let seq, last = get_seq_last seq in
3987 pr " if (strcmp (r, expected) != 0) {\n";
3988 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
3992 List.iter (generate_test_command_call test_name) seq;
3993 generate_test_command_call ~test test_name last
3994 | TestOutputList (seq, expected) ->
3995 pr " /* TestOutputList for %s (%d) */\n" name i;
3996 let seq, last = get_seq_last seq in
4000 pr " if (!r[%d]) {\n" i;
4001 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
4002 pr " print_strings (r);\n";
4006 pr " char expected[] = \"%s\";\n" (c_quote str);
4007 if String.length str > 7 && String.sub str 0 7 = "/dev/sd" then
4008 pr " expected[5] = devchar;\n";
4009 pr " if (strcmp (r[%d], expected) != 0) {\n" i;
4010 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
4015 pr " if (r[%d] != NULL) {\n" (List.length expected);
4016 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
4018 pr " print_strings (r);\n";
4022 List.iter (generate_test_command_call test_name) seq;
4023 generate_test_command_call ~test test_name last
4024 | TestOutputInt (seq, expected) ->
4025 pr " /* TestOutputInt for %s (%d) */\n" name i;
4026 let seq, last = get_seq_last seq in
4028 pr " if (r != %d) {\n" expected;
4029 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
4035 List.iter (generate_test_command_call test_name) seq;
4036 generate_test_command_call ~test test_name last
4037 | TestOutputTrue seq ->
4038 pr " /* TestOutputTrue for %s (%d) */\n" name i;
4039 let seq, last = get_seq_last seq in
4042 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
4047 List.iter (generate_test_command_call test_name) seq;
4048 generate_test_command_call ~test test_name last
4049 | TestOutputFalse seq ->
4050 pr " /* TestOutputFalse for %s (%d) */\n" name i;
4051 let seq, last = get_seq_last seq in
4054 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
4059 List.iter (generate_test_command_call test_name) seq;
4060 generate_test_command_call ~test test_name last
4061 | TestOutputLength (seq, expected) ->
4062 pr " /* TestOutputLength for %s (%d) */\n" name i;
4063 let seq, last = get_seq_last seq in
4066 pr " for (j = 0; j < %d; ++j)\n" expected;
4067 pr " if (r[j] == NULL) {\n";
4068 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
4070 pr " print_strings (r);\n";
4073 pr " if (r[j] != NULL) {\n";
4074 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
4076 pr " print_strings (r);\n";
4080 List.iter (generate_test_command_call test_name) seq;
4081 generate_test_command_call ~test test_name last
4082 | TestOutputStruct (seq, checks) ->
4083 pr " /* TestOutputStruct for %s (%d) */\n" name i;
4084 let seq, last = get_seq_last seq in
4088 | CompareWithInt (field, expected) ->
4089 pr " if (r->%s != %d) {\n" field expected;
4090 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
4091 test_name field expected;
4092 pr " (int) r->%s);\n" field;
4095 | CompareWithString (field, expected) ->
4096 pr " if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
4097 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
4098 test_name field expected;
4099 pr " r->%s);\n" field;
4102 | CompareFieldsIntEq (field1, field2) ->
4103 pr " if (r->%s != r->%s) {\n" field1 field2;
4104 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
4105 test_name field1 field2;
4106 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
4109 | CompareFieldsStrEq (field1, field2) ->
4110 pr " if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
4111 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
4112 test_name field1 field2;
4113 pr " r->%s, r->%s);\n" field1 field2;
4118 List.iter (generate_test_command_call test_name) seq;
4119 generate_test_command_call ~test test_name last
4120 | TestLastFail seq ->
4121 pr " /* TestLastFail for %s (%d) */\n" name i;
4122 let seq, last = get_seq_last seq in
4123 List.iter (generate_test_command_call test_name) seq;
4124 generate_test_command_call test_name ~expect_error:true last
4126 (* Generate the code to run a command, leaving the result in 'r'.
4127 * If you expect to get an error then you should set expect_error:true.
4129 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
4131 | [] -> assert false
4133 (* Look up the command to find out what args/ret it has. *)
4136 let _, style, _, _, _, _, _ =
4137 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
4140 failwithf "%s: in test, command %s was not found" test_name name in
4142 if List.length (snd style) <> List.length args then
4143 failwithf "%s: in test, wrong number of args given to %s"
4150 | OptString n, "NULL" -> ()
4152 | OptString n, arg ->
4153 pr " char %s[] = \"%s\";\n" n (c_quote arg);
4154 if String.length arg > 7 && String.sub arg 0 7 = "/dev/sd" then
4155 pr " %s[5] = devchar;\n" n
4158 | FileIn _, _ | FileOut _, _ -> ()
4159 | StringList n, arg ->
4160 let strs = string_split " " arg in
4163 pr " char %s_%d[] = \"%s\";\n" n i (c_quote str);
4164 if String.length str > 7 && String.sub str 0 7 = "/dev/sd" then
4165 pr " %s_%d[5] = devchar;\n" n i
4167 pr " char *%s[] = {\n" n;
4169 fun i _ -> pr " %s_%d,\n" n i
4173 ) (List.combine (snd style) args);
4176 match fst style with
4177 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
4178 | RInt64 _ -> pr " int64_t r;\n"; "-1"
4179 | RConstString _ -> pr " const char *r;\n"; "NULL"
4180 | RString _ -> pr " char *r;\n"; "NULL"
4181 | RStringList _ | RHashtable _ ->
4186 pr " struct guestfs_int_bool *r;\n"; "NULL"
4188 pr " struct guestfs_lvm_pv_list *r;\n"; "NULL"
4190 pr " struct guestfs_lvm_vg_list *r;\n"; "NULL"
4192 pr " struct guestfs_lvm_lv_list *r;\n"; "NULL"
4194 pr " struct guestfs_stat *r;\n"; "NULL"
4196 pr " struct guestfs_statvfs *r;\n"; "NULL" in
4198 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
4199 pr " r = guestfs_%s (g" name;
4201 (* Generate the parameters. *)
4204 | OptString _, "NULL" -> pr ", NULL"
4208 | FileIn _, arg | FileOut _, arg ->
4209 pr ", \"%s\"" (c_quote arg)
4210 | StringList n, _ ->
4214 try int_of_string arg
4215 with Failure "int_of_string" ->
4216 failwithf "%s: expecting an int, but got '%s'" test_name arg in
4219 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
4220 ) (List.combine (snd style) args);
4223 if not expect_error then
4224 pr " if (r == %s)\n" error_code
4226 pr " if (r != %s)\n" error_code;
4229 (* Insert the test code. *)
4235 (match fst style with
4236 | RErr | RInt _ | RInt64 _ | RBool _ | RConstString _ -> ()
4237 | RString _ -> pr " free (r);\n"
4238 | RStringList _ | RHashtable _ ->
4239 pr " for (i = 0; r[i] != NULL; ++i)\n";
4240 pr " free (r[i]);\n";
4243 pr " guestfs_free_int_bool (r);\n"
4245 pr " guestfs_free_lvm_pv_list (r);\n"
4247 pr " guestfs_free_lvm_vg_list (r);\n"
4249 pr " guestfs_free_lvm_lv_list (r);\n"
4250 | RStat _ | RStatVFS _ ->
4257 let str = replace_str str "\r" "\\r" in
4258 let str = replace_str str "\n" "\\n" in
4259 let str = replace_str str "\t" "\\t" in
4260 let str = replace_str str "\000" "\\0" in
4263 (* Generate a lot of different functions for guestfish. *)
4264 and generate_fish_cmds () =
4265 generate_header CStyle GPLv2;
4269 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
4271 let all_functions_sorted =
4273 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
4274 ) all_functions_sorted in
4276 pr "#include <stdio.h>\n";
4277 pr "#include <stdlib.h>\n";
4278 pr "#include <string.h>\n";
4279 pr "#include <inttypes.h>\n";
4281 pr "#include <guestfs.h>\n";
4282 pr "#include \"fish.h\"\n";
4285 (* list_commands function, which implements guestfish -h *)
4286 pr "void list_commands (void)\n";
4288 pr " printf (\" %%-16s %%s\\n\", \"Command\", \"Description\");\n";
4289 pr " list_builtin_commands ();\n";