3 * Copyright (C) 2009-2010 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 of
25 * 'daemon_functions' below), and daemon/<somefile>.c to write the
28 * After editing this file, run it (./src/generator.ml) to regenerate
29 * all the output files. 'make' will rerun this automatically when
30 * necessary. Note that if you are using a separate build directory
31 * you must run generator.ml from the _source_ directory.
33 * IMPORTANT: This script should NOT print any warnings. If it prints
34 * warnings, you should treat them as errors.
37 * (1) In emacs, install tuareg-mode to display and format OCaml code
38 * correctly. 'vim' comes with a good OCaml editing mode by default.
39 * (2) Read the resources at http://ocaml-tutorial.org/
44 #directory "+xml-light";;
45 #load "xml-light.cma";;
50 type style = ret * args
52 (* "RErr" as a return value means an int used as a simple error
53 * indication, ie. 0 or -1.
57 (* "RInt" as a return value means an int which is -1 for error
58 * or any value >= 0 on success. Only use this for smallish
59 * positive ints (0 <= i < 2^30).
63 (* "RInt64" is the same as RInt, but is guaranteed to be able
64 * to return a full 64 bit value, _except_ that -1 means error
65 * (so -1 cannot be a valid, non-error return value).
69 (* "RBool" is a bool return value which can be true/false or
74 (* "RConstString" is a string that refers to a constant value.
75 * The return value must NOT be NULL (since NULL indicates
78 * Try to avoid using this. In particular you cannot use this
79 * for values returned from the daemon, because there is no
80 * thread-safe way to return them in the C API.
82 | RConstString of string
84 (* "RConstOptString" is an even more broken version of
85 * "RConstString". The returned string may be NULL and there
86 * is no way to return an error indication. Avoid using this!
88 | RConstOptString of string
90 (* "RString" is a returned string. It must NOT be NULL, since
91 * a NULL return indicates an error. The caller frees this.
95 (* "RStringList" is a list of strings. No string in the list
96 * can be NULL. The caller frees the strings and the array.
98 | RStringList of string
100 (* "RStruct" is a function which returns a single named structure
101 * or an error indication (in C, a struct, and in other languages
102 * with varying representations, but usually very efficient). See
103 * after the function list below for the structures.
105 | RStruct of string * string (* name of retval, name of struct *)
107 (* "RStructList" is a function which returns either a list/array
108 * of structures (could be zero-length), or an error indication.
110 | RStructList of string * string (* name of retval, name of struct *)
112 (* Key-value pairs of untyped strings. Turns into a hashtable or
113 * dictionary in languages which support it. DON'T use this as a
114 * general "bucket" for results. Prefer a stronger typed return
115 * value if one is available, or write a custom struct. Don't use
116 * this if the list could potentially be very long, since it is
117 * inefficient. Keys should be unique. NULLs are not permitted.
119 | RHashtable of string
121 (* "RBufferOut" is handled almost exactly like RString, but
122 * it allows the string to contain arbitrary 8 bit data including
123 * ASCII NUL. In the C API this causes an implicit extra parameter
124 * to be added of type <size_t *size_r>. The extra parameter
125 * returns the actual size of the return buffer in bytes.
127 * Other programming languages support strings with arbitrary 8 bit
130 * At the RPC layer we have to use the opaque<> type instead of
131 * string<>. Returned data is still limited to the max message
134 | RBufferOut of string
136 and args = argt list (* Function parameters, guestfs handle is implicit. *)
138 (* Note in future we should allow a "variable args" parameter as
139 * the final parameter, to allow commands like
140 * chmod mode file [file(s)...]
141 * This is not implemented yet, but many commands (such as chmod)
142 * are currently defined with the argument order keeping this future
143 * possibility in mind.
146 | String of string (* const char *name, cannot be NULL *)
147 | Device of string (* /dev device name, cannot be NULL *)
148 | Pathname of string (* file name, cannot be NULL *)
149 | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
150 | OptString of string (* const char *name, may be NULL *)
151 | StringList of string(* list of strings (each string cannot be NULL) *)
152 | DeviceList of string(* list of Device names (each cannot be NULL) *)
153 | Bool of string (* boolean *)
154 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
155 | Int64 of string (* any 64 bit int *)
156 (* These are treated as filenames (simple string parameters) in
157 * the C API and bindings. But in the RPC protocol, we transfer
158 * the actual file content up to or down from the daemon.
159 * FileIn: local machine -> daemon (in request)
160 * FileOut: daemon -> local machine (in reply)
161 * In guestfish (only), the special name "-" means read from
162 * stdin or write to stdout.
167 (* Opaque buffer which can contain arbitrary 8 bit data.
168 * In the C API, this is expressed as <char *, int> pair.
169 * Most other languages have a string type which can contain
170 * ASCII NUL. We use whatever type is appropriate for each
172 * Buffers are limited by the total message size. To transfer
173 * large blocks of data, use FileIn/FileOut parameters instead.
174 * To return an arbitrary buffer, use RBufferOut.
180 | ProtocolLimitWarning (* display warning about protocol size limits *)
181 | DangerWillRobinson (* flags particularly dangerous commands *)
182 | FishAlias of string (* provide an alias for this cmd in guestfish *)
183 | FishAction of string (* call this function in guestfish *)
184 | NotInFish (* do not export via guestfish *)
185 | NotInDocs (* do not add this function to documentation *)
186 | DeprecatedBy of string (* function is deprecated, use .. instead *)
187 | Optional of string (* function is part of an optional group *)
189 (* You can supply zero or as many tests as you want per API call.
191 * Note that the test environment has 3 block devices, of size 500MB,
192 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
193 * a fourth ISO block device with some known files on it (/dev/sdd).
195 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
196 * Number of cylinders was 63 for IDE emulated disks with precisely
197 * the same size. How exactly this is calculated is a mystery.
199 * The ISO block device (/dev/sdd) comes from images/test.iso.
201 * To be able to run the tests in a reasonable amount of time,
202 * the virtual machine and block devices are reused between tests.
203 * So don't try testing kill_subprocess :-x
205 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
207 * Don't assume anything about the previous contents of the block
208 * devices. Use 'Init*' to create some initial scenarios.
210 * You can add a prerequisite clause to any individual test. This
211 * is a run-time check, which, if it fails, causes the test to be
212 * skipped. Useful if testing a command which might not work on
213 * all variations of libguestfs builds. A test that has prerequisite
214 * of 'Always' is run unconditionally.
216 * In addition, packagers can skip individual tests by setting the
217 * environment variables: eg:
218 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
219 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
221 type tests = (test_init * test_prereq * test) list
223 (* Run the command sequence and just expect nothing to fail. *)
226 (* Run the command sequence and expect the output of the final
227 * command to be the string.
229 | TestOutput of seq * string
231 (* Run the command sequence and expect the output of the final
232 * command to be the list of strings.
234 | TestOutputList of seq * string list
236 (* Run the command sequence and expect the output of the final
237 * command to be the list of block devices (could be either
238 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
239 * character of each string).
241 | TestOutputListOfDevices of seq * string list
243 (* Run the command sequence and expect the output of the final
244 * command to be the integer.
246 | TestOutputInt of seq * int
248 (* Run the command sequence and expect the output of the final
249 * command to be <op> <int>, eg. ">=", "1".
251 | TestOutputIntOp of seq * string * int
253 (* Run the command sequence and expect the output of the final
254 * command to be a true value (!= 0 or != NULL).
256 | TestOutputTrue of seq
258 (* Run the command sequence and expect the output of the final
259 * command to be a false value (== 0 or == NULL, but not an error).
261 | TestOutputFalse of seq
263 (* Run the command sequence and expect the output of the final
264 * command to be a list of the given length (but don't care about
267 | TestOutputLength of seq * int
269 (* Run the command sequence and expect the output of the final
270 * command to be a buffer (RBufferOut), ie. string + size.
272 | TestOutputBuffer of seq * string
274 (* Run the command sequence and expect the output of the final
275 * command to be a structure.
277 | TestOutputStruct of seq * test_field_compare list
279 (* Run the command sequence and expect the final command (only)
282 | TestLastFail of seq
284 and test_field_compare =
285 | CompareWithInt of string * int
286 | CompareWithIntOp of string * string * int
287 | CompareWithString of string * string
288 | CompareFieldsIntEq of string * string
289 | CompareFieldsStrEq of string * string
291 (* Test prerequisites. *)
293 (* Test always runs. *)
296 (* Test is currently disabled - eg. it fails, or it tests some
297 * unimplemented feature.
301 (* 'string' is some C code (a function body) that should return
302 * true or false. The test will run if the code returns true.
306 (* As for 'If' but the test runs _unless_ the code returns true. *)
309 (* Some initial scenarios for testing. *)
311 (* Do nothing, block devices could contain random stuff including
312 * LVM PVs, and some filesystems might be mounted. This is usually
317 (* Block devices are empty and no filesystems are mounted. *)
320 (* /dev/sda contains a single partition /dev/sda1, with random
321 * content. /dev/sdb and /dev/sdc may have random content.
326 (* /dev/sda contains a single partition /dev/sda1, which is formatted
327 * as ext2, empty [except for lost+found] and mounted on /.
328 * /dev/sdb and /dev/sdc may have random content.
334 * /dev/sda1 (is a PV):
335 * /dev/VG/LV (size 8MB):
336 * formatted as ext2, empty [except for lost+found], mounted on /
337 * /dev/sdb and /dev/sdc may have random content.
341 (* /dev/sdd (the ISO, see images/ directory in source)
346 (* Sequence of commands for testing. *)
348 and cmd = string list
350 (* Note about long descriptions: When referring to another
351 * action, use the format C<guestfs_other> (ie. the full name of
352 * the C function). This will be replaced as appropriate in other
355 * Apart from that, long descriptions are just perldoc paragraphs.
358 (* Generate a random UUID (used in tests). *)
360 let chan = open_process_in "uuidgen" in
361 let uuid = input_line chan in
362 (match close_process_in chan with
365 failwith "uuidgen: process exited with non-zero status"
366 | WSIGNALED _ | WSTOPPED _ ->
367 failwith "uuidgen: process signalled or stopped by signal"
371 (* These test functions are used in the language binding tests. *)
373 let test_all_args = [
376 StringList "strlist";
384 let test_all_rets = [
385 (* except for RErr, which is tested thoroughly elsewhere *)
386 "test0rint", RInt "valout";
387 "test0rint64", RInt64 "valout";
388 "test0rbool", RBool "valout";
389 "test0rconststring", RConstString "valout";
390 "test0rconstoptstring", RConstOptString "valout";
391 "test0rstring", RString "valout";
392 "test0rstringlist", RStringList "valout";
393 "test0rstruct", RStruct ("valout", "lvm_pv");
394 "test0rstructlist", RStructList ("valout", "lvm_pv");
395 "test0rhashtable", RHashtable "valout";
398 let test_functions = [
399 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
401 "internal test function - do not use",
403 This is an internal test function which is used to test whether
404 the automatically generated bindings can handle every possible
405 parameter type correctly.
407 It echos the contents of each parameter to stdout.
409 You probably don't want to call this function.");
413 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
415 "internal test function - do not use",
417 This is an internal test function which is used to test whether
418 the automatically generated bindings can handle every possible
419 return type correctly.
421 It converts string C<val> to the return type.
423 You probably don't want to call this function.");
424 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
426 "internal test function - do not use",
428 This is an internal test function which is used to test whether
429 the automatically generated bindings can handle every possible
430 return type correctly.
432 This function always returns an error.
434 You probably don't want to call this function.")]
438 (* non_daemon_functions are any functions which don't get processed
439 * in the daemon, eg. functions for setting and getting local
440 * configuration values.
443 let non_daemon_functions = test_functions @ [
444 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
446 "launch the qemu subprocess",
448 Internally libguestfs is implemented by running a virtual machine
451 You should call this after configuring the handle
452 (eg. adding drives) but before performing any actions.");
454 ("wait_ready", (RErr, []), -1, [NotInFish],
456 "wait until the qemu subprocess launches (no op)",
458 This function is a no op.
460 In versions of the API E<lt> 1.0.71 you had to call this function
461 just after calling C<guestfs_launch> to wait for the launch
462 to complete. However this is no longer necessary because
463 C<guestfs_launch> now does the waiting.
465 If you see any calls to this function in code then you can just
466 remove them, unless you want to retain compatibility with older
467 versions of the API.");
469 ("kill_subprocess", (RErr, []), -1, [],
471 "kill the qemu subprocess",
473 This kills the qemu subprocess. You should never need to call this.");
475 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
477 "add an image to examine or modify",
479 This function adds a virtual machine disk image C<filename> to the
480 guest. The first time you call this function, the disk appears as IDE
481 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
484 You don't necessarily need to be root when using libguestfs. However
485 you obviously do need sufficient permissions to access the filename
486 for whatever operations you want to perform (ie. read access if you
487 just want to read the image or write access if you want to modify the
490 This is equivalent to the qemu parameter
491 C<-drive file=filename,cache=off,if=...>.
493 C<cache=off> is omitted in cases where it is not supported by
494 the underlying filesystem.
496 C<if=...> is set at compile time by the configuration option
497 C<./configure --with-drive-if=...>. In the rare case where you
498 might need to change this at run time, use C<guestfs_add_drive_with_if>
499 or C<guestfs_add_drive_ro_with_if>.
501 Note that this call checks for the existence of C<filename>. This
502 stops you from specifying other types of drive which are supported
503 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
504 the general C<guestfs_config> call instead.");
506 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
508 "add a CD-ROM disk image to examine",
510 This function adds a virtual CD-ROM disk image to the guest.
512 This is equivalent to the qemu parameter C<-cdrom filename>.
520 This call checks for the existence of C<filename>. This
521 stops you from specifying other types of drive which are supported
522 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
523 the general C<guestfs_config> call instead.
527 If you just want to add an ISO file (often you use this as an
528 efficient way to transfer large files into the guest), then you
529 should probably use C<guestfs_add_drive_ro> instead.
533 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
535 "add a drive in snapshot mode (read-only)",
537 This adds a drive in snapshot mode, making it effectively
540 Note that writes to the device are allowed, and will be seen for
541 the duration of the guestfs handle, but they are written
542 to a temporary file which is discarded as soon as the guestfs
543 handle is closed. We don't currently have any method to enable
544 changes to be committed, although qemu can support this.
546 This is equivalent to the qemu parameter
547 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
549 C<if=...> is set at compile time by the configuration option
550 C<./configure --with-drive-if=...>. In the rare case where you
551 might need to change this at run time, use C<guestfs_add_drive_with_if>
552 or C<guestfs_add_drive_ro_with_if>.
554 C<readonly=on> is only added where qemu supports this option.
556 Note that this call checks for the existence of C<filename>. This
557 stops you from specifying other types of drive which are supported
558 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
559 the general C<guestfs_config> call instead.");
561 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
563 "add qemu parameters",
565 This can be used to add arbitrary qemu command line parameters
566 of the form C<-param value>. Actually it's not quite arbitrary - we
567 prevent you from setting some parameters which would interfere with
568 parameters that we use.
570 The first character of C<param> string must be a C<-> (dash).
572 C<value> can be NULL.");
574 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
576 "set the qemu binary",
578 Set the qemu binary that we will use.
580 The default is chosen when the library was compiled by the
583 You can also override this by setting the C<LIBGUESTFS_QEMU>
584 environment variable.
586 Setting C<qemu> to C<NULL> restores the default qemu binary.
588 Note that you should call this function as early as possible
589 after creating the handle. This is because some pre-launch
590 operations depend on testing qemu features (by running C<qemu -help>).
591 If the qemu binary changes, we don't retest features, and
592 so you might see inconsistent results. Using the environment
593 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
594 the qemu binary at the same time as the handle is created.");
596 ("get_qemu", (RConstString "qemu", []), -1, [],
597 [InitNone, Always, TestRun (
599 "get the qemu binary",
601 Return the current qemu binary.
603 This is always non-NULL. If it wasn't set already, then this will
604 return the default qemu binary name.");
606 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
608 "set the search path",
610 Set the path that libguestfs searches for kernel and initrd.img.
612 The default is C<$libdir/guestfs> unless overridden by setting
613 C<LIBGUESTFS_PATH> environment variable.
615 Setting C<path> to C<NULL> restores the default path.");
617 ("get_path", (RConstString "path", []), -1, [],
618 [InitNone, Always, TestRun (
620 "get the search path",
622 Return the current search path.
624 This is always non-NULL. If it wasn't set already, then this will
625 return the default path.");
627 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
629 "add options to kernel command line",
631 This function is used to add additional options to the
632 guest kernel command line.
634 The default is C<NULL> unless overridden by setting
635 C<LIBGUESTFS_APPEND> environment variable.
637 Setting C<append> to C<NULL> means I<no> additional options
638 are passed (libguestfs always adds a few of its own).");
640 ("get_append", (RConstOptString "append", []), -1, [],
641 (* This cannot be tested with the current framework. The
642 * function can return NULL in normal operations, which the
643 * test framework interprets as an error.
646 "get the additional kernel options",
648 Return the additional kernel options which are added to the
649 guest kernel command line.
651 If C<NULL> then no options are added.");
653 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
657 If C<autosync> is true, this enables autosync. Libguestfs will make a
658 best effort attempt to run C<guestfs_umount_all> followed by
659 C<guestfs_sync> when the handle is closed
660 (also if the program exits without closing handles).
662 This is disabled by default (except in guestfish where it is
663 enabled by default).");
665 ("get_autosync", (RBool "autosync", []), -1, [],
666 [InitNone, Always, TestRun (
667 [["get_autosync"]])],
670 Get the autosync flag.");
672 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
676 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
678 Verbose messages are disabled unless the environment variable
679 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
681 ("get_verbose", (RBool "verbose", []), -1, [],
685 This returns the verbose messages flag.");
687 ("is_ready", (RBool "ready", []), -1, [],
688 [InitNone, Always, TestOutputTrue (
690 "is ready to accept commands",
692 This returns true iff this handle is ready to accept commands
693 (in the C<READY> state).
695 For more information on states, see L<guestfs(3)>.");
697 ("is_config", (RBool "config", []), -1, [],
698 [InitNone, Always, TestOutputFalse (
700 "is in configuration state",
702 This returns true iff this handle is being configured
703 (in the C<CONFIG> state).
705 For more information on states, see L<guestfs(3)>.");
707 ("is_launching", (RBool "launching", []), -1, [],
708 [InitNone, Always, TestOutputFalse (
709 [["is_launching"]])],
710 "is launching subprocess",
712 This returns true iff this handle is launching the subprocess
713 (in the C<LAUNCHING> state).
715 For more information on states, see L<guestfs(3)>.");
717 ("is_busy", (RBool "busy", []), -1, [],
718 [InitNone, Always, TestOutputFalse (
720 "is busy processing a command",
722 This returns true iff this handle is busy processing a command
723 (in the C<BUSY> state).
725 For more information on states, see L<guestfs(3)>.");
727 ("get_state", (RInt "state", []), -1, [],
729 "get the current state",
731 This returns the current state as an opaque integer. This is
732 only useful for printing debug and internal error messages.
734 For more information on states, see L<guestfs(3)>.");
736 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
737 [InitNone, Always, TestOutputInt (
738 [["set_memsize"; "500"];
739 ["get_memsize"]], 500)],
740 "set memory allocated to the qemu subprocess",
742 This sets the memory size in megabytes allocated to the
743 qemu subprocess. This only has any effect if called before
746 You can also change this by setting the environment
747 variable C<LIBGUESTFS_MEMSIZE> before the handle is
750 For more information on the architecture of libguestfs,
751 see L<guestfs(3)>.");
753 ("get_memsize", (RInt "memsize", []), -1, [],
754 [InitNone, Always, TestOutputIntOp (
755 [["get_memsize"]], ">=", 256)],
756 "get memory allocated to the qemu subprocess",
758 This gets the memory size in megabytes allocated to the
761 If C<guestfs_set_memsize> was not called
762 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
763 then this returns the compiled-in default value for memsize.
765 For more information on the architecture of libguestfs,
766 see L<guestfs(3)>.");
768 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
769 [InitNone, Always, TestOutputIntOp (
770 [["get_pid"]], ">=", 1)],
771 "get PID of qemu subprocess",
773 Return the process ID of the qemu subprocess. If there is no
774 qemu subprocess, then this will return an error.
776 This is an internal call used for debugging and testing.");
778 ("version", (RStruct ("version", "version"), []), -1, [],
779 [InitNone, Always, TestOutputStruct (
780 [["version"]], [CompareWithInt ("major", 1)])],
781 "get the library version number",
783 Return the libguestfs version number that the program is linked
786 Note that because of dynamic linking this is not necessarily
787 the version of libguestfs that you compiled against. You can
788 compile the program, and then at runtime dynamically link
789 against a completely different C<libguestfs.so> library.
791 This call was added in version C<1.0.58>. In previous
792 versions of libguestfs there was no way to get the version
793 number. From C code you can use ELF weak linking tricks to find out if
794 this symbol exists (if it doesn't, then it's an earlier version).
796 The call returns a structure with four elements. The first
797 three (C<major>, C<minor> and C<release>) are numbers and
798 correspond to the usual version triplet. The fourth element
799 (C<extra>) is a string and is normally empty, but may be
800 used for distro-specific information.
802 To construct the original version string:
803 C<$major.$minor.$release$extra>
805 I<Note:> Don't use this call to test for availability
806 of features. Distro backports makes this unreliable. Use
807 C<guestfs_available> instead.");
809 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
810 [InitNone, Always, TestOutputTrue (
811 [["set_selinux"; "true"];
813 "set SELinux enabled or disabled at appliance boot",
815 This sets the selinux flag that is passed to the appliance
816 at boot time. The default is C<selinux=0> (disabled).
818 Note that if SELinux is enabled, it is always in
819 Permissive mode (C<enforcing=0>).
821 For more information on the architecture of libguestfs,
822 see L<guestfs(3)>.");
824 ("get_selinux", (RBool "selinux", []), -1, [],
826 "get SELinux enabled flag",
828 This returns the current setting of the selinux flag which
829 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
831 For more information on the architecture of libguestfs,
832 see L<guestfs(3)>.");
834 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
835 [InitNone, Always, TestOutputFalse (
836 [["set_trace"; "false"];
838 "enable or disable command traces",
840 If the command trace flag is set to 1, then commands are
841 printed on stdout before they are executed in a format
842 which is very similar to the one used by guestfish. In
843 other words, you can run a program with this enabled, and
844 you will get out a script which you can feed to guestfish
845 to perform the same set of actions.
847 If you want to trace C API calls into libguestfs (and
848 other libraries) then possibly a better way is to use
849 the external ltrace(1) command.
851 Command traces are disabled unless the environment variable
852 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
854 ("get_trace", (RBool "trace", []), -1, [],
856 "get command trace enabled flag",
858 Return the command trace flag.");
860 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
861 [InitNone, Always, TestOutputFalse (
862 [["set_direct"; "false"];
864 "enable or disable direct appliance mode",
866 If the direct appliance mode flag is enabled, then stdin and
867 stdout are passed directly through to the appliance once it
870 One consequence of this is that log messages aren't caught
871 by the library and handled by C<guestfs_set_log_message_callback>,
872 but go straight to stdout.
874 You probably don't want to use this unless you know what you
877 The default is disabled.");
879 ("get_direct", (RBool "direct", []), -1, [],
881 "get direct appliance mode flag",
883 Return the direct appliance mode flag.");
885 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
886 [InitNone, Always, TestOutputTrue (
887 [["set_recovery_proc"; "true"];
888 ["get_recovery_proc"]])],
889 "enable or disable the recovery process",
891 If this is called with the parameter C<false> then
892 C<guestfs_launch> does not create a recovery process. The
893 purpose of the recovery process is to stop runaway qemu
894 processes in the case where the main program aborts abruptly.
896 This only has any effect if called before C<guestfs_launch>,
897 and the default is true.
899 About the only time when you would want to disable this is
900 if the main process will fork itself into the background
901 (\"daemonize\" itself). In this case the recovery process
902 thinks that the main program has disappeared and so kills
903 qemu, which is not very helpful.");
905 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
907 "get recovery process enabled flag",
909 Return the recovery process enabled flag.");
911 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
913 "add a drive specifying the QEMU block emulation to use",
915 This is the same as C<guestfs_add_drive> but it allows you
916 to specify the QEMU interface emulation to use at run time.");
918 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
920 "add a drive read-only specifying the QEMU block emulation to use",
922 This is the same as C<guestfs_add_drive_ro> but it allows you
923 to specify the QEMU interface emulation to use at run time.");
927 (* daemon_functions are any functions which cause some action
928 * to take place in the daemon.
931 let daemon_functions = [
932 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
933 [InitEmpty, Always, TestOutput (
934 [["part_disk"; "/dev/sda"; "mbr"];
935 ["mkfs"; "ext2"; "/dev/sda1"];
936 ["mount"; "/dev/sda1"; "/"];
937 ["write_file"; "/new"; "new file contents"; "0"];
938 ["cat"; "/new"]], "new file contents")],
939 "mount a guest disk at a position in the filesystem",
941 Mount a guest disk at a position in the filesystem. Block devices
942 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
943 the guest. If those block devices contain partitions, they will have
944 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
947 The rules are the same as for L<mount(2)>: A filesystem must
948 first be mounted on C</> before others can be mounted. Other
949 filesystems can only be mounted on directories which already
952 The mounted filesystem is writable, if we have sufficient permissions
953 on the underlying device.
955 The filesystem options C<sync> and C<noatime> are set with this
956 call, in order to improve reliability.");
958 ("sync", (RErr, []), 2, [],
959 [ InitEmpty, Always, TestRun [["sync"]]],
960 "sync disks, writes are flushed through to the disk image",
962 This syncs the disk, so that any writes are flushed through to the
963 underlying disk image.
965 You should always call this if you have modified a disk image, before
966 closing the handle.");
968 ("touch", (RErr, [Pathname "path"]), 3, [],
969 [InitBasicFS, Always, TestOutputTrue (
971 ["exists"; "/new"]])],
972 "update file timestamps or create a new file",
974 Touch acts like the L<touch(1)> command. It can be used to
975 update the timestamps on a file, or, if the file does not exist,
976 to create a new zero-length file.");
978 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
979 [InitISOFS, Always, TestOutput (
980 [["cat"; "/known-2"]], "abcdef\n")],
981 "list the contents of a file",
983 Return the contents of the file named C<path>.
985 Note that this function cannot correctly handle binary files
986 (specifically, files containing C<\\0> character which is treated
987 as end of string). For those you need to use the C<guestfs_read_file>
988 or C<guestfs_download> functions which have a more complex interface.");
990 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
991 [], (* XXX Tricky to test because it depends on the exact format
992 * of the 'ls -l' command, which changes between F10 and F11.
994 "list the files in a directory (long format)",
996 List the files in C<directory> (relative to the root directory,
997 there is no cwd) in the format of 'ls -la'.
999 This command is mostly useful for interactive sessions. It
1000 is I<not> intended that you try to parse the output string.");
1002 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1003 [InitBasicFS, Always, TestOutputList (
1005 ["touch"; "/newer"];
1006 ["touch"; "/newest"];
1007 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1008 "list the files in a directory",
1010 List the files in C<directory> (relative to the root directory,
1011 there is no cwd). The '.' and '..' entries are not returned, but
1012 hidden files are shown.
1014 This command is mostly useful for interactive sessions. Programs
1015 should probably use C<guestfs_readdir> instead.");
1017 ("list_devices", (RStringList "devices", []), 7, [],
1018 [InitEmpty, Always, TestOutputListOfDevices (
1019 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1020 "list the block devices",
1022 List all the block devices.
1024 The full block device names are returned, eg. C</dev/sda>");
1026 ("list_partitions", (RStringList "partitions", []), 8, [],
1027 [InitBasicFS, Always, TestOutputListOfDevices (
1028 [["list_partitions"]], ["/dev/sda1"]);
1029 InitEmpty, Always, TestOutputListOfDevices (
1030 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1031 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1032 "list the partitions",
1034 List all the partitions detected on all block devices.
1036 The full partition device names are returned, eg. C</dev/sda1>
1038 This does not return logical volumes. For that you will need to
1039 call C<guestfs_lvs>.");
1041 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1042 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1043 [["pvs"]], ["/dev/sda1"]);
1044 InitEmpty, Always, TestOutputListOfDevices (
1045 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1046 ["pvcreate"; "/dev/sda1"];
1047 ["pvcreate"; "/dev/sda2"];
1048 ["pvcreate"; "/dev/sda3"];
1049 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1050 "list the LVM physical volumes (PVs)",
1052 List all the physical volumes detected. This is the equivalent
1053 of the L<pvs(8)> command.
1055 This returns a list of just the device names that contain
1056 PVs (eg. C</dev/sda2>).
1058 See also C<guestfs_pvs_full>.");
1060 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1061 [InitBasicFSonLVM, Always, TestOutputList (
1063 InitEmpty, Always, TestOutputList (
1064 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1065 ["pvcreate"; "/dev/sda1"];
1066 ["pvcreate"; "/dev/sda2"];
1067 ["pvcreate"; "/dev/sda3"];
1068 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1069 ["vgcreate"; "VG2"; "/dev/sda3"];
1070 ["vgs"]], ["VG1"; "VG2"])],
1071 "list the LVM volume groups (VGs)",
1073 List all the volumes groups detected. This is the equivalent
1074 of the L<vgs(8)> command.
1076 This returns a list of just the volume group names that were
1077 detected (eg. C<VolGroup00>).
1079 See also C<guestfs_vgs_full>.");
1081 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1082 [InitBasicFSonLVM, Always, TestOutputList (
1083 [["lvs"]], ["/dev/VG/LV"]);
1084 InitEmpty, Always, TestOutputList (
1085 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1086 ["pvcreate"; "/dev/sda1"];
1087 ["pvcreate"; "/dev/sda2"];
1088 ["pvcreate"; "/dev/sda3"];
1089 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1090 ["vgcreate"; "VG2"; "/dev/sda3"];
1091 ["lvcreate"; "LV1"; "VG1"; "50"];
1092 ["lvcreate"; "LV2"; "VG1"; "50"];
1093 ["lvcreate"; "LV3"; "VG2"; "50"];
1094 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1095 "list the LVM logical volumes (LVs)",
1097 List all the logical volumes detected. This is the equivalent
1098 of the L<lvs(8)> command.
1100 This returns a list of the logical volume device names
1101 (eg. C</dev/VolGroup00/LogVol00>).
1103 See also C<guestfs_lvs_full>.");
1105 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1106 [], (* XXX how to test? *)
1107 "list the LVM physical volumes (PVs)",
1109 List all the physical volumes detected. This is the equivalent
1110 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1112 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1113 [], (* XXX how to test? *)
1114 "list the LVM volume groups (VGs)",
1116 List all the volumes groups detected. This is the equivalent
1117 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1119 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1120 [], (* XXX how to test? *)
1121 "list the LVM logical volumes (LVs)",
1123 List all the logical volumes detected. This is the equivalent
1124 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1126 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1127 [InitISOFS, Always, TestOutputList (
1128 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1129 InitISOFS, Always, TestOutputList (
1130 [["read_lines"; "/empty"]], [])],
1131 "read file as lines",
1133 Return the contents of the file named C<path>.
1135 The file contents are returned as a list of lines. Trailing
1136 C<LF> and C<CRLF> character sequences are I<not> returned.
1138 Note that this function cannot correctly handle binary files
1139 (specifically, files containing C<\\0> character which is treated
1140 as end of line). For those you need to use the C<guestfs_read_file>
1141 function which has a more complex interface.");
1143 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1144 [], (* XXX Augeas code needs tests. *)
1145 "create a new Augeas handle",
1147 Create a new Augeas handle for editing configuration files.
1148 If there was any previous Augeas handle associated with this
1149 guestfs session, then it is closed.
1151 You must call this before using any other C<guestfs_aug_*>
1154 C<root> is the filesystem root. C<root> must not be NULL,
1157 The flags are the same as the flags defined in
1158 E<lt>augeas.hE<gt>, the logical I<or> of the following
1163 =item C<AUG_SAVE_BACKUP> = 1
1165 Keep the original file with a C<.augsave> extension.
1167 =item C<AUG_SAVE_NEWFILE> = 2
1169 Save changes into a file with extension C<.augnew>, and
1170 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1172 =item C<AUG_TYPE_CHECK> = 4
1174 Typecheck lenses (can be expensive).
1176 =item C<AUG_NO_STDINC> = 8
1178 Do not use standard load path for modules.
1180 =item C<AUG_SAVE_NOOP> = 16
1182 Make save a no-op, just record what would have been changed.
1184 =item C<AUG_NO_LOAD> = 32
1186 Do not load the tree in C<guestfs_aug_init>.
1190 To close the handle, you can call C<guestfs_aug_close>.
1192 To find out more about Augeas, see L<http://augeas.net/>.");
1194 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1195 [], (* XXX Augeas code needs tests. *)
1196 "close the current Augeas handle",
1198 Close the current Augeas handle and free up any resources
1199 used by it. After calling this, you have to call
1200 C<guestfs_aug_init> again before you can use any other
1201 Augeas functions.");
1203 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1204 [], (* XXX Augeas code needs tests. *)
1205 "define an Augeas variable",
1207 Defines an Augeas variable C<name> whose value is the result
1208 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1211 On success this returns the number of nodes in C<expr>, or
1212 C<0> if C<expr> evaluates to something which is not a nodeset.");
1214 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1215 [], (* XXX Augeas code needs tests. *)
1216 "define an Augeas node",
1218 Defines a variable C<name> whose value is the result of
1221 If C<expr> evaluates to an empty nodeset, a node is created,
1222 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1223 C<name> will be the nodeset containing that single node.
1225 On success this returns a pair containing the
1226 number of nodes in the nodeset, and a boolean flag
1227 if a node was created.");
1229 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1230 [], (* XXX Augeas code needs tests. *)
1231 "look up the value of an Augeas path",
1233 Look up the value associated with C<path>. If C<path>
1234 matches exactly one node, the C<value> is returned.");
1236 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1237 [], (* XXX Augeas code needs tests. *)
1238 "set Augeas path to value",
1240 Set the value associated with C<path> to C<value>.");
1242 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1243 [], (* XXX Augeas code needs tests. *)
1244 "insert a sibling Augeas node",
1246 Create a new sibling C<label> for C<path>, inserting it into
1247 the tree before or after C<path> (depending on the boolean
1250 C<path> must match exactly one existing node in the tree, and
1251 C<label> must be a label, ie. not contain C</>, C<*> or end
1252 with a bracketed index C<[N]>.");
1254 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1255 [], (* XXX Augeas code needs tests. *)
1256 "remove an Augeas path",
1258 Remove C<path> and all of its children.
1260 On success this returns the number of entries which were removed.");
1262 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1263 [], (* XXX Augeas code needs tests. *)
1266 Move the node C<src> to C<dest>. C<src> must match exactly
1267 one node. C<dest> is overwritten if it exists.");
1269 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1270 [], (* XXX Augeas code needs tests. *)
1271 "return Augeas nodes which match augpath",
1273 Returns a list of paths which match the path expression C<path>.
1274 The returned paths are sufficiently qualified so that they match
1275 exactly one node in the current tree.");
1277 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1278 [], (* XXX Augeas code needs tests. *)
1279 "write all pending Augeas changes to disk",
1281 This writes all pending changes to disk.
1283 The flags which were passed to C<guestfs_aug_init> affect exactly
1284 how files are saved.");
1286 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1287 [], (* XXX Augeas code needs tests. *)
1288 "load files into the tree",
1290 Load files into the tree.
1292 See C<aug_load> in the Augeas documentation for the full gory
1295 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1296 [], (* XXX Augeas code needs tests. *)
1297 "list Augeas nodes under augpath",
1299 This is just a shortcut for listing C<guestfs_aug_match>
1300 C<path/*> and sorting the resulting nodes into alphabetical order.");
1302 ("rm", (RErr, [Pathname "path"]), 29, [],
1303 [InitBasicFS, Always, TestRun
1306 InitBasicFS, Always, TestLastFail
1308 InitBasicFS, Always, TestLastFail
1313 Remove the single file C<path>.");
1315 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1316 [InitBasicFS, Always, TestRun
1319 InitBasicFS, Always, TestLastFail
1320 [["rmdir"; "/new"]];
1321 InitBasicFS, Always, TestLastFail
1323 ["rmdir"; "/new"]]],
1324 "remove a directory",
1326 Remove the single directory C<path>.");
1328 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1329 [InitBasicFS, Always, TestOutputFalse
1331 ["mkdir"; "/new/foo"];
1332 ["touch"; "/new/foo/bar"];
1334 ["exists"; "/new"]]],
1335 "remove a file or directory recursively",
1337 Remove the file or directory C<path>, recursively removing the
1338 contents if its a directory. This is like the C<rm -rf> shell
1341 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1342 [InitBasicFS, Always, TestOutputTrue
1344 ["is_dir"; "/new"]];
1345 InitBasicFS, Always, TestLastFail
1346 [["mkdir"; "/new/foo/bar"]]],
1347 "create a directory",
1349 Create a directory named C<path>.");
1351 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1352 [InitBasicFS, Always, TestOutputTrue
1353 [["mkdir_p"; "/new/foo/bar"];
1354 ["is_dir"; "/new/foo/bar"]];
1355 InitBasicFS, Always, TestOutputTrue
1356 [["mkdir_p"; "/new/foo/bar"];
1357 ["is_dir"; "/new/foo"]];
1358 InitBasicFS, Always, TestOutputTrue
1359 [["mkdir_p"; "/new/foo/bar"];
1360 ["is_dir"; "/new"]];
1361 (* Regression tests for RHBZ#503133: *)
1362 InitBasicFS, Always, TestRun
1364 ["mkdir_p"; "/new"]];
1365 InitBasicFS, Always, TestLastFail
1367 ["mkdir_p"; "/new"]]],
1368 "create a directory and parents",
1370 Create a directory named C<path>, creating any parent directories
1371 as necessary. This is like the C<mkdir -p> shell command.");
1373 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1374 [], (* XXX Need stat command to test *)
1377 Change the mode (permissions) of C<path> to C<mode>. Only
1378 numeric modes are supported.
1380 I<Note>: When using this command from guestfish, C<mode>
1381 by default would be decimal, unless you prefix it with
1382 C<0> to get octal, ie. use C<0700> not C<700>.");
1384 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1385 [], (* XXX Need stat command to test *)
1386 "change file owner and group",
1388 Change the file owner to C<owner> and group to C<group>.
1390 Only numeric uid and gid are supported. If you want to use
1391 names, you will need to locate and parse the password file
1392 yourself (Augeas support makes this relatively easy).");
1394 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1395 [InitISOFS, Always, TestOutputTrue (
1396 [["exists"; "/empty"]]);
1397 InitISOFS, Always, TestOutputTrue (
1398 [["exists"; "/directory"]])],
1399 "test if file or directory exists",
1401 This returns C<true> if and only if there is a file, directory
1402 (or anything) with the given C<path> name.
1404 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1406 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1407 [InitISOFS, Always, TestOutputTrue (
1408 [["is_file"; "/known-1"]]);
1409 InitISOFS, Always, TestOutputFalse (
1410 [["is_file"; "/directory"]])],
1411 "test if file exists",
1413 This returns C<true> if and only if there is a file
1414 with the given C<path> name. Note that it returns false for
1415 other objects like directories.
1417 See also C<guestfs_stat>.");
1419 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1420 [InitISOFS, Always, TestOutputFalse (
1421 [["is_dir"; "/known-3"]]);
1422 InitISOFS, Always, TestOutputTrue (
1423 [["is_dir"; "/directory"]])],
1424 "test if file exists",
1426 This returns C<true> if and only if there is a directory
1427 with the given C<path> name. Note that it returns false for
1428 other objects like files.
1430 See also C<guestfs_stat>.");
1432 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1433 [InitEmpty, Always, TestOutputListOfDevices (
1434 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1435 ["pvcreate"; "/dev/sda1"];
1436 ["pvcreate"; "/dev/sda2"];
1437 ["pvcreate"; "/dev/sda3"];
1438 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1439 "create an LVM physical volume",
1441 This creates an LVM physical volume on the named C<device>,
1442 where C<device> should usually be a partition name such
1445 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1446 [InitEmpty, Always, TestOutputList (
1447 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1448 ["pvcreate"; "/dev/sda1"];
1449 ["pvcreate"; "/dev/sda2"];
1450 ["pvcreate"; "/dev/sda3"];
1451 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1452 ["vgcreate"; "VG2"; "/dev/sda3"];
1453 ["vgs"]], ["VG1"; "VG2"])],
1454 "create an LVM volume group",
1456 This creates an LVM volume group called C<volgroup>
1457 from the non-empty list of physical volumes C<physvols>.");
1459 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1460 [InitEmpty, Always, TestOutputList (
1461 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1462 ["pvcreate"; "/dev/sda1"];
1463 ["pvcreate"; "/dev/sda2"];
1464 ["pvcreate"; "/dev/sda3"];
1465 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1466 ["vgcreate"; "VG2"; "/dev/sda3"];
1467 ["lvcreate"; "LV1"; "VG1"; "50"];
1468 ["lvcreate"; "LV2"; "VG1"; "50"];
1469 ["lvcreate"; "LV3"; "VG2"; "50"];
1470 ["lvcreate"; "LV4"; "VG2"; "50"];
1471 ["lvcreate"; "LV5"; "VG2"; "50"];
1473 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1474 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1475 "create an LVM volume group",
1477 This creates an LVM volume group called C<logvol>
1478 on the volume group C<volgroup>, with C<size> megabytes.");
1480 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1481 [InitEmpty, Always, TestOutput (
1482 [["part_disk"; "/dev/sda"; "mbr"];
1483 ["mkfs"; "ext2"; "/dev/sda1"];
1484 ["mount_options"; ""; "/dev/sda1"; "/"];
1485 ["write_file"; "/new"; "new file contents"; "0"];
1486 ["cat"; "/new"]], "new file contents")],
1487 "make a filesystem",
1489 This creates a filesystem on C<device> (usually a partition
1490 or LVM logical volume). The filesystem type is C<fstype>, for
1493 ("sfdisk", (RErr, [Device "device";
1494 Int "cyls"; Int "heads"; Int "sectors";
1495 StringList "lines"]), 43, [DangerWillRobinson],
1497 "create partitions on a block device",
1499 This is a direct interface to the L<sfdisk(8)> program for creating
1500 partitions on block devices.
1502 C<device> should be a block device, for example C</dev/sda>.
1504 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1505 and sectors on the device, which are passed directly to sfdisk as
1506 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1507 of these, then the corresponding parameter is omitted. Usually for
1508 'large' disks, you can just pass C<0> for these, but for small
1509 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1510 out the right geometry and you will need to tell it.
1512 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1513 information refer to the L<sfdisk(8)> manpage.
1515 To create a single partition occupying the whole disk, you would
1516 pass C<lines> as a single element list, when the single element being
1517 the string C<,> (comma).
1519 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1520 C<guestfs_part_init>");
1522 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1523 [InitBasicFS, Always, TestOutput (
1524 [["write_file"; "/new"; "new file contents"; "0"];
1525 ["cat"; "/new"]], "new file contents");
1526 InitBasicFS, Always, TestOutput (
1527 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1528 ["cat"; "/new"]], "\nnew file contents\n");
1529 InitBasicFS, Always, TestOutput (
1530 [["write_file"; "/new"; "\n\n"; "0"];
1531 ["cat"; "/new"]], "\n\n");
1532 InitBasicFS, Always, TestOutput (
1533 [["write_file"; "/new"; ""; "0"];
1534 ["cat"; "/new"]], "");
1535 InitBasicFS, Always, TestOutput (
1536 [["write_file"; "/new"; "\n\n\n"; "0"];
1537 ["cat"; "/new"]], "\n\n\n");
1538 InitBasicFS, Always, TestOutput (
1539 [["write_file"; "/new"; "\n"; "0"];
1540 ["cat"; "/new"]], "\n")],
1543 This call creates a file called C<path>. The contents of the
1544 file is the string C<content> (which can contain any 8 bit data),
1545 with length C<size>.
1547 As a special case, if C<size> is C<0>
1548 then the length is calculated using C<strlen> (so in this case
1549 the content cannot contain embedded ASCII NULs).
1551 I<NB.> Owing to a bug, writing content containing ASCII NUL
1552 characters does I<not> work, even if the length is specified.
1553 We hope to resolve this bug in a future version. In the meantime
1554 use C<guestfs_upload>.");
1556 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1557 [InitEmpty, Always, TestOutputListOfDevices (
1558 [["part_disk"; "/dev/sda"; "mbr"];
1559 ["mkfs"; "ext2"; "/dev/sda1"];
1560 ["mount_options"; ""; "/dev/sda1"; "/"];
1561 ["mounts"]], ["/dev/sda1"]);
1562 InitEmpty, Always, TestOutputList (
1563 [["part_disk"; "/dev/sda"; "mbr"];
1564 ["mkfs"; "ext2"; "/dev/sda1"];
1565 ["mount_options"; ""; "/dev/sda1"; "/"];
1568 "unmount a filesystem",
1570 This unmounts the given filesystem. The filesystem may be
1571 specified either by its mountpoint (path) or the device which
1572 contains the filesystem.");
1574 ("mounts", (RStringList "devices", []), 46, [],
1575 [InitBasicFS, Always, TestOutputListOfDevices (
1576 [["mounts"]], ["/dev/sda1"])],
1577 "show mounted filesystems",
1579 This returns the list of currently mounted filesystems. It returns
1580 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1582 Some internal mounts are not shown.
1584 See also: C<guestfs_mountpoints>");
1586 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1587 [InitBasicFS, Always, TestOutputList (
1590 (* check that umount_all can unmount nested mounts correctly: *)
1591 InitEmpty, Always, TestOutputList (
1592 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1593 ["mkfs"; "ext2"; "/dev/sda1"];
1594 ["mkfs"; "ext2"; "/dev/sda2"];
1595 ["mkfs"; "ext2"; "/dev/sda3"];
1596 ["mount_options"; ""; "/dev/sda1"; "/"];
1598 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1599 ["mkdir"; "/mp1/mp2"];
1600 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1601 ["mkdir"; "/mp1/mp2/mp3"];
1604 "unmount all filesystems",
1606 This unmounts all mounted filesystems.
1608 Some internal mounts are not unmounted by this call.");
1610 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1612 "remove all LVM LVs, VGs and PVs",
1614 This command removes all LVM logical volumes, volume groups
1615 and physical volumes.");
1617 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1618 [InitISOFS, Always, TestOutput (
1619 [["file"; "/empty"]], "empty");
1620 InitISOFS, Always, TestOutput (
1621 [["file"; "/known-1"]], "ASCII text");
1622 InitISOFS, Always, TestLastFail (
1623 [["file"; "/notexists"]])],
1624 "determine file type",
1626 This call uses the standard L<file(1)> command to determine
1627 the type or contents of the file. This also works on devices,
1628 for example to find out whether a partition contains a filesystem.
1630 This call will also transparently look inside various types
1633 The exact command which runs is C<file -zbsL path>. Note in
1634 particular that the filename is not prepended to the output
1635 (the C<-b> option).");
1637 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1638 [InitBasicFS, Always, TestOutput (
1639 [["upload"; "test-command"; "/test-command"];
1640 ["chmod"; "0o755"; "/test-command"];
1641 ["command"; "/test-command 1"]], "Result1");
1642 InitBasicFS, Always, TestOutput (
1643 [["upload"; "test-command"; "/test-command"];
1644 ["chmod"; "0o755"; "/test-command"];
1645 ["command"; "/test-command 2"]], "Result2\n");
1646 InitBasicFS, Always, TestOutput (
1647 [["upload"; "test-command"; "/test-command"];
1648 ["chmod"; "0o755"; "/test-command"];
1649 ["command"; "/test-command 3"]], "\nResult3");
1650 InitBasicFS, Always, TestOutput (
1651 [["upload"; "test-command"; "/test-command"];
1652 ["chmod"; "0o755"; "/test-command"];
1653 ["command"; "/test-command 4"]], "\nResult4\n");
1654 InitBasicFS, Always, TestOutput (
1655 [["upload"; "test-command"; "/test-command"];
1656 ["chmod"; "0o755"; "/test-command"];
1657 ["command"; "/test-command 5"]], "\nResult5\n\n");
1658 InitBasicFS, Always, TestOutput (
1659 [["upload"; "test-command"; "/test-command"];
1660 ["chmod"; "0o755"; "/test-command"];
1661 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1662 InitBasicFS, Always, TestOutput (
1663 [["upload"; "test-command"; "/test-command"];
1664 ["chmod"; "0o755"; "/test-command"];
1665 ["command"; "/test-command 7"]], "");
1666 InitBasicFS, Always, TestOutput (
1667 [["upload"; "test-command"; "/test-command"];
1668 ["chmod"; "0o755"; "/test-command"];
1669 ["command"; "/test-command 8"]], "\n");
1670 InitBasicFS, Always, TestOutput (
1671 [["upload"; "test-command"; "/test-command"];
1672 ["chmod"; "0o755"; "/test-command"];
1673 ["command"; "/test-command 9"]], "\n\n");
1674 InitBasicFS, Always, TestOutput (
1675 [["upload"; "test-command"; "/test-command"];
1676 ["chmod"; "0o755"; "/test-command"];
1677 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1678 InitBasicFS, Always, TestOutput (
1679 [["upload"; "test-command"; "/test-command"];
1680 ["chmod"; "0o755"; "/test-command"];
1681 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1682 InitBasicFS, Always, TestLastFail (
1683 [["upload"; "test-command"; "/test-command"];
1684 ["chmod"; "0o755"; "/test-command"];
1685 ["command"; "/test-command"]])],
1686 "run a command from the guest filesystem",
1688 This call runs a command from the guest filesystem. The
1689 filesystem must be mounted, and must contain a compatible
1690 operating system (ie. something Linux, with the same
1691 or compatible processor architecture).
1693 The single parameter is an argv-style list of arguments.
1694 The first element is the name of the program to run.
1695 Subsequent elements are parameters. The list must be
1696 non-empty (ie. must contain a program name). Note that
1697 the command runs directly, and is I<not> invoked via
1698 the shell (see C<guestfs_sh>).
1700 The return value is anything printed to I<stdout> by
1703 If the command returns a non-zero exit status, then
1704 this function returns an error message. The error message
1705 string is the content of I<stderr> from the command.
1707 The C<$PATH> environment variable will contain at least
1708 C</usr/bin> and C</bin>. If you require a program from
1709 another location, you should provide the full path in the
1712 Shared libraries and data files required by the program
1713 must be available on filesystems which are mounted in the
1714 correct places. It is the caller's responsibility to ensure
1715 all filesystems that are needed are mounted at the right
1718 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1719 [InitBasicFS, Always, TestOutputList (
1720 [["upload"; "test-command"; "/test-command"];
1721 ["chmod"; "0o755"; "/test-command"];
1722 ["command_lines"; "/test-command 1"]], ["Result1"]);
1723 InitBasicFS, Always, TestOutputList (
1724 [["upload"; "test-command"; "/test-command"];
1725 ["chmod"; "0o755"; "/test-command"];
1726 ["command_lines"; "/test-command 2"]], ["Result2"]);
1727 InitBasicFS, Always, TestOutputList (
1728 [["upload"; "test-command"; "/test-command"];
1729 ["chmod"; "0o755"; "/test-command"];
1730 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1731 InitBasicFS, Always, TestOutputList (
1732 [["upload"; "test-command"; "/test-command"];
1733 ["chmod"; "0o755"; "/test-command"];
1734 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1735 InitBasicFS, Always, TestOutputList (
1736 [["upload"; "test-command"; "/test-command"];
1737 ["chmod"; "0o755"; "/test-command"];
1738 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1739 InitBasicFS, Always, TestOutputList (
1740 [["upload"; "test-command"; "/test-command"];
1741 ["chmod"; "0o755"; "/test-command"];
1742 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1743 InitBasicFS, Always, TestOutputList (
1744 [["upload"; "test-command"; "/test-command"];
1745 ["chmod"; "0o755"; "/test-command"];
1746 ["command_lines"; "/test-command 7"]], []);
1747 InitBasicFS, Always, TestOutputList (
1748 [["upload"; "test-command"; "/test-command"];
1749 ["chmod"; "0o755"; "/test-command"];
1750 ["command_lines"; "/test-command 8"]], [""]);
1751 InitBasicFS, Always, TestOutputList (
1752 [["upload"; "test-command"; "/test-command"];
1753 ["chmod"; "0o755"; "/test-command"];
1754 ["command_lines"; "/test-command 9"]], ["";""]);
1755 InitBasicFS, Always, TestOutputList (
1756 [["upload"; "test-command"; "/test-command"];
1757 ["chmod"; "0o755"; "/test-command"];
1758 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1759 InitBasicFS, Always, TestOutputList (
1760 [["upload"; "test-command"; "/test-command"];
1761 ["chmod"; "0o755"; "/test-command"];
1762 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1763 "run a command, returning lines",
1765 This is the same as C<guestfs_command>, but splits the
1766 result into a list of lines.
1768 See also: C<guestfs_sh_lines>");
1770 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1771 [InitISOFS, Always, TestOutputStruct (
1772 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1773 "get file information",
1775 Returns file information for the given C<path>.
1777 This is the same as the C<stat(2)> system call.");
1779 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1780 [InitISOFS, Always, TestOutputStruct (
1781 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1782 "get file information for a symbolic link",
1784 Returns file information for the given C<path>.
1786 This is the same as C<guestfs_stat> except that if C<path>
1787 is a symbolic link, then the link is stat-ed, not the file it
1790 This is the same as the C<lstat(2)> system call.");
1792 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1793 [InitISOFS, Always, TestOutputStruct (
1794 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1795 "get file system statistics",
1797 Returns file system statistics for any mounted file system.
1798 C<path> should be a file or directory in the mounted file system
1799 (typically it is the mount point itself, but it doesn't need to be).
1801 This is the same as the C<statvfs(2)> system call.");
1803 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1805 "get ext2/ext3/ext4 superblock details",
1807 This returns the contents of the ext2, ext3 or ext4 filesystem
1808 superblock on C<device>.
1810 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1811 manpage for more details. The list of fields returned isn't
1812 clearly defined, and depends on both the version of C<tune2fs>
1813 that libguestfs was built against, and the filesystem itself.");
1815 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1816 [InitEmpty, Always, TestOutputTrue (
1817 [["blockdev_setro"; "/dev/sda"];
1818 ["blockdev_getro"; "/dev/sda"]])],
1819 "set block device to read-only",
1821 Sets the block device named C<device> to read-only.
1823 This uses the L<blockdev(8)> command.");
1825 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1826 [InitEmpty, Always, TestOutputFalse (
1827 [["blockdev_setrw"; "/dev/sda"];
1828 ["blockdev_getro"; "/dev/sda"]])],
1829 "set block device to read-write",
1831 Sets the block device named C<device> to read-write.
1833 This uses the L<blockdev(8)> command.");
1835 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1836 [InitEmpty, Always, TestOutputTrue (
1837 [["blockdev_setro"; "/dev/sda"];
1838 ["blockdev_getro"; "/dev/sda"]])],
1839 "is block device set to read-only",
1841 Returns a boolean indicating if the block device is read-only
1842 (true if read-only, false if not).
1844 This uses the L<blockdev(8)> command.");
1846 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1847 [InitEmpty, Always, TestOutputInt (
1848 [["blockdev_getss"; "/dev/sda"]], 512)],
1849 "get sectorsize of block device",
1851 This returns the size of sectors on a block device.
1852 Usually 512, but can be larger for modern devices.
1854 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1857 This uses the L<blockdev(8)> command.");
1859 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1860 [InitEmpty, Always, TestOutputInt (
1861 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1862 "get blocksize of block device",
1864 This returns the block size of a device.
1866 (Note this is different from both I<size in blocks> and
1867 I<filesystem block size>).
1869 This uses the L<blockdev(8)> command.");
1871 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1873 "set blocksize of block device",
1875 This sets the block size of a device.
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1880 This uses the L<blockdev(8)> command.");
1882 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1883 [InitEmpty, Always, TestOutputInt (
1884 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1885 "get total size of device in 512-byte sectors",
1887 This returns the size of the device in units of 512-byte sectors
1888 (even if the sectorsize isn't 512 bytes ... weird).
1890 See also C<guestfs_blockdev_getss> for the real sector size of
1891 the device, and C<guestfs_blockdev_getsize64> for the more
1892 useful I<size in bytes>.
1894 This uses the L<blockdev(8)> command.");
1896 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1897 [InitEmpty, Always, TestOutputInt (
1898 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1899 "get total size of device in bytes",
1901 This returns the size of the device in bytes.
1903 See also C<guestfs_blockdev_getsz>.
1905 This uses the L<blockdev(8)> command.");
1907 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1908 [InitEmpty, Always, TestRun
1909 [["blockdev_flushbufs"; "/dev/sda"]]],
1910 "flush device buffers",
1912 This tells the kernel to flush internal buffers associated
1915 This uses the L<blockdev(8)> command.");
1917 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1918 [InitEmpty, Always, TestRun
1919 [["blockdev_rereadpt"; "/dev/sda"]]],
1920 "reread partition table",
1922 Reread the partition table on C<device>.
1924 This uses the L<blockdev(8)> command.");
1926 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1927 [InitBasicFS, Always, TestOutput (
1928 (* Pick a file from cwd which isn't likely to change. *)
1929 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1930 ["checksum"; "md5"; "/COPYING.LIB"]],
1931 Digest.to_hex (Digest.file "COPYING.LIB"))],
1932 "upload a file from the local machine",
1934 Upload local file C<filename> to C<remotefilename> on the
1937 C<filename> can also be a named pipe.
1939 See also C<guestfs_download>.");
1941 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1942 [InitBasicFS, Always, TestOutput (
1943 (* Pick a file from cwd which isn't likely to change. *)
1944 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1945 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1946 ["upload"; "testdownload.tmp"; "/upload"];
1947 ["checksum"; "md5"; "/upload"]],
1948 Digest.to_hex (Digest.file "COPYING.LIB"))],
1949 "download a file to the local machine",
1951 Download file C<remotefilename> and save it as C<filename>
1952 on the local machine.
1954 C<filename> can also be a named pipe.
1956 See also C<guestfs_upload>, C<guestfs_cat>.");
1958 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1959 [InitISOFS, Always, TestOutput (
1960 [["checksum"; "crc"; "/known-3"]], "2891671662");
1961 InitISOFS, Always, TestLastFail (
1962 [["checksum"; "crc"; "/notexists"]]);
1963 InitISOFS, Always, TestOutput (
1964 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1965 InitISOFS, Always, TestOutput (
1966 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1967 InitISOFS, Always, TestOutput (
1968 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1969 InitISOFS, Always, TestOutput (
1970 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1971 InitISOFS, Always, TestOutput (
1972 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1973 InitISOFS, Always, TestOutput (
1974 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1975 "compute MD5, SHAx or CRC checksum of file",
1977 This call computes the MD5, SHAx or CRC checksum of the
1980 The type of checksum to compute is given by the C<csumtype>
1981 parameter which must have one of the following values:
1987 Compute the cyclic redundancy check (CRC) specified by POSIX
1988 for the C<cksum> command.
1992 Compute the MD5 hash (using the C<md5sum> program).
1996 Compute the SHA1 hash (using the C<sha1sum> program).
2000 Compute the SHA224 hash (using the C<sha224sum> program).
2004 Compute the SHA256 hash (using the C<sha256sum> program).
2008 Compute the SHA384 hash (using the C<sha384sum> program).
2012 Compute the SHA512 hash (using the C<sha512sum> program).
2016 The checksum is returned as a printable string.");
2018 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2019 [InitBasicFS, Always, TestOutput (
2020 [["tar_in"; "../images/helloworld.tar"; "/"];
2021 ["cat"; "/hello"]], "hello\n")],
2022 "unpack tarfile to directory",
2024 This command uploads and unpacks local file C<tarfile> (an
2025 I<uncompressed> tar file) into C<directory>.
2027 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2029 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2031 "pack directory into tarfile",
2033 This command packs the contents of C<directory> and downloads
2034 it to local file C<tarfile>.
2036 To download a compressed tarball, use C<guestfs_tgz_out>.");
2038 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2039 [InitBasicFS, Always, TestOutput (
2040 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2041 ["cat"; "/hello"]], "hello\n")],
2042 "unpack compressed tarball to directory",
2044 This command uploads and unpacks local file C<tarball> (a
2045 I<gzip compressed> tar file) into C<directory>.
2047 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2049 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2051 "pack directory into compressed tarball",
2053 This command packs the contents of C<directory> and downloads
2054 it to local file C<tarball>.
2056 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2058 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2059 [InitBasicFS, Always, TestLastFail (
2061 ["mount_ro"; "/dev/sda1"; "/"];
2062 ["touch"; "/new"]]);
2063 InitBasicFS, Always, TestOutput (
2064 [["write_file"; "/new"; "data"; "0"];
2066 ["mount_ro"; "/dev/sda1"; "/"];
2067 ["cat"; "/new"]], "data")],
2068 "mount a guest disk, read-only",
2070 This is the same as the C<guestfs_mount> command, but it
2071 mounts the filesystem with the read-only (I<-o ro>) flag.");
2073 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2075 "mount a guest disk with mount options",
2077 This is the same as the C<guestfs_mount> command, but it
2078 allows you to set the mount options as for the
2079 L<mount(8)> I<-o> flag.");
2081 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2083 "mount a guest disk with mount options and vfstype",
2085 This is the same as the C<guestfs_mount> command, but it
2086 allows you to set both the mount options and the vfstype
2087 as for the L<mount(8)> I<-o> and I<-t> flags.");
2089 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2091 "debugging and internals",
2093 The C<guestfs_debug> command exposes some internals of
2094 C<guestfsd> (the guestfs daemon) that runs inside the
2097 There is no comprehensive help for this command. You have
2098 to look at the file C<daemon/debug.c> in the libguestfs source
2099 to find out what you can do.");
2101 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2102 [InitEmpty, Always, TestOutputList (
2103 [["part_disk"; "/dev/sda"; "mbr"];
2104 ["pvcreate"; "/dev/sda1"];
2105 ["vgcreate"; "VG"; "/dev/sda1"];
2106 ["lvcreate"; "LV1"; "VG"; "50"];
2107 ["lvcreate"; "LV2"; "VG"; "50"];
2108 ["lvremove"; "/dev/VG/LV1"];
2109 ["lvs"]], ["/dev/VG/LV2"]);
2110 InitEmpty, Always, TestOutputList (
2111 [["part_disk"; "/dev/sda"; "mbr"];
2112 ["pvcreate"; "/dev/sda1"];
2113 ["vgcreate"; "VG"; "/dev/sda1"];
2114 ["lvcreate"; "LV1"; "VG"; "50"];
2115 ["lvcreate"; "LV2"; "VG"; "50"];
2116 ["lvremove"; "/dev/VG"];
2118 InitEmpty, Always, TestOutputList (
2119 [["part_disk"; "/dev/sda"; "mbr"];
2120 ["pvcreate"; "/dev/sda1"];
2121 ["vgcreate"; "VG"; "/dev/sda1"];
2122 ["lvcreate"; "LV1"; "VG"; "50"];
2123 ["lvcreate"; "LV2"; "VG"; "50"];
2124 ["lvremove"; "/dev/VG"];
2126 "remove an LVM logical volume",
2128 Remove an LVM logical volume C<device>, where C<device> is
2129 the path to the LV, such as C</dev/VG/LV>.
2131 You can also remove all LVs in a volume group by specifying
2132 the VG name, C</dev/VG>.");
2134 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2135 [InitEmpty, Always, TestOutputList (
2136 [["part_disk"; "/dev/sda"; "mbr"];
2137 ["pvcreate"; "/dev/sda1"];
2138 ["vgcreate"; "VG"; "/dev/sda1"];
2139 ["lvcreate"; "LV1"; "VG"; "50"];
2140 ["lvcreate"; "LV2"; "VG"; "50"];
2143 InitEmpty, Always, TestOutputList (
2144 [["part_disk"; "/dev/sda"; "mbr"];
2145 ["pvcreate"; "/dev/sda1"];
2146 ["vgcreate"; "VG"; "/dev/sda1"];
2147 ["lvcreate"; "LV1"; "VG"; "50"];
2148 ["lvcreate"; "LV2"; "VG"; "50"];
2151 "remove an LVM volume group",
2153 Remove an LVM volume group C<vgname>, (for example C<VG>).
2155 This also forcibly removes all logical volumes in the volume
2158 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2159 [InitEmpty, Always, TestOutputListOfDevices (
2160 [["part_disk"; "/dev/sda"; "mbr"];
2161 ["pvcreate"; "/dev/sda1"];
2162 ["vgcreate"; "VG"; "/dev/sda1"];
2163 ["lvcreate"; "LV1"; "VG"; "50"];
2164 ["lvcreate"; "LV2"; "VG"; "50"];
2166 ["pvremove"; "/dev/sda1"];
2168 InitEmpty, Always, TestOutputListOfDevices (
2169 [["part_disk"; "/dev/sda"; "mbr"];
2170 ["pvcreate"; "/dev/sda1"];
2171 ["vgcreate"; "VG"; "/dev/sda1"];
2172 ["lvcreate"; "LV1"; "VG"; "50"];
2173 ["lvcreate"; "LV2"; "VG"; "50"];
2175 ["pvremove"; "/dev/sda1"];
2177 InitEmpty, Always, TestOutputListOfDevices (
2178 [["part_disk"; "/dev/sda"; "mbr"];
2179 ["pvcreate"; "/dev/sda1"];
2180 ["vgcreate"; "VG"; "/dev/sda1"];
2181 ["lvcreate"; "LV1"; "VG"; "50"];
2182 ["lvcreate"; "LV2"; "VG"; "50"];
2184 ["pvremove"; "/dev/sda1"];
2186 "remove an LVM physical volume",
2188 This wipes a physical volume C<device> so that LVM will no longer
2191 The implementation uses the C<pvremove> command which refuses to
2192 wipe physical volumes that contain any volume groups, so you have
2193 to remove those first.");
2195 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2196 [InitBasicFS, Always, TestOutput (
2197 [["set_e2label"; "/dev/sda1"; "testlabel"];
2198 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2199 "set the ext2/3/4 filesystem label",
2201 This sets the ext2/3/4 filesystem label of the filesystem on
2202 C<device> to C<label>. Filesystem labels are limited to
2205 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2206 to return the existing label on a filesystem.");
2208 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2210 "get the ext2/3/4 filesystem label",
2212 This returns the ext2/3/4 filesystem label of the filesystem on
2215 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2216 (let uuid = uuidgen () in
2217 [InitBasicFS, Always, TestOutput (
2218 [["set_e2uuid"; "/dev/sda1"; uuid];
2219 ["get_e2uuid"; "/dev/sda1"]], uuid);
2220 InitBasicFS, Always, TestOutput (
2221 [["set_e2uuid"; "/dev/sda1"; "clear"];
2222 ["get_e2uuid"; "/dev/sda1"]], "");
2223 (* We can't predict what UUIDs will be, so just check the commands run. *)
2224 InitBasicFS, Always, TestRun (
2225 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2226 InitBasicFS, Always, TestRun (
2227 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2228 "set the ext2/3/4 filesystem UUID",
2230 This sets the ext2/3/4 filesystem UUID of the filesystem on
2231 C<device> to C<uuid>. The format of the UUID and alternatives
2232 such as C<clear>, C<random> and C<time> are described in the
2233 L<tune2fs(8)> manpage.
2235 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2236 to return the existing UUID of a filesystem.");
2238 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2240 "get the ext2/3/4 filesystem UUID",
2242 This returns the ext2/3/4 filesystem UUID of the filesystem on
2245 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2246 [InitBasicFS, Always, TestOutputInt (
2247 [["umount"; "/dev/sda1"];
2248 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2249 InitBasicFS, Always, TestOutputInt (
2250 [["umount"; "/dev/sda1"];
2251 ["zero"; "/dev/sda1"];
2252 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2253 "run the filesystem checker",
2255 This runs the filesystem checker (fsck) on C<device> which
2256 should have filesystem type C<fstype>.
2258 The returned integer is the status. See L<fsck(8)> for the
2259 list of status codes from C<fsck>.
2267 Multiple status codes can be summed together.
2271 A non-zero return code can mean \"success\", for example if
2272 errors have been corrected on the filesystem.
2276 Checking or repairing NTFS volumes is not supported
2281 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2283 ("zero", (RErr, [Device "device"]), 85, [],
2284 [InitBasicFS, Always, TestOutput (
2285 [["umount"; "/dev/sda1"];
2286 ["zero"; "/dev/sda1"];
2287 ["file"; "/dev/sda1"]], "data")],
2288 "write zeroes to the device",
2290 This command writes zeroes over the first few blocks of C<device>.
2292 How many blocks are zeroed isn't specified (but it's I<not> enough
2293 to securely wipe the device). It should be sufficient to remove
2294 any partition tables, filesystem superblocks and so on.
2296 See also: C<guestfs_scrub_device>.");
2298 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2299 (* Test disabled because grub-install incompatible with virtio-blk driver.
2300 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2302 [InitBasicFS, Disabled, TestOutputTrue (
2303 [["grub_install"; "/"; "/dev/sda1"];
2304 ["is_dir"; "/boot"]])],
2307 This command installs GRUB (the Grand Unified Bootloader) on
2308 C<device>, with the root directory being C<root>.");
2310 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2311 [InitBasicFS, Always, TestOutput (
2312 [["write_file"; "/old"; "file content"; "0"];
2313 ["cp"; "/old"; "/new"];
2314 ["cat"; "/new"]], "file content");
2315 InitBasicFS, Always, TestOutputTrue (
2316 [["write_file"; "/old"; "file content"; "0"];
2317 ["cp"; "/old"; "/new"];
2318 ["is_file"; "/old"]]);
2319 InitBasicFS, Always, TestOutput (
2320 [["write_file"; "/old"; "file content"; "0"];
2322 ["cp"; "/old"; "/dir/new"];
2323 ["cat"; "/dir/new"]], "file content")],
2326 This copies a file from C<src> to C<dest> where C<dest> is
2327 either a destination filename or destination directory.");
2329 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2330 [InitBasicFS, Always, TestOutput (
2331 [["mkdir"; "/olddir"];
2332 ["mkdir"; "/newdir"];
2333 ["write_file"; "/olddir/file"; "file content"; "0"];
2334 ["cp_a"; "/olddir"; "/newdir"];
2335 ["cat"; "/newdir/olddir/file"]], "file content")],
2336 "copy a file or directory recursively",
2338 This copies a file or directory from C<src> to C<dest>
2339 recursively using the C<cp -a> command.");
2341 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2342 [InitBasicFS, Always, TestOutput (
2343 [["write_file"; "/old"; "file content"; "0"];
2344 ["mv"; "/old"; "/new"];
2345 ["cat"; "/new"]], "file content");
2346 InitBasicFS, Always, TestOutputFalse (
2347 [["write_file"; "/old"; "file content"; "0"];
2348 ["mv"; "/old"; "/new"];
2349 ["is_file"; "/old"]])],
2352 This moves a file from C<src> to C<dest> where C<dest> is
2353 either a destination filename or destination directory.");
2355 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2356 [InitEmpty, Always, TestRun (
2357 [["drop_caches"; "3"]])],
2358 "drop kernel page cache, dentries and inodes",
2360 This instructs the guest kernel to drop its page cache,
2361 and/or dentries and inode caches. The parameter C<whattodrop>
2362 tells the kernel what precisely to drop, see
2363 L<http://linux-mm.org/Drop_Caches>
2365 Setting C<whattodrop> to 3 should drop everything.
2367 This automatically calls L<sync(2)> before the operation,
2368 so that the maximum guest memory is freed.");
2370 ("dmesg", (RString "kmsgs", []), 91, [],
2371 [InitEmpty, Always, TestRun (
2373 "return kernel messages",
2375 This returns the kernel messages (C<dmesg> output) from
2376 the guest kernel. This is sometimes useful for extended
2377 debugging of problems.
2379 Another way to get the same information is to enable
2380 verbose messages with C<guestfs_set_verbose> or by setting
2381 the environment variable C<LIBGUESTFS_DEBUG=1> before
2382 running the program.");
2384 ("ping_daemon", (RErr, []), 92, [],
2385 [InitEmpty, Always, TestRun (
2386 [["ping_daemon"]])],
2387 "ping the guest daemon",
2389 This is a test probe into the guestfs daemon running inside
2390 the qemu subprocess. Calling this function checks that the
2391 daemon responds to the ping message, without affecting the daemon
2392 or attached block device(s) in any other way.");
2394 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2395 [InitBasicFS, Always, TestOutputTrue (
2396 [["write_file"; "/file1"; "contents of a file"; "0"];
2397 ["cp"; "/file1"; "/file2"];
2398 ["equal"; "/file1"; "/file2"]]);
2399 InitBasicFS, Always, TestOutputFalse (
2400 [["write_file"; "/file1"; "contents of a file"; "0"];
2401 ["write_file"; "/file2"; "contents of another file"; "0"];
2402 ["equal"; "/file1"; "/file2"]]);
2403 InitBasicFS, Always, TestLastFail (
2404 [["equal"; "/file1"; "/file2"]])],
2405 "test if two files have equal contents",
2407 This compares the two files C<file1> and C<file2> and returns
2408 true if their content is exactly equal, or false otherwise.
2410 The external L<cmp(1)> program is used for the comparison.");
2412 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2413 [InitISOFS, Always, TestOutputList (
2414 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2415 InitISOFS, Always, TestOutputList (
2416 [["strings"; "/empty"]], [])],
2417 "print the printable strings in a file",
2419 This runs the L<strings(1)> command on a file and returns
2420 the list of printable strings found.");
2422 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2423 [InitISOFS, Always, TestOutputList (
2424 [["strings_e"; "b"; "/known-5"]], []);
2425 InitBasicFS, Disabled, TestOutputList (
2426 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2427 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2428 "print the printable strings in a file",
2430 This is like the C<guestfs_strings> command, but allows you to
2431 specify the encoding.
2433 See the L<strings(1)> manpage for the full list of encodings.
2435 Commonly useful encodings are C<l> (lower case L) which will
2436 show strings inside Windows/x86 files.
2438 The returned strings are transcoded to UTF-8.");
2440 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2441 [InitISOFS, Always, TestOutput (
2442 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2443 (* Test for RHBZ#501888c2 regression which caused large hexdump
2444 * commands to segfault.
2446 InitISOFS, Always, TestRun (
2447 [["hexdump"; "/100krandom"]])],
2448 "dump a file in hexadecimal",
2450 This runs C<hexdump -C> on the given C<path>. The result is
2451 the human-readable, canonical hex dump of the file.");
2453 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2454 [InitNone, Always, TestOutput (
2455 [["part_disk"; "/dev/sda"; "mbr"];
2456 ["mkfs"; "ext3"; "/dev/sda1"];
2457 ["mount_options"; ""; "/dev/sda1"; "/"];
2458 ["write_file"; "/new"; "test file"; "0"];
2459 ["umount"; "/dev/sda1"];
2460 ["zerofree"; "/dev/sda1"];
2461 ["mount_options"; ""; "/dev/sda1"; "/"];
2462 ["cat"; "/new"]], "test file")],
2463 "zero unused inodes and disk blocks on ext2/3 filesystem",
2465 This runs the I<zerofree> program on C<device>. This program
2466 claims to zero unused inodes and disk blocks on an ext2/3
2467 filesystem, thus making it possible to compress the filesystem
2470 You should B<not> run this program if the filesystem is
2473 It is possible that using this program can damage the filesystem
2474 or data on the filesystem.");
2476 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2478 "resize an LVM physical volume",
2480 This resizes (expands or shrinks) an existing LVM physical
2481 volume to match the new size of the underlying device.");
2483 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2484 Int "cyls"; Int "heads"; Int "sectors";
2485 String "line"]), 99, [DangerWillRobinson],
2487 "modify a single partition on a block device",
2489 This runs L<sfdisk(8)> option to modify just the single
2490 partition C<n> (note: C<n> counts from 1).
2492 For other parameters, see C<guestfs_sfdisk>. You should usually
2493 pass C<0> for the cyls/heads/sectors parameters.
2495 See also: C<guestfs_part_add>");
2497 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2499 "display the partition table",
2501 This displays the partition table on C<device>, in the
2502 human-readable output of the L<sfdisk(8)> command. It is
2503 not intended to be parsed.
2505 See also: C<guestfs_part_list>");
2507 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2509 "display the kernel geometry",
2511 This displays the kernel's idea of the geometry of C<device>.
2513 The result is in human-readable format, and not designed to
2516 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2518 "display the disk geometry from the partition table",
2520 This displays the disk geometry of C<device> read from the
2521 partition table. Especially in the case where the underlying
2522 block device has been resized, this can be different from the
2523 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2525 The result is in human-readable format, and not designed to
2528 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2530 "activate or deactivate all volume groups",
2532 This command activates or (if C<activate> is false) deactivates
2533 all logical volumes in all volume groups.
2534 If activated, then they are made known to the
2535 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2536 then those devices disappear.
2538 This command is the same as running C<vgchange -a y|n>");
2540 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2542 "activate or deactivate some volume groups",
2544 This command activates or (if C<activate> is false) deactivates
2545 all logical volumes in the listed volume groups C<volgroups>.
2546 If activated, then they are made known to the
2547 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2548 then those devices disappear.
2550 This command is the same as running C<vgchange -a y|n volgroups...>
2552 Note that if C<volgroups> is an empty list then B<all> volume groups
2553 are activated or deactivated.");
2555 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2556 [InitNone, Always, TestOutput (
2557 [["part_disk"; "/dev/sda"; "mbr"];
2558 ["pvcreate"; "/dev/sda1"];
2559 ["vgcreate"; "VG"; "/dev/sda1"];
2560 ["lvcreate"; "LV"; "VG"; "10"];
2561 ["mkfs"; "ext2"; "/dev/VG/LV"];
2562 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2563 ["write_file"; "/new"; "test content"; "0"];
2565 ["lvresize"; "/dev/VG/LV"; "20"];
2566 ["e2fsck_f"; "/dev/VG/LV"];
2567 ["resize2fs"; "/dev/VG/LV"];
2568 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2569 ["cat"; "/new"]], "test content")],
2570 "resize an LVM logical volume",
2572 This resizes (expands or shrinks) an existing LVM logical
2573 volume to C<mbytes>. When reducing, data in the reduced part
2576 ("resize2fs", (RErr, [Device "device"]), 106, [],
2577 [], (* lvresize tests this *)
2578 "resize an ext2/ext3 filesystem",
2580 This resizes an ext2 or ext3 filesystem to match the size of
2581 the underlying device.
2583 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2584 on the C<device> before calling this command. For unknown reasons
2585 C<resize2fs> sometimes gives an error about this and sometimes not.
2586 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2587 calling this function.");
2589 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2590 [InitBasicFS, Always, TestOutputList (
2591 [["find"; "/"]], ["lost+found"]);
2592 InitBasicFS, Always, TestOutputList (
2596 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2597 InitBasicFS, Always, TestOutputList (
2598 [["mkdir_p"; "/a/b/c"];
2599 ["touch"; "/a/b/c/d"];
2600 ["find"; "/a/b/"]], ["c"; "c/d"])],
2601 "find all files and directories",
2603 This command lists out all files and directories, recursively,
2604 starting at C<directory>. It is essentially equivalent to
2605 running the shell command C<find directory -print> but some
2606 post-processing happens on the output, described below.
2608 This returns a list of strings I<without any prefix>. Thus
2609 if the directory structure was:
2615 then the returned list from C<guestfs_find> C</tmp> would be
2623 If C<directory> is not a directory, then this command returns
2626 The returned list is sorted.
2628 See also C<guestfs_find0>.");
2630 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2631 [], (* lvresize tests this *)
2632 "check an ext2/ext3 filesystem",
2634 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2635 filesystem checker on C<device>, noninteractively (C<-p>),
2636 even if the filesystem appears to be clean (C<-f>).
2638 This command is only needed because of C<guestfs_resize2fs>
2639 (q.v.). Normally you should use C<guestfs_fsck>.");
2641 ("sleep", (RErr, [Int "secs"]), 109, [],
2642 [InitNone, Always, TestRun (
2644 "sleep for some seconds",
2646 Sleep for C<secs> seconds.");
2648 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2649 [InitNone, Always, TestOutputInt (
2650 [["part_disk"; "/dev/sda"; "mbr"];
2651 ["mkfs"; "ntfs"; "/dev/sda1"];
2652 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2653 InitNone, Always, TestOutputInt (
2654 [["part_disk"; "/dev/sda"; "mbr"];
2655 ["mkfs"; "ext2"; "/dev/sda1"];
2656 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2657 "probe NTFS volume",
2659 This command runs the L<ntfs-3g.probe(8)> command which probes
2660 an NTFS C<device> for mountability. (Not all NTFS volumes can
2661 be mounted read-write, and some cannot be mounted at all).
2663 C<rw> is a boolean flag. Set it to true if you want to test
2664 if the volume can be mounted read-write. Set it to false if
2665 you want to test if the volume can be mounted read-only.
2667 The return value is an integer which C<0> if the operation
2668 would succeed, or some non-zero value documented in the
2669 L<ntfs-3g.probe(8)> manual page.");
2671 ("sh", (RString "output", [String "command"]), 111, [],
2672 [], (* XXX needs tests *)
2673 "run a command via the shell",
2675 This call runs a command from the guest filesystem via the
2678 This is like C<guestfs_command>, but passes the command to:
2680 /bin/sh -c \"command\"
2682 Depending on the guest's shell, this usually results in
2683 wildcards being expanded, shell expressions being interpolated
2686 All the provisos about C<guestfs_command> apply to this call.");
2688 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2689 [], (* XXX needs tests *)
2690 "run a command via the shell returning lines",
2692 This is the same as C<guestfs_sh>, but splits the result
2693 into a list of lines.
2695 See also: C<guestfs_command_lines>");
2697 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2698 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2699 * code in stubs.c, since all valid glob patterns must start with "/".
2700 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2702 [InitBasicFS, Always, TestOutputList (
2703 [["mkdir_p"; "/a/b/c"];
2704 ["touch"; "/a/b/c/d"];
2705 ["touch"; "/a/b/c/e"];
2706 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2707 InitBasicFS, Always, TestOutputList (
2708 [["mkdir_p"; "/a/b/c"];
2709 ["touch"; "/a/b/c/d"];
2710 ["touch"; "/a/b/c/e"];
2711 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2712 InitBasicFS, Always, TestOutputList (
2713 [["mkdir_p"; "/a/b/c"];
2714 ["touch"; "/a/b/c/d"];
2715 ["touch"; "/a/b/c/e"];
2716 ["glob_expand"; "/a/*/x/*"]], [])],
2717 "expand a wildcard path",
2719 This command searches for all the pathnames matching
2720 C<pattern> according to the wildcard expansion rules
2723 If no paths match, then this returns an empty list
2724 (note: not an error).
2726 It is just a wrapper around the C L<glob(3)> function
2727 with flags C<GLOB_MARK|GLOB_BRACE>.
2728 See that manual page for more details.");
2730 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2731 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2732 [["scrub_device"; "/dev/sdc"]])],
2733 "scrub (securely wipe) a device",
2735 This command writes patterns over C<device> to make data retrieval
2738 It is an interface to the L<scrub(1)> program. See that
2739 manual page for more details.");
2741 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2742 [InitBasicFS, Always, TestRun (
2743 [["write_file"; "/file"; "content"; "0"];
2744 ["scrub_file"; "/file"]])],
2745 "scrub (securely wipe) a file",
2747 This command writes patterns over a file to make data retrieval
2750 The file is I<removed> after scrubbing.
2752 It is an interface to the L<scrub(1)> program. See that
2753 manual page for more details.");
2755 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2756 [], (* XXX needs testing *)
2757 "scrub (securely wipe) free space",
2759 This command creates the directory C<dir> and then fills it
2760 with files until the filesystem is full, and scrubs the files
2761 as for C<guestfs_scrub_file>, and deletes them.
2762 The intention is to scrub any free space on the partition
2765 It is an interface to the L<scrub(1)> program. See that
2766 manual page for more details.");
2768 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2769 [InitBasicFS, Always, TestRun (
2771 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2772 "create a temporary directory",
2774 This command creates a temporary directory. The
2775 C<template> parameter should be a full pathname for the
2776 temporary directory name with the final six characters being
2779 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2780 the second one being suitable for Windows filesystems.
2782 The name of the temporary directory that was created
2785 The temporary directory is created with mode 0700
2786 and is owned by root.
2788 The caller is responsible for deleting the temporary
2789 directory and its contents after use.
2791 See also: L<mkdtemp(3)>");
2793 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2794 [InitISOFS, Always, TestOutputInt (
2795 [["wc_l"; "/10klines"]], 10000)],
2796 "count lines in a file",
2798 This command counts the lines in a file, using the
2799 C<wc -l> external command.");
2801 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2802 [InitISOFS, Always, TestOutputInt (
2803 [["wc_w"; "/10klines"]], 10000)],
2804 "count words in a file",
2806 This command counts the words in a file, using the
2807 C<wc -w> external command.");
2809 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2810 [InitISOFS, Always, TestOutputInt (
2811 [["wc_c"; "/100kallspaces"]], 102400)],
2812 "count characters in a file",
2814 This command counts the characters in a file, using the
2815 C<wc -c> external command.");
2817 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2818 [InitISOFS, Always, TestOutputList (
2819 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2820 "return first 10 lines of a file",
2822 This command returns up to the first 10 lines of a file as
2823 a list of strings.");
2825 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2826 [InitISOFS, Always, TestOutputList (
2827 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2828 InitISOFS, Always, TestOutputList (
2829 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2830 InitISOFS, Always, TestOutputList (
2831 [["head_n"; "0"; "/10klines"]], [])],
2832 "return first N lines of a file",
2834 If the parameter C<nrlines> is a positive number, this returns the first
2835 C<nrlines> lines of the file C<path>.
2837 If the parameter C<nrlines> is a negative number, this returns lines
2838 from the file C<path>, excluding the last C<nrlines> lines.
2840 If the parameter C<nrlines> is zero, this returns an empty list.");
2842 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2843 [InitISOFS, Always, TestOutputList (
2844 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2845 "return last 10 lines of a file",
2847 This command returns up to the last 10 lines of a file as
2848 a list of strings.");
2850 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2851 [InitISOFS, Always, TestOutputList (
2852 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2853 InitISOFS, Always, TestOutputList (
2854 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2855 InitISOFS, Always, TestOutputList (
2856 [["tail_n"; "0"; "/10klines"]], [])],
2857 "return last N lines of a file",
2859 If the parameter C<nrlines> is a positive number, this returns the last
2860 C<nrlines> lines of the file C<path>.
2862 If the parameter C<nrlines> is a negative number, this returns lines
2863 from the file C<path>, starting with the C<-nrlines>th line.
2865 If the parameter C<nrlines> is zero, this returns an empty list.");
2867 ("df", (RString "output", []), 125, [],
2868 [], (* XXX Tricky to test because it depends on the exact format
2869 * of the 'df' command and other imponderables.
2871 "report file system disk space usage",
2873 This command runs the C<df> command to report disk space used.
2875 This command is mostly useful for interactive sessions. It
2876 is I<not> intended that you try to parse the output string.
2877 Use C<statvfs> from programs.");
2879 ("df_h", (RString "output", []), 126, [],
2880 [], (* XXX Tricky to test because it depends on the exact format
2881 * of the 'df' command and other imponderables.
2883 "report file system disk space usage (human readable)",
2885 This command runs the C<df -h> command to report disk space used
2886 in human-readable format.
2888 This command is mostly useful for interactive sessions. It
2889 is I<not> intended that you try to parse the output string.
2890 Use C<statvfs> from programs.");
2892 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2893 [InitISOFS, Always, TestOutputInt (
2894 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2895 "estimate file space usage",
2897 This command runs the C<du -s> command to estimate file space
2900 C<path> can be a file or a directory. If C<path> is a directory
2901 then the estimate includes the contents of the directory and all
2902 subdirectories (recursively).
2904 The result is the estimated size in I<kilobytes>
2905 (ie. units of 1024 bytes).");
2907 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2908 [InitISOFS, Always, TestOutputList (
2909 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2910 "list files in an initrd",
2912 This command lists out files contained in an initrd.
2914 The files are listed without any initial C</> character. The
2915 files are listed in the order they appear (not necessarily
2916 alphabetical). Directory names are listed as separate items.
2918 Old Linux kernels (2.4 and earlier) used a compressed ext2
2919 filesystem as initrd. We I<only> support the newer initramfs
2920 format (compressed cpio files).");
2922 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2924 "mount a file using the loop device",
2926 This command lets you mount C<file> (a filesystem image
2927 in a file) on a mount point. It is entirely equivalent to
2928 the command C<mount -o loop file mountpoint>.");
2930 ("mkswap", (RErr, [Device "device"]), 130, [],
2931 [InitEmpty, Always, TestRun (
2932 [["part_disk"; "/dev/sda"; "mbr"];
2933 ["mkswap"; "/dev/sda1"]])],
2934 "create a swap partition",
2936 Create a swap partition on C<device>.");
2938 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2939 [InitEmpty, Always, TestRun (
2940 [["part_disk"; "/dev/sda"; "mbr"];
2941 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2942 "create a swap partition with a label",
2944 Create a swap partition on C<device> with label C<label>.
2946 Note that you cannot attach a swap label to a block device
2947 (eg. C</dev/sda>), just to a partition. This appears to be
2948 a limitation of the kernel or swap tools.");
2950 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2951 (let uuid = uuidgen () in
2952 [InitEmpty, Always, TestRun (
2953 [["part_disk"; "/dev/sda"; "mbr"];
2954 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2955 "create a swap partition with an explicit UUID",
2957 Create a swap partition on C<device> with UUID C<uuid>.");
2959 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2960 [InitBasicFS, Always, TestOutputStruct (
2961 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2962 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2963 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2964 InitBasicFS, Always, TestOutputStruct (
2965 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2966 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2967 "make block, character or FIFO devices",
2969 This call creates block or character special devices, or
2970 named pipes (FIFOs).
2972 The C<mode> parameter should be the mode, using the standard
2973 constants. C<devmajor> and C<devminor> are the
2974 device major and minor numbers, only used when creating block
2975 and character special devices.");
2977 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2978 [InitBasicFS, Always, TestOutputStruct (
2979 [["mkfifo"; "0o777"; "/node"];
2980 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2981 "make FIFO (named pipe)",
2983 This call creates a FIFO (named pipe) called C<path> with
2984 mode C<mode>. It is just a convenient wrapper around
2985 C<guestfs_mknod>.");
2987 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2988 [InitBasicFS, Always, TestOutputStruct (
2989 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2990 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2991 "make block device node",
2993 This call creates a block device node called C<path> with
2994 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2995 It is just a convenient wrapper around C<guestfs_mknod>.");
2997 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2998 [InitBasicFS, Always, TestOutputStruct (
2999 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3000 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3001 "make char device node",
3003 This call creates a char device node called C<path> with
3004 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3005 It is just a convenient wrapper around C<guestfs_mknod>.");
3007 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3008 [], (* XXX umask is one of those stateful things that we should
3009 * reset between each test.
3011 "set file mode creation mask (umask)",
3013 This function sets the mask used for creating new files and
3014 device nodes to C<mask & 0777>.
3016 Typical umask values would be C<022> which creates new files
3017 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3018 C<002> which creates new files with permissions like
3019 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3021 The default umask is C<022>. This is important because it
3022 means that directories and device nodes will be created with
3023 C<0644> or C<0755> mode even if you specify C<0777>.
3025 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3027 This call returns the previous umask.");
3029 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3031 "read directories entries",
3033 This returns the list of directory entries in directory C<dir>.
3035 All entries in the directory are returned, including C<.> and
3036 C<..>. The entries are I<not> sorted, but returned in the same
3037 order as the underlying filesystem.
3039 Also this call returns basic file type information about each
3040 file. The C<ftyp> field will contain one of the following characters:
3078 The L<readdir(3)> returned a C<d_type> field with an
3083 This function is primarily intended for use by programs. To
3084 get a simple list of names, use C<guestfs_ls>. To get a printable
3085 directory for human consumption, use C<guestfs_ll>.");
3087 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3089 "create partitions on a block device",
3091 This is a simplified interface to the C<guestfs_sfdisk>
3092 command, where partition sizes are specified in megabytes
3093 only (rounded to the nearest cylinder) and you don't need
3094 to specify the cyls, heads and sectors parameters which
3095 were rarely if ever used anyway.
3097 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3098 and C<guestfs_part_disk>");
3100 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3102 "determine file type inside a compressed file",
3104 This command runs C<file> after first decompressing C<path>
3107 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3109 Since 1.0.63, use C<guestfs_file> instead which can now
3110 process compressed files.");
3112 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3114 "list extended attributes of a file or directory",
3116 This call lists the extended attributes of the file or directory
3119 At the system call level, this is a combination of the
3120 L<listxattr(2)> and L<getxattr(2)> calls.
3122 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3124 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3126 "list extended attributes of a file or directory",
3128 This is the same as C<guestfs_getxattrs>, but if C<path>
3129 is a symbolic link, then it returns the extended attributes
3130 of the link itself.");
3132 ("setxattr", (RErr, [String "xattr";
3133 String "val"; Int "vallen"; (* will be BufferIn *)
3134 Pathname "path"]), 143, [Optional "linuxxattrs"],
3136 "set extended attribute of a file or directory",
3138 This call sets the extended attribute named C<xattr>
3139 of the file C<path> to the value C<val> (of length C<vallen>).
3140 The value is arbitrary 8 bit data.
3142 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3144 ("lsetxattr", (RErr, [String "xattr";
3145 String "val"; Int "vallen"; (* will be BufferIn *)
3146 Pathname "path"]), 144, [Optional "linuxxattrs"],
3148 "set extended attribute of a file or directory",
3150 This is the same as C<guestfs_setxattr>, but if C<path>
3151 is a symbolic link, then it sets an extended attribute
3152 of the link itself.");
3154 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3156 "remove extended attribute of a file or directory",
3158 This call removes the extended attribute named C<xattr>
3159 of the file C<path>.
3161 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3163 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3165 "remove extended attribute of a file or directory",
3167 This is the same as C<guestfs_removexattr>, but if C<path>
3168 is a symbolic link, then it removes an extended attribute
3169 of the link itself.");
3171 ("mountpoints", (RHashtable "mps", []), 147, [],
3175 This call is similar to C<guestfs_mounts>. That call returns
3176 a list of devices. This one returns a hash table (map) of
3177 device name to directory where the device is mounted.");
3179 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3180 (* This is a special case: while you would expect a parameter
3181 * of type "Pathname", that doesn't work, because it implies
3182 * NEED_ROOT in the generated calling code in stubs.c, and
3183 * this function cannot use NEED_ROOT.
3186 "create a mountpoint",
3188 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3189 specialized calls that can be used to create extra mountpoints
3190 before mounting the first filesystem.
3192 These calls are I<only> necessary in some very limited circumstances,
3193 mainly the case where you want to mount a mix of unrelated and/or
3194 read-only filesystems together.
3196 For example, live CDs often contain a \"Russian doll\" nest of
3197 filesystems, an ISO outer layer, with a squashfs image inside, with
3198 an ext2/3 image inside that. You can unpack this as follows
3201 add-ro Fedora-11-i686-Live.iso
3204 mkmountpoint /squash
3207 mount-loop /cd/LiveOS/squashfs.img /squash
3208 mount-loop /squash/LiveOS/ext3fs.img /ext3
3210 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3212 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3214 "remove a mountpoint",
3216 This calls removes a mountpoint that was previously created
3217 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3218 for full details.");
3220 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3221 [InitISOFS, Always, TestOutputBuffer (
3222 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3225 This calls returns the contents of the file C<path> as a
3228 Unlike C<guestfs_cat>, this function can correctly
3229 handle files that contain embedded ASCII NUL characters.
3230 However unlike C<guestfs_download>, this function is limited
3231 in the total size of file that can be handled.");
3233 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3234 [InitISOFS, Always, TestOutputList (
3235 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3236 InitISOFS, Always, TestOutputList (
3237 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3238 "return lines matching a pattern",
3240 This calls the external C<grep> program and returns the
3243 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3244 [InitISOFS, Always, TestOutputList (
3245 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3246 "return lines matching a pattern",
3248 This calls the external C<egrep> program and returns the
3251 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3252 [InitISOFS, Always, TestOutputList (
3253 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3254 "return lines matching a pattern",
3256 This calls the external C<fgrep> program and returns the
3259 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3260 [InitISOFS, Always, TestOutputList (
3261 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3262 "return lines matching a pattern",
3264 This calls the external C<grep -i> program and returns the
3267 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3268 [InitISOFS, Always, TestOutputList (
3269 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3270 "return lines matching a pattern",
3272 This calls the external C<egrep -i> program and returns the
3275 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3276 [InitISOFS, Always, TestOutputList (
3277 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3278 "return lines matching a pattern",
3280 This calls the external C<fgrep -i> program and returns the
3283 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3284 [InitISOFS, Always, TestOutputList (
3285 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3286 "return lines matching a pattern",
3288 This calls the external C<zgrep> program and returns the
3291 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3292 [InitISOFS, Always, TestOutputList (
3293 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3294 "return lines matching a pattern",
3296 This calls the external C<zegrep> program and returns the
3299 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3300 [InitISOFS, Always, TestOutputList (
3301 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3302 "return lines matching a pattern",
3304 This calls the external C<zfgrep> program and returns the
3307 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3308 [InitISOFS, Always, TestOutputList (
3309 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3310 "return lines matching a pattern",
3312 This calls the external C<zgrep -i> program and returns the
3315 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3316 [InitISOFS, Always, TestOutputList (
3317 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3318 "return lines matching a pattern",
3320 This calls the external C<zegrep -i> program and returns the
3323 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3324 [InitISOFS, Always, TestOutputList (
3325 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3326 "return lines matching a pattern",
3328 This calls the external C<zfgrep -i> program and returns the
3331 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3332 [InitISOFS, Always, TestOutput (
3333 [["realpath"; "/../directory"]], "/directory")],
3334 "canonicalized absolute pathname",
3336 Return the canonicalized absolute pathname of C<path>. The
3337 returned path has no C<.>, C<..> or symbolic link path elements.");
3339 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3340 [InitBasicFS, Always, TestOutputStruct (
3343 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3344 "create a hard link",
3346 This command creates a hard link using the C<ln> command.");
3348 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3349 [InitBasicFS, Always, TestOutputStruct (
3352 ["ln_f"; "/a"; "/b"];
3353 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3354 "create a hard link",
3356 This command creates a hard link using the C<ln -f> command.
3357 The C<-f> option removes the link (C<linkname>) if it exists already.");
3359 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3360 [InitBasicFS, Always, TestOutputStruct (
3362 ["ln_s"; "a"; "/b"];
3363 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3364 "create a symbolic link",
3366 This command creates a symbolic link using the C<ln -s> command.");
3368 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3369 [InitBasicFS, Always, TestOutput (
3370 [["mkdir_p"; "/a/b"];
3371 ["touch"; "/a/b/c"];
3372 ["ln_sf"; "../d"; "/a/b/c"];
3373 ["readlink"; "/a/b/c"]], "../d")],
3374 "create a symbolic link",
3376 This command creates a symbolic link using the C<ln -sf> command,
3377 The C<-f> option removes the link (C<linkname>) if it exists already.");
3379 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3380 [] (* XXX tested above *),
3381 "read the target of a symbolic link",
3383 This command reads the target of a symbolic link.");
3385 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3386 [InitBasicFS, Always, TestOutputStruct (
3387 [["fallocate"; "/a"; "1000000"];
3388 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3389 "preallocate a file in the guest filesystem",
3391 This command preallocates a file (containing zero bytes) named
3392 C<path> of size C<len> bytes. If the file exists already, it
3395 Do not confuse this with the guestfish-specific
3396 C<alloc> command which allocates a file in the host and
3397 attaches it as a device.");
3399 ("swapon_device", (RErr, [Device "device"]), 170, [],
3400 [InitPartition, Always, TestRun (
3401 [["mkswap"; "/dev/sda1"];
3402 ["swapon_device"; "/dev/sda1"];
3403 ["swapoff_device"; "/dev/sda1"]])],
3404 "enable swap on device",
3406 This command enables the libguestfs appliance to use the
3407 swap device or partition named C<device>. The increased
3408 memory is made available for all commands, for example
3409 those run using C<guestfs_command> or C<guestfs_sh>.
3411 Note that you should not swap to existing guest swap
3412 partitions unless you know what you are doing. They may
3413 contain hibernation information, or other information that
3414 the guest doesn't want you to trash. You also risk leaking
3415 information about the host to the guest this way. Instead,
3416 attach a new host device to the guest and swap on that.");
3418 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3419 [], (* XXX tested by swapon_device *)
3420 "disable swap on device",
3422 This command disables the libguestfs appliance swap
3423 device or partition named C<device>.
3424 See C<guestfs_swapon_device>.");
3426 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3427 [InitBasicFS, Always, TestRun (
3428 [["fallocate"; "/swap"; "8388608"];
3429 ["mkswap_file"; "/swap"];
3430 ["swapon_file"; "/swap"];
3431 ["swapoff_file"; "/swap"]])],
3432 "enable swap on file",
3434 This command enables swap to a file.
3435 See C<guestfs_swapon_device> for other notes.");
3437 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3438 [], (* XXX tested by swapon_file *)
3439 "disable swap on file",
3441 This command disables the libguestfs appliance swap on file.");
3443 ("swapon_label", (RErr, [String "label"]), 174, [],
3444 [InitEmpty, Always, TestRun (
3445 [["part_disk"; "/dev/sdb"; "mbr"];
3446 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3447 ["swapon_label"; "swapit"];
3448 ["swapoff_label"; "swapit"];
3449 ["zero"; "/dev/sdb"];
3450 ["blockdev_rereadpt"; "/dev/sdb"]])],
3451 "enable swap on labeled swap partition",
3453 This command enables swap to a labeled swap partition.
3454 See C<guestfs_swapon_device> for other notes.");
3456 ("swapoff_label", (RErr, [String "label"]), 175, [],
3457 [], (* XXX tested by swapon_label *)
3458 "disable swap on labeled swap partition",
3460 This command disables the libguestfs appliance swap on
3461 labeled swap partition.");
3463 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3464 (let uuid = uuidgen () in
3465 [InitEmpty, Always, TestRun (
3466 [["mkswap_U"; uuid; "/dev/sdb"];
3467 ["swapon_uuid"; uuid];
3468 ["swapoff_uuid"; uuid]])]),
3469 "enable swap on swap partition by UUID",
3471 This command enables swap to a swap partition with the given UUID.
3472 See C<guestfs_swapon_device> for other notes.");
3474 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3475 [], (* XXX tested by swapon_uuid *)
3476 "disable swap on swap partition by UUID",
3478 This command disables the libguestfs appliance swap partition
3479 with the given UUID.");
3481 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3482 [InitBasicFS, Always, TestRun (
3483 [["fallocate"; "/swap"; "8388608"];
3484 ["mkswap_file"; "/swap"]])],
3485 "create a swap file",
3489 This command just writes a swap file signature to an existing
3490 file. To create the file itself, use something like C<guestfs_fallocate>.");
3492 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3493 [InitISOFS, Always, TestRun (
3494 [["inotify_init"; "0"]])],
3495 "create an inotify handle",
3497 This command creates a new inotify handle.
3498 The inotify subsystem can be used to notify events which happen to
3499 objects in the guest filesystem.
3501 C<maxevents> is the maximum number of events which will be
3502 queued up between calls to C<guestfs_inotify_read> or
3503 C<guestfs_inotify_files>.
3504 If this is passed as C<0>, then the kernel (or previously set)
3505 default is used. For Linux 2.6.29 the default was 16384 events.
3506 Beyond this limit, the kernel throws away events, but records
3507 the fact that it threw them away by setting a flag
3508 C<IN_Q_OVERFLOW> in the returned structure list (see
3509 C<guestfs_inotify_read>).
3511 Before any events are generated, you have to add some
3512 watches to the internal watch list. See:
3513 C<guestfs_inotify_add_watch>,
3514 C<guestfs_inotify_rm_watch> and
3515 C<guestfs_inotify_watch_all>.
3517 Queued up events should be read periodically by calling
3518 C<guestfs_inotify_read>
3519 (or C<guestfs_inotify_files> which is just a helpful
3520 wrapper around C<guestfs_inotify_read>). If you don't
3521 read the events out often enough then you risk the internal
3524 The handle should be closed after use by calling
3525 C<guestfs_inotify_close>. This also removes any
3526 watches automatically.
3528 See also L<inotify(7)> for an overview of the inotify interface
3529 as exposed by the Linux kernel, which is roughly what we expose
3530 via libguestfs. Note that there is one global inotify handle
3531 per libguestfs instance.");
3533 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3534 [InitBasicFS, Always, TestOutputList (
3535 [["inotify_init"; "0"];
3536 ["inotify_add_watch"; "/"; "1073741823"];
3539 ["inotify_files"]], ["a"; "b"])],
3540 "add an inotify watch",
3542 Watch C<path> for the events listed in C<mask>.
3544 Note that if C<path> is a directory then events within that
3545 directory are watched, but this does I<not> happen recursively
3546 (in subdirectories).
3548 Note for non-C or non-Linux callers: the inotify events are
3549 defined by the Linux kernel ABI and are listed in
3550 C</usr/include/sys/inotify.h>.");
3552 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3554 "remove an inotify watch",
3556 Remove a previously defined inotify watch.
3557 See C<guestfs_inotify_add_watch>.");
3559 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3561 "return list of inotify events",
3563 Return the complete queue of events that have happened
3564 since the previous read call.
3566 If no events have happened, this returns an empty list.
3568 I<Note>: In order to make sure that all events have been
3569 read, you must call this function repeatedly until it
3570 returns an empty list. The reason is that the call will
3571 read events up to the maximum appliance-to-host message
3572 size and leave remaining events in the queue.");
3574 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3576 "return list of watched files that had events",
3578 This function is a helpful wrapper around C<guestfs_inotify_read>
3579 which just returns a list of pathnames of objects that were
3580 touched. The returned pathnames are sorted and deduplicated.");
3582 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3584 "close the inotify handle",
3586 This closes the inotify handle which was previously
3587 opened by inotify_init. It removes all watches, throws
3588 away any pending events, and deallocates all resources.");
3590 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3592 "set SELinux security context",
3594 This sets the SELinux security context of the daemon
3595 to the string C<context>.
3597 See the documentation about SELINUX in L<guestfs(3)>.");
3599 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3601 "get SELinux security context",
3603 This gets the SELinux security context of the daemon.
3605 See the documentation about SELINUX in L<guestfs(3)>,
3606 and C<guestfs_setcon>");
3608 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3609 [InitEmpty, Always, TestOutput (
3610 [["part_disk"; "/dev/sda"; "mbr"];
3611 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3612 ["mount_options"; ""; "/dev/sda1"; "/"];
3613 ["write_file"; "/new"; "new file contents"; "0"];
3614 ["cat"; "/new"]], "new file contents")],
3615 "make a filesystem with block size",
3617 This call is similar to C<guestfs_mkfs>, but it allows you to
3618 control the block size of the resulting filesystem. Supported
3619 block sizes depend on the filesystem type, but typically they
3620 are C<1024>, C<2048> or C<4096> only.");
3622 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3623 [InitEmpty, Always, TestOutput (
3624 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3625 ["mke2journal"; "4096"; "/dev/sda1"];
3626 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3627 ["mount_options"; ""; "/dev/sda2"; "/"];
3628 ["write_file"; "/new"; "new file contents"; "0"];
3629 ["cat"; "/new"]], "new file contents")],
3630 "make ext2/3/4 external journal",
3632 This creates an ext2 external journal on C<device>. It is equivalent
3635 mke2fs -O journal_dev -b blocksize device");
3637 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3638 [InitEmpty, Always, TestOutput (
3639 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3640 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3641 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3642 ["mount_options"; ""; "/dev/sda2"; "/"];
3643 ["write_file"; "/new"; "new file contents"; "0"];
3644 ["cat"; "/new"]], "new file contents")],
3645 "make ext2/3/4 external journal with label",
3647 This creates an ext2 external journal on C<device> with label C<label>.");
3649 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3650 (let uuid = uuidgen () in
3651 [InitEmpty, Always, TestOutput (
3652 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3653 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3654 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3655 ["mount_options"; ""; "/dev/sda2"; "/"];
3656 ["write_file"; "/new"; "new file contents"; "0"];
3657 ["cat"; "/new"]], "new file contents")]),
3658 "make ext2/3/4 external journal with UUID",
3660 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3662 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3664 "make ext2/3/4 filesystem with external journal",
3666 This creates an ext2/3/4 filesystem on C<device> with
3667 an external journal on C<journal>. It is equivalent
3670 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3672 See also C<guestfs_mke2journal>.");
3674 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3676 "make ext2/3/4 filesystem with external journal",
3678 This creates an ext2/3/4 filesystem on C<device> with
3679 an external journal on the journal labeled C<label>.
3681 See also C<guestfs_mke2journal_L>.");
3683 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3685 "make ext2/3/4 filesystem with external journal",
3687 This creates an ext2/3/4 filesystem on C<device> with
3688 an external journal on the journal with UUID C<uuid>.
3690 See also C<guestfs_mke2journal_U>.");
3692 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3693 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3694 "load a kernel module",
3696 This loads a kernel module in the appliance.
3698 The kernel module must have been whitelisted when libguestfs
3699 was built (see C<appliance/kmod.whitelist.in> in the source).");
3701 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3702 [InitNone, Always, TestOutput (
3703 [["echo_daemon"; "This is a test"]], "This is a test"
3705 "echo arguments back to the client",
3707 This command concatenate the list of C<words> passed with single spaces between
3708 them and returns the resulting string.
3710 You can use this command to test the connection through to the daemon.
3712 See also C<guestfs_ping_daemon>.");
3714 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3715 [], (* There is a regression test for this. *)
3716 "find all files and directories, returning NUL-separated list",
3718 This command lists out all files and directories, recursively,
3719 starting at C<directory>, placing the resulting list in the
3720 external file called C<files>.
3722 This command works the same way as C<guestfs_find> with the
3723 following exceptions:
3729 The resulting list is written to an external file.
3733 Items (filenames) in the result are separated
3734 by C<\\0> characters. See L<find(1)> option I<-print0>.
3738 This command is not limited in the number of names that it
3743 The result list is not sorted.
3747 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3748 [InitISOFS, Always, TestOutput (
3749 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3750 InitISOFS, Always, TestOutput (
3751 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3752 InitISOFS, Always, TestOutput (
3753 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3754 InitISOFS, Always, TestLastFail (
3755 [["case_sensitive_path"; "/Known-1/"]]);
3756 InitBasicFS, Always, TestOutput (
3758 ["mkdir"; "/a/bbb"];
3759 ["touch"; "/a/bbb/c"];
3760 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3761 InitBasicFS, Always, TestOutput (
3763 ["mkdir"; "/a/bbb"];
3764 ["touch"; "/a/bbb/c"];
3765 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3766 InitBasicFS, Always, TestLastFail (
3768 ["mkdir"; "/a/bbb"];
3769 ["touch"; "/a/bbb/c"];
3770 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3771 "return true path on case-insensitive filesystem",
3773 This can be used to resolve case insensitive paths on
3774 a filesystem which is case sensitive. The use case is
3775 to resolve paths which you have read from Windows configuration
3776 files or the Windows Registry, to the true path.
3778 The command handles a peculiarity of the Linux ntfs-3g
3779 filesystem driver (and probably others), which is that although
3780 the underlying filesystem is case-insensitive, the driver
3781 exports the filesystem to Linux as case-sensitive.
3783 One consequence of this is that special directories such
3784 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3785 (or other things) depending on the precise details of how
3786 they were created. In Windows itself this would not be
3789 Bug or feature? You decide:
3790 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3792 This function resolves the true case of each element in the
3793 path and returns the case-sensitive path.
3795 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3796 might return C<\"/WINDOWS/system32\"> (the exact return value
3797 would depend on details of how the directories were originally
3798 created under Windows).
3801 This function does not handle drive names, backslashes etc.
3803 See also C<guestfs_realpath>.");
3805 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3806 [InitBasicFS, Always, TestOutput (
3807 [["vfs_type"; "/dev/sda1"]], "ext2")],
3808 "get the Linux VFS type corresponding to a mounted device",
3810 This command gets the block device type corresponding to
3811 a mounted device called C<device>.
3813 Usually the result is the name of the Linux VFS module that
3814 is used to mount this device (probably determined automatically
3815 if you used the C<guestfs_mount> call).");
3817 ("truncate", (RErr, [Pathname "path"]), 199, [],
3818 [InitBasicFS, Always, TestOutputStruct (
3819 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3820 ["truncate"; "/test"];
3821 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3822 "truncate a file to zero size",
3824 This command truncates C<path> to a zero-length file. The
3825 file must exist already.");
3827 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3828 [InitBasicFS, Always, TestOutputStruct (
3829 [["touch"; "/test"];
3830 ["truncate_size"; "/test"; "1000"];
3831 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3832 "truncate a file to a particular size",
3834 This command truncates C<path> to size C<size> bytes. The file
3835 must exist already. If the file is smaller than C<size> then
3836 the file is extended to the required size with null bytes.");
3838 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3839 [InitBasicFS, Always, TestOutputStruct (
3840 [["touch"; "/test"];
3841 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3842 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3843 "set timestamp of a file with nanosecond precision",
3845 This command sets the timestamps of a file with nanosecond
3848 C<atsecs, atnsecs> are the last access time (atime) in secs and
3849 nanoseconds from the epoch.
3851 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3852 secs and nanoseconds from the epoch.
3854 If the C<*nsecs> field contains the special value C<-1> then
3855 the corresponding timestamp is set to the current time. (The
3856 C<*secs> field is ignored in this case).
3858 If the C<*nsecs> field contains the special value C<-2> then
3859 the corresponding timestamp is left unchanged. (The
3860 C<*secs> field is ignored in this case).");
3862 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3863 [InitBasicFS, Always, TestOutputStruct (
3864 [["mkdir_mode"; "/test"; "0o111"];
3865 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3866 "create a directory with a particular mode",
3868 This command creates a directory, setting the initial permissions
3869 of the directory to C<mode>. See also C<guestfs_mkdir>.");
3871 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3873 "change file owner and group",
3875 Change the file owner to C<owner> and group to C<group>.
3876 This is like C<guestfs_chown> but if C<path> is a symlink then
3877 the link itself is changed, not the target.
3879 Only numeric uid and gid are supported. If you want to use
3880 names, you will need to locate and parse the password file
3881 yourself (Augeas support makes this relatively easy).");
3883 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3885 "lstat on multiple files",
3887 This call allows you to perform the C<guestfs_lstat> operation
3888 on multiple files, where all files are in the directory C<path>.
3889 C<names> is the list of files from this directory.
3891 On return you get a list of stat structs, with a one-to-one
3892 correspondence to the C<names> list. If any name did not exist
3893 or could not be lstat'd, then the C<ino> field of that structure
3896 This call is intended for programs that want to efficiently
3897 list a directory contents without making many round-trips.
3898 See also C<guestfs_lxattrlist> for a similarly efficient call
3899 for getting extended attributes. Very long directory listings
3900 might cause the protocol message size to be exceeded, causing
3901 this call to fail. The caller must split up such requests
3902 into smaller groups of names.");
3904 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3906 "lgetxattr on multiple files",
3908 This call allows you to get the extended attributes
3909 of multiple files, where all files are in the directory C<path>.
3910 C<names> is the list of files from this directory.
3912 On return you get a flat list of xattr structs which must be
3913 interpreted sequentially. The first xattr struct always has a zero-length
3914 C<attrname>. C<attrval> in this struct is zero-length
3915 to indicate there was an error doing C<lgetxattr> for this
3916 file, I<or> is a C string which is a decimal number
3917 (the number of following attributes for this file, which could
3918 be C<\"0\">). Then after the first xattr struct are the
3919 zero or more attributes for the first named file.
3920 This repeats for the second and subsequent files.
3922 This call is intended for programs that want to efficiently
3923 list a directory contents without making many round-trips.
3924 See also C<guestfs_lstatlist> for a similarly efficient call
3925 for getting standard stats. Very long directory listings
3926 might cause the protocol message size to be exceeded, causing
3927 this call to fail. The caller must split up such requests
3928 into smaller groups of names.");
3930 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3932 "readlink on multiple files",
3934 This call allows you to do a C<readlink> operation
3935 on multiple files, where all files are in the directory C<path>.
3936 C<names> is the list of files from this directory.
3938 On return you get a list of strings, with a one-to-one
3939 correspondence to the C<names> list. Each string is the
3940 value of the symbol link.
3942 If the C<readlink(2)> operation fails on any name, then
3943 the corresponding result string is the empty string C<\"\">.
3944 However the whole operation is completed even if there
3945 were C<readlink(2)> errors, and so you can call this
3946 function with names where you don't know if they are
3947 symbolic links already (albeit slightly less efficient).
3949 This call is intended for programs that want to efficiently
3950 list a directory contents without making many round-trips.
3951 Very long directory listings might cause the protocol
3952 message size to be exceeded, causing
3953 this call to fail. The caller must split up such requests
3954 into smaller groups of names.");
3956 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3957 [InitISOFS, Always, TestOutputBuffer (
3958 [["pread"; "/known-4"; "1"; "3"]], "\n");
3959 InitISOFS, Always, TestOutputBuffer (
3960 [["pread"; "/empty"; "0"; "100"]], "")],
3961 "read part of a file",
3963 This command lets you read part of a file. It reads C<count>
3964 bytes of the file, starting at C<offset>, from file C<path>.
3966 This may read fewer bytes than requested. For further details
3967 see the L<pread(2)> system call.");
3969 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3970 [InitEmpty, Always, TestRun (
3971 [["part_init"; "/dev/sda"; "gpt"]])],
3972 "create an empty partition table",
3974 This creates an empty partition table on C<device> of one of the
3975 partition types listed below. Usually C<parttype> should be
3976 either C<msdos> or C<gpt> (for large disks).
3978 Initially there are no partitions. Following this, you should
3979 call C<guestfs_part_add> for each partition required.
3981 Possible values for C<parttype> are:
3985 =item B<efi> | B<gpt>
3987 Intel EFI / GPT partition table.
3989 This is recommended for >= 2 TB partitions that will be accessed
3990 from Linux and Intel-based Mac OS X. It also has limited backwards
3991 compatibility with the C<mbr> format.
3993 =item B<mbr> | B<msdos>
3995 The standard PC \"Master Boot Record\" (MBR) format used
3996 by MS-DOS and Windows. This partition type will B<only> work
3997 for device sizes up to 2 TB. For large disks we recommend
4002 Other partition table types that may work but are not
4011 =item B<amiga> | B<rdb>
4013 Amiga \"Rigid Disk Block\" format.
4021 DASD, used on IBM mainframes.
4029 Old Mac partition format. Modern Macs use C<gpt>.
4033 NEC PC-98 format, common in Japan apparently.
4041 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4042 [InitEmpty, Always, TestRun (
4043 [["part_init"; "/dev/sda"; "mbr"];
4044 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4045 InitEmpty, Always, TestRun (
4046 [["part_init"; "/dev/sda"; "gpt"];
4047 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4048 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4049 InitEmpty, Always, TestRun (
4050 [["part_init"; "/dev/sda"; "mbr"];
4051 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4052 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4053 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4054 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4055 "add a partition to the device",
4057 This command adds a partition to C<device>. If there is no partition
4058 table on the device, call C<guestfs_part_init> first.
4060 The C<prlogex> parameter is the type of partition. Normally you
4061 should pass C<p> or C<primary> here, but MBR partition tables also
4062 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4065 C<startsect> and C<endsect> are the start and end of the partition
4066 in I<sectors>. C<endsect> may be negative, which means it counts
4067 backwards from the end of the disk (C<-1> is the last sector).
4069 Creating a partition which covers the whole disk is not so easy.
4070 Use C<guestfs_part_disk> to do that.");
4072 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4073 [InitEmpty, Always, TestRun (
4074 [["part_disk"; "/dev/sda"; "mbr"]]);
4075 InitEmpty, Always, TestRun (
4076 [["part_disk"; "/dev/sda"; "gpt"]])],
4077 "partition whole disk with a single primary partition",
4079 This command is simply a combination of C<guestfs_part_init>
4080 followed by C<guestfs_part_add> to create a single primary partition
4081 covering the whole disk.
4083 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4084 but other possible values are described in C<guestfs_part_init>.");
4086 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4087 [InitEmpty, Always, TestRun (
4088 [["part_disk"; "/dev/sda"; "mbr"];
4089 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4090 "make a partition bootable",
4092 This sets the bootable flag on partition numbered C<partnum> on
4093 device C<device>. Note that partitions are numbered from 1.
4095 The bootable flag is used by some PC BIOSes to determine which
4096 partition to boot from. It is by no means universally recognized,
4097 and in any case if your operating system installed a boot
4098 sector on the device itself, then that takes precedence.");
4100 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4101 [InitEmpty, Always, TestRun (
4102 [["part_disk"; "/dev/sda"; "gpt"];
4103 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4104 "set partition name",
4106 This sets the partition name on partition numbered C<partnum> on
4107 device C<device>. Note that partitions are numbered from 1.
4109 The partition name can only be set on certain types of partition
4110 table. This works on C<gpt> but not on C<mbr> partitions.");
4112 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4113 [], (* XXX Add a regression test for this. *)
4114 "list partitions on a device",
4116 This command parses the partition table on C<device> and
4117 returns the list of partitions found.
4119 The fields in the returned structure are:
4125 Partition number, counting from 1.
4129 Start of the partition I<in bytes>. To get sectors you have to
4130 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4134 End of the partition in bytes.
4138 Size of the partition in bytes.
4142 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4143 [InitEmpty, Always, TestOutput (
4144 [["part_disk"; "/dev/sda"; "gpt"];
4145 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4146 "get the partition table type",
4148 This command examines the partition table on C<device> and
4149 returns the partition table type (format) being used.
4151 Common return values include: C<msdos> (a DOS/Windows style MBR
4152 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4153 values are possible, although unusual. See C<guestfs_part_init>
4156 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4157 [InitBasicFS, Always, TestOutputBuffer (
4158 [["fill"; "0x63"; "10"; "/test"];
4159 ["read_file"; "/test"]], "cccccccccc")],
4160 "fill a file with octets",
4162 This command creates a new file called C<path>. The initial
4163 content of the file is C<len> octets of C<c>, where C<c>
4164 must be a number in the range C<[0..255]>.
4166 To fill a file with zero bytes (sparsely), it is
4167 much more efficient to use C<guestfs_truncate_size>.");
4169 ("available", (RErr, [StringList "groups"]), 216, [],
4170 [InitNone, Always, TestRun [["available"; ""]]],
4171 "test availability of some parts of the API",
4173 This command is used to check the availability of some
4174 groups of functionality in the appliance, which not all builds of
4175 the libguestfs appliance will be able to provide.
4177 The libguestfs groups, and the functions that those
4178 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4180 The argument C<groups> is a list of group names, eg:
4181 C<[\"inotify\", \"augeas\"]> would check for the availability of
4182 the Linux inotify functions and Augeas (configuration file
4185 The command returns no error if I<all> requested groups are available.
4187 It fails with an error if one or more of the requested
4188 groups is unavailable in the appliance.
4190 If an unknown group name is included in the
4191 list of groups then an error is always returned.
4199 You must call C<guestfs_launch> before calling this function.
4201 The reason is because we don't know what groups are
4202 supported by the appliance/daemon until it is running and can
4207 If a group of functions is available, this does not necessarily
4208 mean that they will work. You still have to check for errors
4209 when calling individual API functions even if they are
4214 It is usually the job of distro packagers to build
4215 complete functionality into the libguestfs appliance.
4216 Upstream libguestfs, if built from source with all
4217 requirements satisfied, will support everything.
4221 This call was added in version C<1.0.80>. In previous
4222 versions of libguestfs all you could do would be to speculatively
4223 execute a command to find out if the daemon implemented it.
4224 See also C<guestfs_version>.
4228 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4229 [InitBasicFS, Always, TestOutputBuffer (
4230 [["write_file"; "/src"; "hello, world"; "0"];
4231 ["dd"; "/src"; "/dest"];
4232 ["read_file"; "/dest"]], "hello, world")],
4233 "copy from source to destination using dd",
4235 This command copies from one source device or file C<src>
4236 to another destination device or file C<dest>. Normally you
4237 would use this to copy to or from a device or partition, for
4238 example to duplicate a filesystem.
4240 If the destination is a device, it must be as large or larger
4241 than the source file or device, otherwise the copy will fail.
4242 This command cannot do partial copies.");
4244 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4245 [InitBasicFS, Always, TestOutputInt (
4246 [["write_file"; "/file"; "hello, world"; "0"];
4247 ["filesize"; "/file"]], 12)],
4248 "return the size of the file in bytes",
4250 This command returns the size of C<file> in bytes.
4252 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4253 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4254 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4256 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4257 [InitBasicFSonLVM, Always, TestOutputList (
4258 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4259 ["lvs"]], ["/dev/VG/LV2"])],
4260 "rename an LVM logical volume",
4262 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4264 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4265 [InitBasicFSonLVM, Always, TestOutputList (
4267 ["vg_activate"; "false"; "VG"];
4268 ["vgrename"; "VG"; "VG2"];
4269 ["vg_activate"; "true"; "VG2"];
4270 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4271 ["vgs"]], ["VG2"])],
4272 "rename an LVM volume group",
4274 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4276 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4277 [InitISOFS, Always, TestOutputBuffer (
4278 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4279 "list the contents of a single file in an initrd",
4281 This command unpacks the file C<filename> from the initrd file
4282 called C<initrdpath>. The filename must be given I<without> the
4283 initial C</> character.
4285 For example, in guestfish you could use the following command
4286 to examine the boot script (usually called C</init>)
4287 contained in a Linux initrd or initramfs image:
4289 initrd-cat /boot/initrd-<version>.img init
4291 See also C<guestfs_initrd_list>.");
4293 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4295 "get the UUID of a physical volume",
4297 This command returns the UUID of the LVM PV C<device>.");
4299 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4301 "get the UUID of a volume group",
4303 This command returns the UUID of the LVM VG named C<vgname>.");
4305 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4307 "get the UUID of a logical volume",
4309 This command returns the UUID of the LVM LV C<device>.");
4311 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4313 "get the PV UUIDs containing the volume group",
4315 Given a VG called C<vgname>, this returns the UUIDs of all
4316 the physical volumes that this volume group resides on.
4318 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4319 calls to associate physical volumes and volume groups.
4321 See also C<guestfs_vglvuuids>.");
4323 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4325 "get the LV UUIDs of all LVs in the volume group",
4327 Given a VG called C<vgname>, this returns the UUIDs of all
4328 the logical volumes created in this volume group.
4330 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4331 calls to associate logical volumes and volume groups.
4333 See also C<guestfs_vgpvuuids>.");
4337 let all_functions = non_daemon_functions @ daemon_functions
4339 (* In some places we want the functions to be displayed sorted
4340 * alphabetically, so this is useful:
4342 let all_functions_sorted =
4343 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4344 compare n1 n2) all_functions
4346 (* Field types for structures. *)
4348 | FChar (* C 'char' (really, a 7 bit byte). *)
4349 | FString (* nul-terminated ASCII string, NOT NULL. *)
4350 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4355 | FBytes (* Any int measure that counts bytes. *)
4356 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4357 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4359 (* Because we generate extra parsing code for LVM command line tools,
4360 * we have to pull out the LVM columns separately here.
4370 "pv_attr", FString (* XXX *);
4371 "pv_pe_count", FInt64;
4372 "pv_pe_alloc_count", FInt64;
4375 "pv_mda_count", FInt64;
4376 "pv_mda_free", FBytes;
4377 (* Not in Fedora 10:
4378 "pv_mda_size", FBytes;
4385 "vg_attr", FString (* XXX *);
4388 "vg_sysid", FString;
4389 "vg_extent_size", FBytes;
4390 "vg_extent_count", FInt64;
4391 "vg_free_count", FInt64;
4396 "snap_count", FInt64;
4399 "vg_mda_count", FInt64;
4400 "vg_mda_free", FBytes;
4401 (* Not in Fedora 10:
4402 "vg_mda_size", FBytes;
4408 "lv_attr", FString (* XXX *);
4411 "lv_kernel_major", FInt64;
4412 "lv_kernel_minor", FInt64;
4414 "seg_count", FInt64;
4416 "snap_percent", FOptPercent;
4417 "copy_percent", FOptPercent;
4420 "mirror_log", FString;
4424 (* Names and fields in all structures (in RStruct and RStructList)
4428 (* The old RIntBool return type, only ever used for aug_defnode. Do
4429 * not use this struct in any new code.
4432 "i", FInt32; (* for historical compatibility *)
4433 "b", FInt32; (* for historical compatibility *)
4436 (* LVM PVs, VGs, LVs. *)
4437 "lvm_pv", lvm_pv_cols;
4438 "lvm_vg", lvm_vg_cols;
4439 "lvm_lv", lvm_lv_cols;
4441 (* Column names and types from stat structures.
4442 * NB. Can't use things like 'st_atime' because glibc header files
4443 * define some of these as macros. Ugh.
4474 (* Column names in dirent structure. *)
4477 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4482 (* Version numbers. *)
4490 (* Extended attribute. *)
4492 "attrname", FString;
4496 (* Inotify events. *)
4500 "in_cookie", FUInt32;
4504 (* Partition table entry. *)
4507 "part_start", FBytes;
4509 "part_size", FBytes;
4511 ] (* end of structs *)
4513 (* Ugh, Java has to be different ..
4514 * These names are also used by the Haskell bindings.
4516 let java_structs = [
4517 "int_bool", "IntBool";
4522 "statvfs", "StatVFS";
4524 "version", "Version";
4526 "inotify_event", "INotifyEvent";
4527 "partition", "Partition";
4530 (* What structs are actually returned. *)
4531 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4533 (* Returns a list of RStruct/RStructList structs that are returned
4534 * by any function. Each element of returned list is a pair:
4536 * (structname, RStructOnly)
4537 * == there exists function which returns RStruct (_, structname)
4538 * (structname, RStructListOnly)
4539 * == there exists function which returns RStructList (_, structname)
4540 * (structname, RStructAndList)
4541 * == there are functions returning both RStruct (_, structname)
4542 * and RStructList (_, structname)
4544 let rstructs_used_by functions =
4545 (* ||| is a "logical OR" for rstructs_used_t *)
4549 | _, RStructAndList -> RStructAndList
4550 | RStructOnly, RStructListOnly
4551 | RStructListOnly, RStructOnly -> RStructAndList
4552 | RStructOnly, RStructOnly -> RStructOnly
4553 | RStructListOnly, RStructListOnly -> RStructListOnly
4556 let h = Hashtbl.create 13 in
4558 (* if elem->oldv exists, update entry using ||| operator,
4559 * else just add elem->newv to the hash
4561 let update elem newv =
4562 try let oldv = Hashtbl.find h elem in
4563 Hashtbl.replace h elem (newv ||| oldv)
4564 with Not_found -> Hashtbl.add h elem newv
4568 fun (_, style, _, _, _, _, _) ->
4569 match fst style with
4570 | RStruct (_, structname) -> update structname RStructOnly
4571 | RStructList (_, structname) -> update structname RStructListOnly
4575 (* return key->values as a list of (key,value) *)
4576 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4578 (* Used for testing language bindings. *)
4580 | CallString of string
4581 | CallOptString of string option
4582 | CallStringList of string list
4584 | CallInt64 of int64
4587 (* Used to memoize the result of pod2text. *)
4588 let pod2text_memo_filename = "src/.pod2text.data"
4589 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4591 let chan = open_in pod2text_memo_filename in
4592 let v = input_value chan in
4596 _ -> Hashtbl.create 13
4597 let pod2text_memo_updated () =
4598 let chan = open_out pod2text_memo_filename in
4599 output_value chan pod2text_memo;
4602 (* Useful functions.
4603 * Note we don't want to use any external OCaml libraries which
4604 * makes this a bit harder than it should be.
4606 module StringMap = Map.Make (String)
4608 let failwithf fs = ksprintf failwith fs
4610 let unique = let i = ref 0 in fun () -> incr i; !i
4612 let replace_char s c1 c2 =
4613 let s2 = String.copy s in
4614 let r = ref false in
4615 for i = 0 to String.length s2 - 1 do
4616 if String.unsafe_get s2 i = c1 then (
4617 String.unsafe_set s2 i c2;
4621 if not !r then s else s2
4625 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4627 let triml ?(test = isspace) str =
4629 let n = ref (String.length str) in
4630 while !n > 0 && test str.[!i]; do
4635 else String.sub str !i !n
4637 let trimr ?(test = isspace) str =
4638 let n = ref (String.length str) in
4639 while !n > 0 && test str.[!n-1]; do
4642 if !n = String.length str then str
4643 else String.sub str 0 !n
4645 let trim ?(test = isspace) str =
4646 trimr ~test (triml ~test str)
4648 let rec find s sub =
4649 let len = String.length s in
4650 let sublen = String.length sub in
4652 if i <= len-sublen then (
4654 if j < sublen then (
4655 if s.[i+j] = sub.[j] then loop2 (j+1)
4661 if r = -1 then loop (i+1) else r
4667 let rec replace_str s s1 s2 =
4668 let len = String.length s in
4669 let sublen = String.length s1 in
4670 let i = find s s1 in
4673 let s' = String.sub s 0 i in
4674 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4675 s' ^ s2 ^ replace_str s'' s1 s2
4678 let rec string_split sep str =
4679 let len = String.length str in
4680 let seplen = String.length sep in
4681 let i = find str sep in
4682 if i = -1 then [str]
4684 let s' = String.sub str 0 i in
4685 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4686 s' :: string_split sep s''
4689 let files_equal n1 n2 =
4690 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4691 match Sys.command cmd with
4694 | i -> failwithf "%s: failed with error code %d" cmd i
4696 let rec filter_map f = function
4700 | Some y -> y :: filter_map f xs
4701 | None -> filter_map f xs
4703 let rec find_map f = function
4704 | [] -> raise Not_found
4708 | None -> find_map f xs
4711 let rec loop i = function
4713 | x :: xs -> f i x; loop (i+1) xs
4718 let rec loop i = function
4720 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4724 let count_chars c str =
4725 let count = ref 0 in
4726 for i = 0 to String.length str - 1 do
4727 if c = String.unsafe_get str i then incr count
4731 let name_of_argt = function
4732 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4733 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4734 | FileIn n | FileOut n -> n
4736 let java_name_of_struct typ =
4737 try List.assoc typ java_structs
4740 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4742 let cols_of_struct typ =
4743 try List.assoc typ structs
4745 failwithf "cols_of_struct: unknown struct %s" typ
4747 let seq_of_test = function
4748 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4749 | TestOutputListOfDevices (s, _)
4750 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4751 | TestOutputTrue s | TestOutputFalse s
4752 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4753 | TestOutputStruct (s, _)
4754 | TestLastFail s -> s
4756 (* Handling for function flags. *)
4757 let protocol_limit_warning =
4758 "Because of the message protocol, there is a transfer limit
4759 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4761 let danger_will_robinson =
4762 "B<This command is dangerous. Without careful use you
4763 can easily destroy all your data>."
4765 let deprecation_notice flags =
4768 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4770 sprintf "This function is deprecated.
4771 In new code, use the C<%s> call instead.
4773 Deprecated functions will not be removed from the API, but the
4774 fact that they are deprecated indicates that there are problems
4775 with correct use of these functions." alt in
4780 (* Create list of optional groups. *)
4782 let h = Hashtbl.create 13 in
4784 fun (name, _, _, flags, _, _, _) ->
4788 let names = try Hashtbl.find h group with Not_found -> [] in
4789 Hashtbl.replace h group (name :: names)
4793 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4796 fun group -> group, List.sort compare (Hashtbl.find h group)
4798 List.sort (fun x y -> compare (fst x) (fst y)) groups
4800 (* Check function names etc. for consistency. *)
4801 let check_functions () =
4802 let contains_uppercase str =
4803 let len = String.length str in
4805 if i >= len then false
4808 if c >= 'A' && c <= 'Z' then true
4815 (* Check function names. *)
4817 fun (name, _, _, _, _, _, _) ->
4818 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4819 failwithf "function name %s does not need 'guestfs' prefix" name;
4821 failwithf "function name is empty";
4822 if name.[0] < 'a' || name.[0] > 'z' then
4823 failwithf "function name %s must start with lowercase a-z" name;
4824 if String.contains name '-' then
4825 failwithf "function name %s should not contain '-', use '_' instead."
4829 (* Check function parameter/return names. *)
4831 fun (name, style, _, _, _, _, _) ->
4832 let check_arg_ret_name n =
4833 if contains_uppercase n then
4834 failwithf "%s param/ret %s should not contain uppercase chars"
4836 if String.contains n '-' || String.contains n '_' then
4837 failwithf "%s param/ret %s should not contain '-' or '_'"
4840 failwithf "%s has a param/ret called 'value', which causes conflicts in the OCaml bindings, use something like 'val' or a more descriptive name" name;
4841 if n = "int" || n = "char" || n = "short" || n = "long" then
4842 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4843 if n = "i" || n = "n" then
4844 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4845 if n = "argv" || n = "args" then
4846 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4848 (* List Haskell, OCaml and C keywords here.
4849 * http://www.haskell.org/haskellwiki/Keywords
4850 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4851 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4852 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4853 * |perl -pe 's/(.+)/"$1";/'|fmt -70
4854 * Omitting _-containing words, since they're handled above.
4855 * Omitting the OCaml reserved word, "val", is ok,
4856 * and saves us from renaming several parameters.
4859 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4860 "char"; "class"; "const"; "constraint"; "continue"; "data";
4861 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4862 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4863 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4864 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4865 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4867 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4868 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4869 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4870 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4871 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4872 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4873 "volatile"; "when"; "where"; "while";
4875 if List.mem n reserved then
4876 failwithf "%s has param/ret using reserved word %s" name n;
4879 (match fst style with
4881 | RInt n | RInt64 n | RBool n
4882 | RConstString n | RConstOptString n | RString n
4883 | RStringList n | RStruct (n, _) | RStructList (n, _)
4884 | RHashtable n | RBufferOut n ->
4885 check_arg_ret_name n
4887 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4890 (* Check short descriptions. *)
4892 fun (name, _, _, _, _, shortdesc, _) ->
4893 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4894 failwithf "short description of %s should begin with lowercase." name;
4895 let c = shortdesc.[String.length shortdesc-1] in
4896 if c = '\n' || c = '.' then
4897 failwithf "short description of %s should not end with . or \\n." name
4900 (* Check long dscriptions. *)
4902 fun (name, _, _, _, _, _, longdesc) ->
4903 if longdesc.[String.length longdesc-1] = '\n' then
4904 failwithf "long description of %s should not end with \\n." name
4907 (* Check proc_nrs. *)
4909 fun (name, _, proc_nr, _, _, _, _) ->
4910 if proc_nr <= 0 then
4911 failwithf "daemon function %s should have proc_nr > 0" name
4915 fun (name, _, proc_nr, _, _, _, _) ->
4916 if proc_nr <> -1 then
4917 failwithf "non-daemon function %s should have proc_nr -1" name
4918 ) non_daemon_functions;
4921 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4924 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4925 let rec loop = function
4928 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4930 | (name1,nr1) :: (name2,nr2) :: _ ->
4931 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4939 (* Ignore functions that have no tests. We generate a
4940 * warning when the user does 'make check' instead.
4942 | name, _, _, _, [], _, _ -> ()
4943 | name, _, _, _, tests, _, _ ->
4947 match seq_of_test test with
4949 failwithf "%s has a test containing an empty sequence" name
4950 | cmds -> List.map List.hd cmds
4952 let funcs = List.flatten funcs in
4954 let tested = List.mem name funcs in
4957 failwithf "function %s has tests but does not test itself" name
4960 (* 'pr' prints to the current output file. *)
4961 let chan = ref Pervasives.stdout
4966 let i = count_chars '\n' str in
4967 lines := !lines + i;
4968 output_string !chan str
4971 let copyright_years =
4972 let this_year = 1900 + (localtime (time ())).tm_year in
4973 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
4975 (* Generate a header block in a number of standard styles. *)
4976 type comment_style =
4977 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
4978 type license = GPLv2plus | LGPLv2plus
4980 let generate_header ?(extra_inputs = []) comment license =
4981 let inputs = "src/generator.ml" :: extra_inputs in
4982 let c = match comment with
4983 | CStyle -> pr "/* "; " *"
4984 | CPlusPlusStyle -> pr "// "; "//"
4985 | HashStyle -> pr "# "; "#"
4986 | OCamlStyle -> pr "(* "; " *"
4987 | HaskellStyle -> pr "{- "; " " in
4988 pr "libguestfs generated file\n";
4989 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
4990 List.iter (pr "%s %s\n" c) inputs;
4991 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4993 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
4997 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4998 pr "%s it under the terms of the GNU General Public License as published by\n" c;
4999 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5000 pr "%s (at your option) any later version.\n" c;
5002 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5003 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5004 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5005 pr "%s GNU General Public License for more details.\n" c;
5007 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5008 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5009 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5012 pr "%s This library is free software; you can redistribute it and/or\n" c;
5013 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5014 pr "%s License as published by the Free Software Foundation; either\n" c;
5015 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5017 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5018 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5019 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5020 pr "%s Lesser General Public License for more details.\n" c;
5022 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5023 pr "%s License along with this library; if not, write to the Free Software\n" c;
5024 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5027 | CStyle -> pr " */\n"
5030 | OCamlStyle -> pr " *)\n"
5031 | HaskellStyle -> pr "-}\n"
5035 (* Start of main code generation functions below this line. *)
5037 (* Generate the pod documentation for the C API. *)
5038 let rec generate_actions_pod () =
5040 fun (shortname, style, _, flags, _, _, longdesc) ->
5041 if not (List.mem NotInDocs flags) then (
5042 let name = "guestfs_" ^ shortname in
5043 pr "=head2 %s\n\n" name;
5045 generate_prototype ~extern:false ~handle:"handle" name style;
5047 pr "%s\n\n" longdesc;
5048 (match fst style with
5050 pr "This function returns 0 on success or -1 on error.\n\n"
5052 pr "On error this function returns -1.\n\n"
5054 pr "On error this function returns -1.\n\n"
5056 pr "This function returns a C truth value on success or -1 on error.\n\n"
5058 pr "This function returns a string, or NULL on error.
5059 The string is owned by the guest handle and must I<not> be freed.\n\n"
5060 | RConstOptString _ ->
5061 pr "This function returns a string which may be NULL.
5062 There is way to return an error from this function.
5063 The string is owned by the guest handle and must I<not> be freed.\n\n"
5065 pr "This function returns a string, or NULL on error.
5066 I<The caller must free the returned string after use>.\n\n"
5068 pr "This function returns a NULL-terminated array of strings
5069 (like L<environ(3)>), or NULL if there was an error.
5070 I<The caller must free the strings and the array after use>.\n\n"
5071 | RStruct (_, typ) ->
5072 pr "This function returns a C<struct guestfs_%s *>,
5073 or NULL if there was an error.
5074 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5075 | RStructList (_, typ) ->
5076 pr "This function returns a C<struct guestfs_%s_list *>
5077 (see E<lt>guestfs-structs.hE<gt>),
5078 or NULL if there was an error.
5079 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5081 pr "This function returns a NULL-terminated array of
5082 strings, or NULL if there was an error.
5083 The array of strings will always have length C<2n+1>, where
5084 C<n> keys and values alternate, followed by the trailing NULL entry.
5085 I<The caller must free the strings and the array after use>.\n\n"
5087 pr "This function returns a buffer, or NULL on error.
5088 The size of the returned buffer is written to C<*size_r>.
5089 I<The caller must free the returned buffer after use>.\n\n"
5091 if List.mem ProtocolLimitWarning flags then
5092 pr "%s\n\n" protocol_limit_warning;
5093 if List.mem DangerWillRobinson flags then
5094 pr "%s\n\n" danger_will_robinson;
5095 match deprecation_notice flags with
5097 | Some txt -> pr "%s\n\n" txt
5099 ) all_functions_sorted
5101 and generate_structs_pod () =
5102 (* Structs documentation. *)
5105 pr "=head2 guestfs_%s\n" typ;
5107 pr " struct guestfs_%s {\n" typ;
5110 | name, FChar -> pr " char %s;\n" name
5111 | name, FUInt32 -> pr " uint32_t %s;\n" name
5112 | name, FInt32 -> pr " int32_t %s;\n" name
5113 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5114 | name, FInt64 -> pr " int64_t %s;\n" name
5115 | name, FString -> pr " char *%s;\n" name
5117 pr " /* The next two fields describe a byte array. */\n";
5118 pr " uint32_t %s_len;\n" name;
5119 pr " char *%s;\n" name
5121 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5122 pr " char %s[32];\n" name
5123 | name, FOptPercent ->
5124 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5125 pr " float %s;\n" name
5129 pr " struct guestfs_%s_list {\n" typ;
5130 pr " uint32_t len; /* Number of elements in list. */\n";
5131 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5134 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5135 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5140 and generate_availability_pod () =
5141 (* Availability documentation. *)
5145 fun (group, functions) ->
5146 pr "=item B<%s>\n" group;
5148 pr "The following functions:\n";
5149 List.iter (pr "L</guestfs_%s>\n") functions;
5155 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5156 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5158 * We have to use an underscore instead of a dash because otherwise
5159 * rpcgen generates incorrect code.
5161 * This header is NOT exported to clients, but see also generate_structs_h.
5163 and generate_xdr () =
5164 generate_header CStyle LGPLv2plus;
5166 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5167 pr "typedef string str<>;\n";
5170 (* Internal structures. *)
5174 pr "struct guestfs_int_%s {\n" typ;
5176 | name, FChar -> pr " char %s;\n" name
5177 | name, FString -> pr " string %s<>;\n" name
5178 | name, FBuffer -> pr " opaque %s<>;\n" name
5179 | name, FUUID -> pr " opaque %s[32];\n" name
5180 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5181 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5182 | name, FOptPercent -> pr " float %s;\n" name
5186 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5191 fun (shortname, style, _, _, _, _, _) ->
5192 let name = "guestfs_" ^ shortname in
5194 (match snd style with
5197 pr "struct %s_args {\n" name;
5200 | Pathname n | Device n | Dev_or_Path n | String n ->
5201 pr " string %s<>;\n" n
5202 | OptString n -> pr " str *%s;\n" n
5203 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5204 | Bool n -> pr " bool %s;\n" n
5205 | Int n -> pr " int %s;\n" n
5206 | Int64 n -> pr " hyper %s;\n" n
5207 | FileIn _ | FileOut _ -> ()
5211 (match fst style with
5214 pr "struct %s_ret {\n" name;
5218 pr "struct %s_ret {\n" name;
5219 pr " hyper %s;\n" n;
5222 pr "struct %s_ret {\n" name;
5225 | RConstString _ | RConstOptString _ ->
5226 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5228 pr "struct %s_ret {\n" name;
5229 pr " string %s<>;\n" n;
5232 pr "struct %s_ret {\n" name;
5233 pr " str %s<>;\n" n;
5235 | RStruct (n, typ) ->
5236 pr "struct %s_ret {\n" name;
5237 pr " guestfs_int_%s %s;\n" typ n;
5239 | RStructList (n, typ) ->
5240 pr "struct %s_ret {\n" name;
5241 pr " guestfs_int_%s_list %s;\n" typ n;
5244 pr "struct %s_ret {\n" name;
5245 pr " str %s<>;\n" n;
5248 pr "struct %s_ret {\n" name;
5249 pr " opaque %s<>;\n" n;
5254 (* Table of procedure numbers. *)
5255 pr "enum guestfs_procedure {\n";
5257 fun (shortname, _, proc_nr, _, _, _, _) ->
5258 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5260 pr " GUESTFS_PROC_NR_PROCS\n";
5264 (* Having to choose a maximum message size is annoying for several
5265 * reasons (it limits what we can do in the API), but it (a) makes
5266 * the protocol a lot simpler, and (b) provides a bound on the size
5267 * of the daemon which operates in limited memory space.
5269 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5272 (* Message header, etc. *)
5274 /* The communication protocol is now documented in the guestfs(3)
5278 const GUESTFS_PROGRAM = 0x2000F5F5;
5279 const GUESTFS_PROTOCOL_VERSION = 1;
5281 /* These constants must be larger than any possible message length. */
5282 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5283 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5285 enum guestfs_message_direction {
5286 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5287 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5290 enum guestfs_message_status {
5291 GUESTFS_STATUS_OK = 0,
5292 GUESTFS_STATUS_ERROR = 1
5295 const GUESTFS_ERROR_LEN = 256;
5297 struct guestfs_message_error {
5298 string error_message<GUESTFS_ERROR_LEN>;
5301 struct guestfs_message_header {
5302 unsigned prog; /* GUESTFS_PROGRAM */
5303 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5304 guestfs_procedure proc; /* GUESTFS_PROC_x */
5305 guestfs_message_direction direction;
5306 unsigned serial; /* message serial number */
5307 guestfs_message_status status;
5310 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5312 struct guestfs_chunk {
5313 int cancel; /* if non-zero, transfer is cancelled */
5314 /* data size is 0 bytes if the transfer has finished successfully */
5315 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5319 (* Generate the guestfs-structs.h file. *)
5320 and generate_structs_h () =
5321 generate_header CStyle LGPLv2plus;
5323 (* This is a public exported header file containing various
5324 * structures. The structures are carefully written to have
5325 * exactly the same in-memory format as the XDR structures that
5326 * we use on the wire to the daemon. The reason for creating
5327 * copies of these structures here is just so we don't have to
5328 * export the whole of guestfs_protocol.h (which includes much
5329 * unrelated and XDR-dependent stuff that we don't want to be
5330 * public, or required by clients).
5332 * To reiterate, we will pass these structures to and from the
5333 * client with a simple assignment or memcpy, so the format
5334 * must be identical to what rpcgen / the RFC defines.
5337 (* Public structures. *)
5340 pr "struct guestfs_%s {\n" typ;
5343 | name, FChar -> pr " char %s;\n" name
5344 | name, FString -> pr " char *%s;\n" name
5346 pr " uint32_t %s_len;\n" name;
5347 pr " char *%s;\n" name
5348 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5349 | name, FUInt32 -> pr " uint32_t %s;\n" name
5350 | name, FInt32 -> pr " int32_t %s;\n" name
5351 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5352 | name, FInt64 -> pr " int64_t %s;\n" name
5353 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5357 pr "struct guestfs_%s_list {\n" typ;
5358 pr " uint32_t len;\n";
5359 pr " struct guestfs_%s *val;\n" typ;
5362 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5363 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5367 (* Generate the guestfs-actions.h file. *)
5368 and generate_actions_h () =
5369 generate_header CStyle LGPLv2plus;
5371 fun (shortname, style, _, _, _, _, _) ->
5372 let name = "guestfs_" ^ shortname in
5373 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5377 (* Generate the guestfs-internal-actions.h file. *)
5378 and generate_internal_actions_h () =
5379 generate_header CStyle LGPLv2plus;
5381 fun (shortname, style, _, _, _, _, _) ->
5382 let name = "guestfs__" ^ shortname in
5383 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5385 ) non_daemon_functions
5387 (* Generate the client-side dispatch stubs. *)
5388 and generate_client_actions () =
5389 generate_header CStyle LGPLv2plus;
5395 #include <inttypes.h>
5397 #include \"guestfs.h\"
5398 #include \"guestfs-internal.h\"
5399 #include \"guestfs-internal-actions.h\"
5400 #include \"guestfs_protocol.h\"
5402 #define error guestfs_error
5403 //#define perrorf guestfs_perrorf
5404 #define safe_malloc guestfs_safe_malloc
5405 #define safe_realloc guestfs_safe_realloc
5406 //#define safe_strdup guestfs_safe_strdup
5407 #define safe_memdup guestfs_safe_memdup
5409 /* Check the return message from a call for validity. */
5411 check_reply_header (guestfs_h *g,
5412 const struct guestfs_message_header *hdr,
5413 unsigned int proc_nr, unsigned int serial)
5415 if (hdr->prog != GUESTFS_PROGRAM) {
5416 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5419 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5420 error (g, \"wrong protocol version (%%d/%%d)\",
5421 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5424 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5425 error (g, \"unexpected message direction (%%d/%%d)\",
5426 hdr->direction, GUESTFS_DIRECTION_REPLY);
5429 if (hdr->proc != proc_nr) {
5430 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5433 if (hdr->serial != serial) {
5434 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5441 /* Check we are in the right state to run a high-level action. */
5443 check_state (guestfs_h *g, const char *caller)
5445 if (!guestfs__is_ready (g)) {
5446 if (guestfs__is_config (g) || guestfs__is_launching (g))
5447 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5450 error (g, \"%%s called from the wrong state, %%d != READY\",
5451 caller, guestfs__get_state (g));
5459 (* Generate code to generate guestfish call traces. *)
5460 let trace_call shortname style =
5461 pr " if (guestfs__get_trace (g)) {\n";
5464 List.exists (function
5465 | StringList _ | DeviceList _ -> true
5466 | _ -> false) (snd style) in
5472 pr " printf (\"%s\");\n" shortname;
5475 | String n (* strings *)
5481 (* guestfish doesn't support string escaping, so neither do we *)
5482 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5483 | OptString n -> (* string option *)
5484 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5485 pr " else printf (\" null\");\n"
5487 | DeviceList n -> (* string list *)
5488 pr " putchar (' ');\n";
5489 pr " putchar ('\"');\n";
5490 pr " for (i = 0; %s[i]; ++i) {\n" n;
5491 pr " if (i > 0) putchar (' ');\n";
5492 pr " fputs (%s[i], stdout);\n" n;
5494 pr " putchar ('\"');\n";
5495 | Bool n -> (* boolean *)
5496 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5497 | Int n -> (* int *)
5498 pr " printf (\" %%d\", %s);\n" n
5500 pr " printf (\" %%\" PRIi64, %s);\n" n
5502 pr " putchar ('\\n');\n";
5507 (* For non-daemon functions, generate a wrapper around each function. *)
5509 fun (shortname, style, _, _, _, _, _) ->
5510 let name = "guestfs_" ^ shortname in
5512 generate_prototype ~extern:false ~semicolon:false ~newline:true
5513 ~handle:"g" name style;
5515 trace_call shortname style;
5516 pr " return guestfs__%s " shortname;
5517 generate_c_call_args ~handle:"g" style;
5521 ) non_daemon_functions;
5523 (* Client-side stubs for each function. *)
5525 fun (shortname, style, _, _, _, _, _) ->
5526 let name = "guestfs_" ^ shortname in
5528 (* Generate the action stub. *)
5529 generate_prototype ~extern:false ~semicolon:false ~newline:true
5530 ~handle:"g" name style;
5533 match fst style with
5534 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5535 | RConstString _ | RConstOptString _ ->
5536 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5537 | RString _ | RStringList _
5538 | RStruct _ | RStructList _
5539 | RHashtable _ | RBufferOut _ ->
5544 (match snd style with
5546 | _ -> pr " struct %s_args args;\n" name
5549 pr " guestfs_message_header hdr;\n";
5550 pr " guestfs_message_error err;\n";
5552 match fst style with
5554 | RConstString _ | RConstOptString _ ->
5555 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5557 | RBool _ | RString _ | RStringList _
5558 | RStruct _ | RStructList _
5559 | RHashtable _ | RBufferOut _ ->
5560 pr " struct %s_ret ret;\n" name;
5563 pr " int serial;\n";
5566 trace_call shortname style;
5567 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5568 pr " guestfs___set_busy (g);\n";
5571 (* Send the main header and arguments. *)
5572 (match snd style with
5574 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5575 (String.uppercase shortname)
5579 | Pathname n | Device n | Dev_or_Path n | String n ->
5580 pr " args.%s = (char *) %s;\n" n n
5582 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5583 | StringList n | DeviceList n ->
5584 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5585 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5587 pr " args.%s = %s;\n" n n
5589 pr " args.%s = %s;\n" n n
5591 pr " args.%s = %s;\n" n n
5592 | FileIn _ | FileOut _ -> ()
5594 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5595 (String.uppercase shortname);
5596 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5599 pr " if (serial == -1) {\n";
5600 pr " guestfs___end_busy (g);\n";
5601 pr " return %s;\n" error_code;
5605 (* Send any additional files (FileIn) requested. *)
5606 let need_read_reply_label = ref false in
5610 pr " r = guestfs___send_file (g, %s);\n" n;
5611 pr " if (r == -1) {\n";
5612 pr " guestfs___end_busy (g);\n";
5613 pr " return %s;\n" error_code;
5615 pr " if (r == -2) /* daemon cancelled */\n";
5616 pr " goto read_reply;\n";
5617 need_read_reply_label := true;
5622 (* Wait for the reply from the remote end. *)
5623 if !need_read_reply_label then pr " read_reply:\n";
5624 pr " memset (&hdr, 0, sizeof hdr);\n";
5625 pr " memset (&err, 0, sizeof err);\n";
5626 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5628 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5632 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5635 pr " if (r == -1) {\n";
5636 pr " guestfs___end_busy (g);\n";
5637 pr " return %s;\n" error_code;
5641 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5642 (String.uppercase shortname);
5643 pr " guestfs___end_busy (g);\n";
5644 pr " return %s;\n" error_code;
5648 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5649 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5650 pr " free (err.error_message);\n";
5651 pr " guestfs___end_busy (g);\n";
5652 pr " return %s;\n" error_code;
5656 (* Expecting to receive further files (FileOut)? *)
5660 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5661 pr " guestfs___end_busy (g);\n";
5662 pr " return %s;\n" error_code;
5668 pr " guestfs___end_busy (g);\n";
5670 (match fst style with
5671 | RErr -> pr " return 0;\n"
5672 | RInt n | RInt64 n | RBool n ->
5673 pr " return ret.%s;\n" n
5674 | RConstString _ | RConstOptString _ ->
5675 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5677 pr " return ret.%s; /* caller will free */\n" n
5678 | RStringList n | RHashtable n ->
5679 pr " /* caller will free this, but we need to add a NULL entry */\n";
5680 pr " ret.%s.%s_val =\n" n n;
5681 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5682 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5684 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5685 pr " return ret.%s.%s_val;\n" n n
5687 pr " /* caller will free this */\n";
5688 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5689 | RStructList (n, _) ->
5690 pr " /* caller will free this */\n";
5691 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5693 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5694 pr " * _val might be NULL here. To make the API saner for\n";
5695 pr " * callers, we turn this case into a unique pointer (using\n";
5696 pr " * malloc(1)).\n";
5698 pr " if (ret.%s.%s_len > 0) {\n" n n;
5699 pr " *size_r = ret.%s.%s_len;\n" n n;
5700 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5702 pr " free (ret.%s.%s_val);\n" n n;
5703 pr " char *p = safe_malloc (g, 1);\n";
5704 pr " *size_r = ret.%s.%s_len;\n" n n;
5712 (* Functions to free structures. *)
5713 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5714 pr " * structure format is identical to the XDR format. See note in\n";
5715 pr " * generator.ml.\n";
5722 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5724 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5730 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5732 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5739 (* Generate daemon/actions.h. *)
5740 and generate_daemon_actions_h () =
5741 generate_header CStyle GPLv2plus;
5743 pr "#include \"../src/guestfs_protocol.h\"\n";
5747 fun (name, style, _, _, _, _, _) ->
5749 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5753 (* Generate the linker script which controls the visibility of
5754 * symbols in the public ABI and ensures no other symbols get
5755 * exported accidentally.
5757 and generate_linker_script () =
5758 generate_header HashStyle GPLv2plus;
5763 "guestfs_get_error_handler";
5764 "guestfs_get_out_of_memory_handler";
5765 "guestfs_last_error";
5766 "guestfs_set_error_handler";
5767 "guestfs_set_launch_done_callback";
5768 "guestfs_set_log_message_callback";
5769 "guestfs_set_out_of_memory_handler";
5770 "guestfs_set_subprocess_quit_callback";
5772 (* Unofficial parts of the API: the bindings code use these
5773 * functions, so it is useful to export them.
5775 "guestfs_safe_calloc";
5776 "guestfs_safe_malloc";
5779 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5783 List.map (fun (typ, _) ->
5784 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5787 let globals = List.sort compare (globals @ functions @ structs) in
5791 List.iter (pr " %s;\n") globals;
5798 (* Generate the server-side stubs. *)
5799 and generate_daemon_actions () =
5800 generate_header CStyle GPLv2plus;
5802 pr "#include <config.h>\n";
5804 pr "#include <stdio.h>\n";
5805 pr "#include <stdlib.h>\n";
5806 pr "#include <string.h>\n";
5807 pr "#include <inttypes.h>\n";
5808 pr "#include <rpc/types.h>\n";
5809 pr "#include <rpc/xdr.h>\n";
5811 pr "#include \"daemon.h\"\n";
5812 pr "#include \"c-ctype.h\"\n";
5813 pr "#include \"../src/guestfs_protocol.h\"\n";
5814 pr "#include \"actions.h\"\n";
5818 fun (name, style, _, _, _, _, _) ->
5819 (* Generate server-side stubs. *)
5820 pr "static void %s_stub (XDR *xdr_in)\n" name;
5823 match fst style with
5824 | RErr | RInt _ -> pr " int r;\n"; "-1"
5825 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5826 | RBool _ -> pr " int r;\n"; "-1"
5827 | RConstString _ | RConstOptString _ ->
5828 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5829 | RString _ -> pr " char *r;\n"; "NULL"
5830 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
5831 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
5832 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
5834 pr " size_t size = 1;\n";
5838 (match snd style with
5841 pr " struct guestfs_%s_args args;\n" name;
5844 | Device n | Dev_or_Path n
5847 | OptString n -> pr " char *%s;\n" n
5848 | StringList n | DeviceList n -> pr " char **%s;\n" n
5849 | Bool n -> pr " int %s;\n" n
5850 | Int n -> pr " int %s;\n" n
5851 | Int64 n -> pr " int64_t %s;\n" n
5852 | FileIn _ | FileOut _ -> ()
5857 (match snd style with
5860 pr " memset (&args, 0, sizeof args);\n";
5862 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5863 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5867 pr " char *%s = args.%s;\n" n n
5869 let pr_list_handling_code n =
5870 pr " %s = realloc (args.%s.%s_val,\n" n n n;
5871 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5872 pr " if (%s == NULL) {\n" n;
5873 pr " reply_with_perror (\"realloc\");\n";
5876 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
5877 pr " args.%s.%s_val = %s;\n" n n n;
5883 pr " ABS_PATH (%s, goto done);\n" n;
5886 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
5889 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5890 | String n -> pr_args n
5891 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
5893 pr_list_handling_code n;
5895 pr_list_handling_code n;
5896 pr " /* Ensure that each is a device,\n";
5897 pr " * and perform device name translation. */\n";
5898 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5899 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5901 | Bool n -> pr " %s = args.%s;\n" n n
5902 | Int n -> pr " %s = args.%s;\n" n n
5903 | Int64 n -> pr " %s = args.%s;\n" n n
5904 | FileIn _ | FileOut _ -> ()
5910 (* this is used at least for do_equal *)
5911 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5912 (* Emit NEED_ROOT just once, even when there are two or
5913 more Pathname args *)
5914 pr " NEED_ROOT (goto done);\n";
5917 (* Don't want to call the impl with any FileIn or FileOut
5918 * parameters, since these go "outside" the RPC protocol.
5921 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5923 pr " r = do_%s " name;
5924 generate_c_call_args (fst style, args');
5927 (match fst style with
5928 | RErr | RInt _ | RInt64 _ | RBool _
5929 | RConstString _ | RConstOptString _
5930 | RString _ | RStringList _ | RHashtable _
5931 | RStruct (_, _) | RStructList (_, _) ->
5932 pr " if (r == %s)\n" error_code;
5933 pr " /* do_%s has already called reply_with_error */\n" name;
5937 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
5938 pr " * an ordinary zero-length buffer), so be careful ...\n";
5940 pr " if (size == 1 && r == %s)\n" error_code;
5941 pr " /* do_%s has already called reply_with_error */\n" name;
5946 (* If there are any FileOut parameters, then the impl must
5947 * send its own reply.
5950 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5952 pr " /* do_%s has already sent a reply */\n" name
5954 match fst style with
5955 | RErr -> pr " reply (NULL, NULL);\n"
5956 | RInt n | RInt64 n | RBool n ->
5957 pr " struct guestfs_%s_ret ret;\n" name;
5958 pr " ret.%s = r;\n" n;
5959 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5961 | RConstString _ | RConstOptString _ ->
5962 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5964 pr " struct guestfs_%s_ret ret;\n" name;
5965 pr " ret.%s = r;\n" n;
5966 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5969 | RStringList n | RHashtable n ->
5970 pr " struct guestfs_%s_ret ret;\n" name;
5971 pr " ret.%s.%s_len = count_strings (r);\n" n n;
5972 pr " ret.%s.%s_val = r;\n" n n;
5973 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5975 pr " free_strings (r);\n"
5977 pr " struct guestfs_%s_ret ret;\n" name;
5978 pr " ret.%s = *r;\n" n;
5979 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5981 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5983 | RStructList (n, _) ->
5984 pr " struct guestfs_%s_ret ret;\n" name;
5985 pr " ret.%s = *r;\n" n;
5986 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5988 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5991 pr " struct guestfs_%s_ret ret;\n" name;
5992 pr " ret.%s.%s_val = r;\n" n n;
5993 pr " ret.%s.%s_len = size;\n" n n;
5994 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5999 (* Free the args. *)
6000 (match snd style with
6005 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6012 (* Dispatch function. *)
6013 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6015 pr " switch (proc_nr) {\n";
6018 fun (name, style, _, _, _, _, _) ->
6019 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6020 pr " %s_stub (xdr_in);\n" name;
6025 pr " reply_with_error (\"dispatch_incoming_message: unknown procedure number %%d, set LIBGUESTFS_PATH to point to the matching libguestfs appliance directory\", proc_nr);\n";
6030 (* LVM columns and tokenization functions. *)
6031 (* XXX This generates crap code. We should rethink how we
6037 pr "static const char *lvm_%s_cols = \"%s\";\n"
6038 typ (String.concat "," (List.map fst cols));
6041 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6043 pr " char *tok, *p, *next;\n";
6047 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6050 pr " if (!str) {\n";
6051 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6054 pr " if (!*str || c_isspace (*str)) {\n";
6055 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6060 fun (name, coltype) ->
6061 pr " if (!tok) {\n";
6062 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6065 pr " p = strchrnul (tok, ',');\n";
6066 pr " if (*p) next = p+1; else next = NULL;\n";
6067 pr " *p = '\\0';\n";
6070 pr " r->%s = strdup (tok);\n" name;
6071 pr " if (r->%s == NULL) {\n" name;
6072 pr " perror (\"strdup\");\n";
6076 pr " for (i = j = 0; i < 32; ++j) {\n";
6077 pr " if (tok[j] == '\\0') {\n";
6078 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6080 pr " } else if (tok[j] != '-')\n";
6081 pr " r->%s[i++] = tok[j];\n" name;
6084 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6085 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6089 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6090 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6094 pr " if (tok[0] == '\\0')\n";
6095 pr " r->%s = -1;\n" name;
6096 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6097 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6100 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6101 assert false (* can never be an LVM column *)
6103 pr " tok = next;\n";
6106 pr " if (tok != NULL) {\n";
6107 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6114 pr "guestfs_int_lvm_%s_list *\n" typ;
6115 pr "parse_command_line_%ss (void)\n" typ;
6117 pr " char *out, *err;\n";
6118 pr " char *p, *pend;\n";
6120 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6121 pr " void *newp;\n";
6123 pr " ret = malloc (sizeof *ret);\n";
6124 pr " if (!ret) {\n";
6125 pr " reply_with_perror (\"malloc\");\n";
6126 pr " return NULL;\n";
6129 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6130 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6132 pr " r = command (&out, &err,\n";
6133 pr " \"/sbin/lvm\", \"%ss\",\n" typ;
6134 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6135 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6136 pr " if (r == -1) {\n";
6137 pr " reply_with_error (\"%%s\", err);\n";
6138 pr " free (out);\n";
6139 pr " free (err);\n";
6140 pr " free (ret);\n";
6141 pr " return NULL;\n";
6144 pr " free (err);\n";
6146 pr " /* Tokenize each line of the output. */\n";
6149 pr " while (p) {\n";
6150 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6151 pr " if (pend) {\n";
6152 pr " *pend = '\\0';\n";
6156 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6159 pr " if (!*p) { /* Empty line? Skip it. */\n";
6164 pr " /* Allocate some space to store this next entry. */\n";
6165 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6166 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6167 pr " if (newp == NULL) {\n";
6168 pr " reply_with_perror (\"realloc\");\n";
6169 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6170 pr " free (ret);\n";
6171 pr " free (out);\n";
6172 pr " return NULL;\n";
6174 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6176 pr " /* Tokenize the next entry. */\n";
6177 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6178 pr " if (r == -1) {\n";
6179 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6180 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6181 pr " free (ret);\n";
6182 pr " free (out);\n";
6183 pr " return NULL;\n";
6190 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6192 pr " free (out);\n";
6193 pr " return ret;\n";
6196 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6198 (* Generate a list of function names, for debugging in the daemon.. *)
6199 and generate_daemon_names () =
6200 generate_header CStyle GPLv2plus;
6202 pr "#include <config.h>\n";
6204 pr "#include \"daemon.h\"\n";
6207 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6208 pr "const char *function_names[] = {\n";
6210 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6214 (* Generate the optional groups for the daemon to implement
6215 * guestfs_available.
6217 and generate_daemon_optgroups_c () =
6218 generate_header CStyle GPLv2plus;
6220 pr "#include <config.h>\n";
6222 pr "#include \"daemon.h\"\n";
6223 pr "#include \"optgroups.h\"\n";
6226 pr "struct optgroup optgroups[] = {\n";
6229 pr " { \"%s\", optgroup_%s_available },\n" group group
6231 pr " { NULL, NULL }\n";
6234 and generate_daemon_optgroups_h () =
6235 generate_header CStyle GPLv2plus;
6239 pr "extern int optgroup_%s_available (void);\n" group
6242 (* Generate the tests. *)
6243 and generate_tests () =
6244 generate_header CStyle GPLv2plus;
6251 #include <sys/types.h>
6254 #include \"guestfs.h\"
6255 #include \"guestfs-internal.h\"
6257 static guestfs_h *g;
6258 static int suppress_error = 0;
6260 static void print_error (guestfs_h *g, void *data, const char *msg)
6262 if (!suppress_error)
6263 fprintf (stderr, \"%%s\\n\", msg);
6266 /* FIXME: nearly identical code appears in fish.c */
6267 static void print_strings (char *const *argv)
6271 for (argc = 0; argv[argc] != NULL; ++argc)
6272 printf (\"\\t%%s\\n\", argv[argc]);
6276 static void print_table (char const *const *argv)
6280 for (i = 0; argv[i] != NULL; i += 2)
6281 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6287 (* Generate a list of commands which are not tested anywhere. *)
6288 pr "static void no_test_warnings (void)\n";
6291 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6293 fun (_, _, _, _, tests, _, _) ->
6294 let tests = filter_map (
6296 | (_, (Always|If _|Unless _), test) -> Some test
6297 | (_, Disabled, _) -> None
6299 let seq = List.concat (List.map seq_of_test tests) in
6300 let cmds_tested = List.map List.hd seq in
6301 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6305 fun (name, _, _, _, _, _, _) ->
6306 if not (Hashtbl.mem hash name) then
6307 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6313 (* Generate the actual tests. Note that we generate the tests
6314 * in reverse order, deliberately, so that (in general) the
6315 * newest tests run first. This makes it quicker and easier to
6320 fun (name, _, _, flags, tests, _, _) ->
6321 mapi (generate_one_test name flags) tests
6322 ) (List.rev all_functions) in
6323 let test_names = List.concat test_names in
6324 let nr_tests = List.length test_names in
6327 int main (int argc, char *argv[])
6330 unsigned long int n_failed = 0;
6331 const char *filename;
6333 int nr_tests, test_num = 0;
6335 setbuf (stdout, NULL);
6337 no_test_warnings ();
6339 g = guestfs_create ();
6341 printf (\"guestfs_create FAILED\\n\");
6342 exit (EXIT_FAILURE);
6345 guestfs_set_error_handler (g, print_error, NULL);
6347 guestfs_set_path (g, \"../appliance\");
6349 filename = \"test1.img\";
6350 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6353 exit (EXIT_FAILURE);
6355 if (lseek (fd, %d, SEEK_SET) == -1) {
6359 exit (EXIT_FAILURE);
6361 if (write (fd, &c, 1) == -1) {
6365 exit (EXIT_FAILURE);
6367 if (close (fd) == -1) {
6370 exit (EXIT_FAILURE);
6372 if (guestfs_add_drive (g, filename) == -1) {
6373 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6374 exit (EXIT_FAILURE);
6377 filename = \"test2.img\";
6378 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6381 exit (EXIT_FAILURE);
6383 if (lseek (fd, %d, SEEK_SET) == -1) {
6387 exit (EXIT_FAILURE);
6389 if (write (fd, &c, 1) == -1) {
6393 exit (EXIT_FAILURE);
6395 if (close (fd) == -1) {
6398 exit (EXIT_FAILURE);
6400 if (guestfs_add_drive (g, filename) == -1) {
6401 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6402 exit (EXIT_FAILURE);
6405 filename = \"test3.img\";
6406 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6409 exit (EXIT_FAILURE);
6411 if (lseek (fd, %d, SEEK_SET) == -1) {
6415 exit (EXIT_FAILURE);
6417 if (write (fd, &c, 1) == -1) {
6421 exit (EXIT_FAILURE);
6423 if (close (fd) == -1) {
6426 exit (EXIT_FAILURE);
6428 if (guestfs_add_drive (g, filename) == -1) {
6429 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6430 exit (EXIT_FAILURE);
6433 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6434 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6435 exit (EXIT_FAILURE);
6438 if (guestfs_launch (g) == -1) {
6439 printf (\"guestfs_launch FAILED\\n\");
6440 exit (EXIT_FAILURE);
6443 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6446 /* Cancel previous alarm. */
6451 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6455 pr " test_num++;\n";
6456 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6457 pr " if (%s () == -1) {\n" test_name;
6458 pr " printf (\"%s FAILED\\n\");\n" test_name;
6459 pr " n_failed++;\n";
6464 pr " guestfs_close (g);\n";
6465 pr " unlink (\"test1.img\");\n";
6466 pr " unlink (\"test2.img\");\n";
6467 pr " unlink (\"test3.img\");\n";
6470 pr " if (n_failed > 0) {\n";
6471 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6472 pr " exit (EXIT_FAILURE);\n";
6476 pr " exit (EXIT_SUCCESS);\n";
6479 and generate_one_test name flags i (init, prereq, test) =
6480 let test_name = sprintf "test_%s_%d" name i in
6483 static int %s_skip (void)
6487 str = getenv (\"TEST_ONLY\");
6489 return strstr (str, \"%s\") == NULL;
6490 str = getenv (\"SKIP_%s\");
6491 if (str && STREQ (str, \"1\")) return 1;
6492 str = getenv (\"SKIP_TEST_%s\");
6493 if (str && STREQ (str, \"1\")) return 1;
6497 " test_name name (String.uppercase test_name) (String.uppercase name);
6500 | Disabled | Always -> ()
6501 | If code | Unless code ->
6502 pr "static int %s_prereq (void)\n" test_name;
6510 static int %s (void)
6513 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6517 " test_name test_name test_name;
6519 (* Optional functions should only be tested if the relevant
6520 * support is available in the daemon.
6526 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6528 pr " suppress_error = 1;\n";
6529 pr " r = guestfs_available (g, (char **) groups);\n";
6530 pr " suppress_error = 0;\n";
6531 pr " if (r == -1) {\n";
6532 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6541 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6543 pr " if (! %s_prereq ()) {\n" test_name;
6544 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6548 generate_one_test_body name i test_name init test;
6550 pr " if (%s_prereq ()) {\n" test_name;
6551 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6555 generate_one_test_body name i test_name init test;
6557 generate_one_test_body name i test_name init test
6565 and generate_one_test_body name i test_name init test =
6567 | InitNone (* XXX at some point, InitNone and InitEmpty became
6568 * folded together as the same thing. Really we should
6569 * make InitNone do nothing at all, but the tests may
6570 * need to be checked to make sure this is OK.
6573 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6574 List.iter (generate_test_command_call test_name)
6575 [["blockdev_setrw"; "/dev/sda"];
6579 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6580 List.iter (generate_test_command_call test_name)
6581 [["blockdev_setrw"; "/dev/sda"];
6584 ["part_disk"; "/dev/sda"; "mbr"]]
6586 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6587 List.iter (generate_test_command_call test_name)
6588 [["blockdev_setrw"; "/dev/sda"];
6591 ["part_disk"; "/dev/sda"; "mbr"];
6592 ["mkfs"; "ext2"; "/dev/sda1"];
6593 ["mount_options"; ""; "/dev/sda1"; "/"]]
6594 | InitBasicFSonLVM ->
6595 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6597 List.iter (generate_test_command_call test_name)
6598 [["blockdev_setrw"; "/dev/sda"];
6601 ["part_disk"; "/dev/sda"; "mbr"];
6602 ["pvcreate"; "/dev/sda1"];
6603 ["vgcreate"; "VG"; "/dev/sda1"];
6604 ["lvcreate"; "LV"; "VG"; "8"];
6605 ["mkfs"; "ext2"; "/dev/VG/LV"];
6606 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6608 pr " /* InitISOFS for %s */\n" test_name;
6609 List.iter (generate_test_command_call test_name)
6610 [["blockdev_setrw"; "/dev/sda"];
6613 ["mount_ro"; "/dev/sdd"; "/"]]
6616 let get_seq_last = function
6618 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6621 let seq = List.rev seq in
6622 List.rev (List.tl seq), List.hd seq
6627 pr " /* TestRun for %s (%d) */\n" name i;
6628 List.iter (generate_test_command_call test_name) seq
6629 | TestOutput (seq, expected) ->
6630 pr " /* TestOutput for %s (%d) */\n" name i;
6631 pr " const char *expected = \"%s\";\n" (c_quote expected);
6632 let seq, last = get_seq_last seq in
6634 pr " if (STRNEQ (r, expected)) {\n";
6635 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6639 List.iter (generate_test_command_call test_name) seq;
6640 generate_test_command_call ~test test_name last
6641 | TestOutputList (seq, expected) ->
6642 pr " /* TestOutputList for %s (%d) */\n" name i;
6643 let seq, last = get_seq_last seq in
6647 pr " if (!r[%d]) {\n" i;
6648 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6649 pr " print_strings (r);\n";
6653 pr " const char *expected = \"%s\";\n" (c_quote str);
6654 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6655 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6660 pr " if (r[%d] != NULL) {\n" (List.length expected);
6661 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6663 pr " print_strings (r);\n";
6667 List.iter (generate_test_command_call test_name) seq;
6668 generate_test_command_call ~test test_name last
6669 | TestOutputListOfDevices (seq, expected) ->
6670 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6671 let seq, last = get_seq_last seq in
6675 pr " if (!r[%d]) {\n" i;
6676 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6677 pr " print_strings (r);\n";
6681 pr " const char *expected = \"%s\";\n" (c_quote str);
6682 pr " r[%d][5] = 's';\n" i;
6683 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6684 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6689 pr " if (r[%d] != NULL) {\n" (List.length expected);
6690 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6692 pr " print_strings (r);\n";
6696 List.iter (generate_test_command_call test_name) seq;
6697 generate_test_command_call ~test test_name last
6698 | TestOutputInt (seq, expected) ->
6699 pr " /* TestOutputInt for %s (%d) */\n" name i;
6700 let seq, last = get_seq_last seq in
6702 pr " if (r != %d) {\n" expected;
6703 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6709 List.iter (generate_test_command_call test_name) seq;
6710 generate_test_command_call ~test test_name last
6711 | TestOutputIntOp (seq, op, expected) ->
6712 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6713 let seq, last = get_seq_last seq in
6715 pr " if (! (r %s %d)) {\n" op expected;
6716 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6717 test_name op expected;
6722 List.iter (generate_test_command_call test_name) seq;
6723 generate_test_command_call ~test test_name last
6724 | TestOutputTrue seq ->
6725 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6726 let seq, last = get_seq_last seq in
6729 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6734 List.iter (generate_test_command_call test_name) seq;
6735 generate_test_command_call ~test test_name last
6736 | TestOutputFalse seq ->
6737 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6738 let seq, last = get_seq_last seq in
6741 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6746 List.iter (generate_test_command_call test_name) seq;
6747 generate_test_command_call ~test test_name last
6748 | TestOutputLength (seq, expected) ->
6749 pr " /* TestOutputLength for %s (%d) */\n" name i;
6750 let seq, last = get_seq_last seq in
6753 pr " for (j = 0; j < %d; ++j)\n" expected;
6754 pr " if (r[j] == NULL) {\n";
6755 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6757 pr " print_strings (r);\n";
6760 pr " if (r[j] != NULL) {\n";
6761 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6763 pr " print_strings (r);\n";
6767 List.iter (generate_test_command_call test_name) seq;
6768 generate_test_command_call ~test test_name last
6769 | TestOutputBuffer (seq, expected) ->
6770 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6771 pr " const char *expected = \"%s\";\n" (c_quote expected);
6772 let seq, last = get_seq_last seq in
6773 let len = String.length expected in
6775 pr " if (size != %d) {\n" len;
6776 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6779 pr " if (STRNEQLEN (r, expected, size)) {\n";
6780 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6784 List.iter (generate_test_command_call test_name) seq;
6785 generate_test_command_call ~test test_name last
6786 | TestOutputStruct (seq, checks) ->
6787 pr " /* TestOutputStruct for %s (%d) */\n" name i;
6788 let seq, last = get_seq_last seq in
6792 | CompareWithInt (field, expected) ->
6793 pr " if (r->%s != %d) {\n" field expected;
6794 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6795 test_name field expected;
6796 pr " (int) r->%s);\n" field;
6799 | CompareWithIntOp (field, op, expected) ->
6800 pr " if (!(r->%s %s %d)) {\n" field op expected;
6801 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6802 test_name field op expected;
6803 pr " (int) r->%s);\n" field;
6806 | CompareWithString (field, expected) ->
6807 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6808 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6809 test_name field expected;
6810 pr " r->%s);\n" field;
6813 | CompareFieldsIntEq (field1, field2) ->
6814 pr " if (r->%s != r->%s) {\n" field1 field2;
6815 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6816 test_name field1 field2;
6817 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
6820 | CompareFieldsStrEq (field1, field2) ->
6821 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6822 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6823 test_name field1 field2;
6824 pr " r->%s, r->%s);\n" field1 field2;
6829 List.iter (generate_test_command_call test_name) seq;
6830 generate_test_command_call ~test test_name last
6831 | TestLastFail seq ->
6832 pr " /* TestLastFail for %s (%d) */\n" name i;
6833 let seq, last = get_seq_last seq in
6834 List.iter (generate_test_command_call test_name) seq;
6835 generate_test_command_call test_name ~expect_error:true last
6837 (* Generate the code to run a command, leaving the result in 'r'.
6838 * If you expect to get an error then you should set expect_error:true.
6840 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6842 | [] -> assert false
6844 (* Look up the command to find out what args/ret it has. *)
6847 let _, style, _, _, _, _, _ =
6848 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6851 failwithf "%s: in test, command %s was not found" test_name name in
6853 if List.length (snd style) <> List.length args then
6854 failwithf "%s: in test, wrong number of args given to %s"
6861 | OptString n, "NULL" -> ()
6864 | Dev_or_Path n, arg
6866 | OptString n, arg ->
6867 pr " const char *%s = \"%s\";\n" n (c_quote arg);
6871 | FileIn _, _ | FileOut _, _ -> ()
6872 | StringList n, "" | DeviceList n, "" ->
6873 pr " const char *const %s[1] = { NULL };\n" n
6874 | StringList n, arg | DeviceList n, arg ->
6875 let strs = string_split " " arg in
6878 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
6880 pr " const char *const %s[] = {\n" n;
6882 fun i _ -> pr " %s_%d,\n" n i
6886 ) (List.combine (snd style) args);
6889 match fst style with
6890 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
6891 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6892 | RConstString _ | RConstOptString _ ->
6893 pr " const char *r;\n"; "NULL"
6894 | RString _ -> pr " char *r;\n"; "NULL"
6895 | RStringList _ | RHashtable _ ->
6899 | RStruct (_, typ) ->
6900 pr " struct guestfs_%s *r;\n" typ; "NULL"
6901 | RStructList (_, typ) ->
6902 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
6905 pr " size_t size;\n";
6908 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
6909 pr " r = guestfs_%s (g" name;
6911 (* Generate the parameters. *)
6914 | OptString _, "NULL" -> pr ", NULL"
6916 | Device n, _ | Dev_or_Path n, _
6920 | FileIn _, arg | FileOut _, arg ->
6921 pr ", \"%s\"" (c_quote arg)
6922 | StringList n, _ | DeviceList n, _ ->
6923 pr ", (char **) %s" n
6926 try int_of_string arg
6927 with Failure "int_of_string" ->
6928 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6932 try Int64.of_string arg
6933 with Failure "int_of_string" ->
6934 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6937 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6938 ) (List.combine (snd style) args);
6940 (match fst style with
6941 | RBufferOut _ -> pr ", &size"
6947 if not expect_error then
6948 pr " if (r == %s)\n" error_code
6950 pr " if (r != %s)\n" error_code;
6953 (* Insert the test code. *)
6959 (match fst style with
6960 | RErr | RInt _ | RInt64 _ | RBool _
6961 | RConstString _ | RConstOptString _ -> ()
6962 | RString _ | RBufferOut _ -> pr " free (r);\n"
6963 | RStringList _ | RHashtable _ ->
6964 pr " for (i = 0; r[i] != NULL; ++i)\n";
6965 pr " free (r[i]);\n";
6967 | RStruct (_, typ) ->
6968 pr " guestfs_free_%s (r);\n" typ
6969 | RStructList (_, typ) ->
6970 pr " guestfs_free_%s_list (r);\n" typ
6976 let str = replace_str str "\r" "\\r" in
6977 let str = replace_str str "\n" "\\n" in
6978 let str = replace_str str "\t" "\\t" in
6979 let str = replace_str str "\000" "\\0" in
6982 (* Generate a lot of different functions for guestfish. *)
6983 and generate_fish_cmds () =
6984 generate_header CStyle GPLv2plus;
6988 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6990 let all_functions_sorted =
6992 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6993 ) all_functions_sorted in
6995 pr "#include <config.h>\n";
6997 pr "#include <stdio.h>\n";
6998 pr "#include <stdlib.h>\n";
6999 pr "#include <string.h>\n";
7000 pr "#include <inttypes.h>\n";
7002 pr "#include <guestfs.h>\n";
7003 pr "#include \"c-ctype.h\"\n";
7004 pr "#include \"full-write.h\"\n";
7005 pr "#include \"xstrtol.h\"\n";
7006 pr "#include \"fish.h\"\n";
7009 (* list_commands function, which implements guestfish -h *)
7010 pr "void list_commands (void)\n";
7012 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7013 pr " list_builtin_commands ();\n";
7015 fun (name, _, _, flags, _, shortdesc, _) ->
7016 let name = replace_char name '_' '-' in
7017 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7019 ) all_functions_sorted;
7020 pr " printf (\" %%s\\n\",";
7021 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7025 (* display_command function, which implements guestfish -h cmd *)
7026 pr "void display_command (const char *cmd)\n";
7029 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7030 let name2 = replace_char name '_' '-' in
7032 try find_map (function FishAlias n -> Some n | _ -> None) flags
7033 with Not_found -> name in
7034 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7036 match snd style with
7040 name2 (String.concat " " (List.map name_of_argt args)) in
7043 if List.mem ProtocolLimitWarning flags then
7044 ("\n\n" ^ protocol_limit_warning)
7047 (* For DangerWillRobinson commands, we should probably have
7048 * guestfish prompt before allowing you to use them (especially
7049 * in interactive mode). XXX
7053 if List.mem DangerWillRobinson flags then
7054 ("\n\n" ^ danger_will_robinson)
7059 match deprecation_notice flags with
7061 | Some txt -> "\n\n" ^ txt in
7063 let describe_alias =
7064 if name <> alias then
7065 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7069 pr "STRCASEEQ (cmd, \"%s\")" name;
7070 if name <> name2 then
7071 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7072 if name <> alias then
7073 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7075 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7077 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7078 "=head1 DESCRIPTION\n\n" ^
7079 longdesc ^ warnings ^ describe_alias);
7082 pr " display_builtin_command (cmd);\n";
7086 let emit_print_list_function typ =
7087 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7090 pr " unsigned int i;\n";
7092 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7093 pr " printf (\"[%%d] = {\\n\", i);\n";
7094 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7095 pr " printf (\"}\\n\");\n";
7101 (* print_* functions *)
7105 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7107 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7110 pr " unsigned int i;\n";
7116 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7118 pr " printf (\"%%s%s: \", indent);\n" name;
7119 pr " for (i = 0; i < 32; ++i)\n";
7120 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7121 pr " printf (\"\\n\");\n"
7123 pr " printf (\"%%s%s: \", indent);\n" name;
7124 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7125 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7126 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7128 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7129 pr " printf (\"\\n\");\n"
7130 | name, (FUInt64|FBytes) ->
7131 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7134 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7137 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7140 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7143 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7145 | name, FOptPercent ->
7146 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7147 typ name name typ name;
7148 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7154 (* Emit a print_TYPE_list function definition only if that function is used. *)
7157 | typ, (RStructListOnly | RStructAndList) ->
7158 (* generate the function for typ *)
7159 emit_print_list_function typ
7160 | typ, _ -> () (* empty *)
7161 ) (rstructs_used_by all_functions);
7163 (* Emit a print_TYPE function definition only if that function is used. *)
7166 | typ, (RStructOnly | RStructAndList) ->
7167 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7169 pr " print_%s_indent (%s, \"\");\n" typ typ;
7172 | typ, _ -> () (* empty *)
7173 ) (rstructs_used_by all_functions);
7175 (* run_<action> actions *)
7177 fun (name, style, _, flags, _, _, _) ->
7178 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7180 (match fst style with
7183 | RBool _ -> pr " int r;\n"
7184 | RInt64 _ -> pr " int64_t r;\n"
7185 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7186 | RString _ -> pr " char *r;\n"
7187 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7188 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7189 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7192 pr " size_t size;\n";
7200 | FileOut n -> pr " const char *%s;\n" n
7202 | Dev_or_Path n -> pr " char *%s;\n" n
7203 | StringList n | DeviceList n -> pr " char **%s;\n" n
7204 | Bool n -> pr " int %s;\n" n
7205 | Int n -> pr " int %s;\n" n
7206 | Int64 n -> pr " int64_t %s;\n" n
7209 (* Check and convert parameters. *)
7210 let argc_expected = List.length (snd style) in
7211 pr " if (argc != %d) {\n" argc_expected;
7212 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7214 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7218 let parse_integer fn fntyp rtyp range name i =
7220 pr " strtol_error xerr;\n";
7221 pr " %s r;\n" fntyp;
7223 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7224 pr " if (xerr != LONGINT_OK) {\n";
7225 pr " fprintf (stderr,\n";
7226 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7227 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7232 | Some (min, max, comment) ->
7233 pr " /* %s */\n" comment;
7234 pr " if (r < %s || r > %s) {\n" min max;
7235 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7239 pr " /* The check above should ensure this assignment does not overflow. */\n";
7241 pr " %s = r;\n" name;
7250 pr " %s = argv[%d];\n" name i
7252 | Dev_or_Path name ->
7253 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7254 pr " if (%s == NULL) return -1;\n" name
7256 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7259 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7262 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7264 | StringList name | DeviceList name ->
7265 pr " %s = parse_string_list (argv[%d]);\n" name i;
7266 pr " if (%s == NULL) return -1;\n" name;
7268 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7271 let min = "(-(2LL<<30))"
7272 and max = "((2LL<<30)-1)"
7274 "The Int type in the generator is a signed 31 bit int." in
7275 Some (min, max, comment) in
7276 parse_integer "xstrtoll" "long long" "int" range name i
7278 parse_integer "xstrtoll" "long long" "int64_t" None name i
7281 (* Call C API function. *)
7283 try find_map (function FishAction n -> Some n | _ -> None) flags
7284 with Not_found -> sprintf "guestfs_%s" name in
7286 generate_c_call_args ~handle:"g" style;
7291 | Device name | String name
7292 | OptString name | FileIn name | FileOut name | Bool name
7293 | Int name | Int64 name -> ()
7294 | Pathname name | Dev_or_Path name ->
7295 pr " free (%s);\n" name
7296 | StringList name | DeviceList name ->
7297 pr " free_strings (%s);\n" name
7300 (* Check return value for errors and display command results. *)
7301 (match fst style with
7302 | RErr -> pr " return r;\n"
7304 pr " if (r == -1) return -1;\n";
7305 pr " printf (\"%%d\\n\", r);\n";
7308 pr " if (r == -1) return -1;\n";
7309 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7312 pr " if (r == -1) return -1;\n";
7313 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7316 pr " if (r == NULL) return -1;\n";
7317 pr " printf (\"%%s\\n\", r);\n";
7319 | RConstOptString _ ->
7320 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7323 pr " if (r == NULL) return -1;\n";
7324 pr " printf (\"%%s\\n\", r);\n";
7328 pr " if (r == NULL) return -1;\n";
7329 pr " print_strings (r);\n";
7330 pr " free_strings (r);\n";
7332 | RStruct (_, typ) ->
7333 pr " if (r == NULL) return -1;\n";
7334 pr " print_%s (r);\n" typ;
7335 pr " guestfs_free_%s (r);\n" typ;
7337 | RStructList (_, typ) ->
7338 pr " if (r == NULL) return -1;\n";
7339 pr " print_%s_list (r);\n" typ;
7340 pr " guestfs_free_%s_list (r);\n" typ;
7343 pr " if (r == NULL) return -1;\n";
7344 pr " print_table (r);\n";
7345 pr " free_strings (r);\n";
7348 pr " if (r == NULL) return -1;\n";
7349 pr " if (full_write (1, r, size) != size) {\n";
7350 pr " perror (\"write\");\n";
7361 (* run_action function *)
7362 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7365 fun (name, _, _, flags, _, _, _) ->
7366 let name2 = replace_char name '_' '-' in
7368 try find_map (function FishAlias n -> Some n | _ -> None) flags
7369 with Not_found -> name in
7371 pr "STRCASEEQ (cmd, \"%s\")" name;
7372 if name <> name2 then
7373 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7374 if name <> alias then
7375 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7377 pr " return run_%s (cmd, argc, argv);\n" name;
7381 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7388 (* Readline completion for guestfish. *)
7389 and generate_fish_completion () =
7390 generate_header CStyle GPLv2plus;
7394 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7404 #ifdef HAVE_LIBREADLINE
7405 #include <readline/readline.h>
7410 #ifdef HAVE_LIBREADLINE
7412 static const char *const commands[] = {
7413 BUILTIN_COMMANDS_FOR_COMPLETION,
7416 (* Get the commands, including the aliases. They don't need to be
7417 * sorted - the generator() function just does a dumb linear search.
7421 fun (name, _, _, flags, _, _, _) ->
7422 let name2 = replace_char name '_' '-' in
7424 try find_map (function FishAlias n -> Some n | _ -> None) flags
7425 with Not_found -> name in
7427 if name <> alias then [name2; alias] else [name2]
7429 let commands = List.flatten commands in
7431 List.iter (pr " \"%s\",\n") commands;
7437 generator (const char *text, int state)
7439 static int index, len;
7444 len = strlen (text);
7447 rl_attempted_completion_over = 1;
7449 while ((name = commands[index]) != NULL) {
7451 if (STRCASEEQLEN (name, text, len))
7452 return strdup (name);
7458 #endif /* HAVE_LIBREADLINE */
7460 char **do_completion (const char *text, int start, int end)
7462 char **matches = NULL;
7464 #ifdef HAVE_LIBREADLINE
7465 rl_completion_append_character = ' ';
7468 matches = rl_completion_matches (text, generator);
7469 else if (complete_dest_paths)
7470 matches = rl_completion_matches (text, complete_dest_paths_generator);
7477 (* Generate the POD documentation for guestfish. *)
7478 and generate_fish_actions_pod () =
7479 let all_functions_sorted =
7481 fun (_, _, _, flags, _, _, _) ->
7482 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7483 ) all_functions_sorted in
7485 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7488 fun (name, style, _, flags, _, _, longdesc) ->
7490 Str.global_substitute rex (
7493 try Str.matched_group 1 s
7495 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7496 "C<" ^ replace_char sub '_' '-' ^ ">"
7498 let name = replace_char name '_' '-' in
7500 try find_map (function FishAlias n -> Some n | _ -> None) flags
7501 with Not_found -> name in
7503 pr "=head2 %s" name;
7504 if name <> alias then
7511 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7512 | OptString n -> pr " %s" n
7513 | StringList n | DeviceList n -> pr " '%s ...'" n
7514 | Bool _ -> pr " true|false"
7515 | Int n -> pr " %s" n
7516 | Int64 n -> pr " %s" n
7517 | FileIn n | FileOut n -> pr " (%s|-)" n
7521 pr "%s\n\n" longdesc;
7523 if List.exists (function FileIn _ | FileOut _ -> true
7524 | _ -> false) (snd style) then
7525 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7527 if List.mem ProtocolLimitWarning flags then
7528 pr "%s\n\n" protocol_limit_warning;
7530 if List.mem DangerWillRobinson flags then
7531 pr "%s\n\n" danger_will_robinson;
7533 match deprecation_notice flags with
7535 | Some txt -> pr "%s\n\n" txt
7536 ) all_functions_sorted
7538 (* Generate a C function prototype. *)
7539 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7540 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7542 ?handle name style =
7543 if extern then pr "extern ";
7544 if static then pr "static ";
7545 (match fst style with
7547 | RInt _ -> pr "int "
7548 | RInt64 _ -> pr "int64_t "
7549 | RBool _ -> pr "int "
7550 | RConstString _ | RConstOptString _ -> pr "const char *"
7551 | RString _ | RBufferOut _ -> pr "char *"
7552 | RStringList _ | RHashtable _ -> pr "char **"
7553 | RStruct (_, typ) ->
7554 if not in_daemon then pr "struct guestfs_%s *" typ
7555 else pr "guestfs_int_%s *" typ
7556 | RStructList (_, typ) ->
7557 if not in_daemon then pr "struct guestfs_%s_list *" typ
7558 else pr "guestfs_int_%s_list *" typ
7560 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7561 pr "%s%s (" prefix name;
7562 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7565 let comma = ref false in
7568 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7572 if single_line then pr ", " else pr ",\n\t\t"
7579 | Device n | Dev_or_Path n
7583 pr "const char *%s" n
7584 | StringList n | DeviceList n ->
7586 pr "char *const *%s" n
7587 | Bool n -> next (); pr "int %s" n
7588 | Int n -> next (); pr "int %s" n
7589 | Int64 n -> next (); pr "int64_t %s" n
7592 if not in_daemon then (next (); pr "const char *%s" n)
7594 if is_RBufferOut then (next (); pr "size_t *size_r");
7597 if semicolon then pr ";";
7598 if newline then pr "\n"
7600 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7601 and generate_c_call_args ?handle ?(decl = false) style =
7603 let comma = ref false in
7605 if !comma then pr ", ";
7610 | Some handle -> pr "%s" handle; comma := true
7615 pr "%s" (name_of_argt arg)
7617 (* For RBufferOut calls, add implicit &size parameter. *)
7619 match fst style with
7627 (* Generate the OCaml bindings interface. *)
7628 and generate_ocaml_mli () =
7629 generate_header OCamlStyle LGPLv2plus;
7632 (** For API documentation you should refer to the C API
7633 in the guestfs(3) manual page. The OCaml API uses almost
7634 exactly the same calls. *)
7637 (** A [guestfs_h] handle. *)
7639 exception Error of string
7640 (** This exception is raised when there is an error. *)
7642 exception Handle_closed of string
7643 (** This exception is raised if you use a {!Guestfs.t} handle
7644 after calling {!close} on it. The string is the name of
7647 val create : unit -> t
7648 (** Create a {!Guestfs.t} handle. *)
7650 val close : t -> unit
7651 (** Close the {!Guestfs.t} handle and free up all resources used
7654 Handles are closed by the garbage collector when they become
7655 unreferenced, but callers can call this in order to provide
7656 predictable cleanup. *)
7659 generate_ocaml_structure_decls ();
7663 fun (name, style, _, _, _, shortdesc, _) ->
7664 generate_ocaml_prototype name style;
7665 pr "(** %s *)\n" shortdesc;
7667 ) all_functions_sorted
7669 (* Generate the OCaml bindings implementation. *)
7670 and generate_ocaml_ml () =
7671 generate_header OCamlStyle LGPLv2plus;
7676 exception Error of string
7677 exception Handle_closed of string
7679 external create : unit -> t = \"ocaml_guestfs_create\"
7680 external close : t -> unit = \"ocaml_guestfs_close\"
7682 (* Give the exceptions names, so they can be raised from the C code. *)
7684 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7685 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7689 generate_ocaml_structure_decls ();
7693 fun (name, style, _, _, _, shortdesc, _) ->
7694 generate_ocaml_prototype ~is_external:true name style;
7695 ) all_functions_sorted
7697 (* Generate the OCaml bindings C implementation. *)
7698 and generate_ocaml_c () =
7699 generate_header CStyle LGPLv2plus;
7706 #include <caml/config.h>
7707 #include <caml/alloc.h>
7708 #include <caml/callback.h>
7709 #include <caml/fail.h>
7710 #include <caml/memory.h>
7711 #include <caml/mlvalues.h>
7712 #include <caml/signals.h>
7714 #include <guestfs.h>
7716 #include \"guestfs_c.h\"
7718 /* Copy a hashtable of string pairs into an assoc-list. We return
7719 * the list in reverse order, but hashtables aren't supposed to be
7722 static CAMLprim value
7723 copy_table (char * const * argv)
7726 CAMLlocal5 (rv, pairv, kv, vv, cons);
7730 for (i = 0; argv[i] != NULL; i += 2) {
7731 kv = caml_copy_string (argv[i]);
7732 vv = caml_copy_string (argv[i+1]);
7733 pairv = caml_alloc (2, 0);
7734 Store_field (pairv, 0, kv);
7735 Store_field (pairv, 1, vv);
7736 cons = caml_alloc (2, 0);
7737 Store_field (cons, 1, rv);
7739 Store_field (cons, 0, pairv);
7747 (* Struct copy functions. *)
7749 let emit_ocaml_copy_list_function typ =
7750 pr "static CAMLprim value\n";
7751 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7753 pr " CAMLparam0 ();\n";
7754 pr " CAMLlocal2 (rv, v);\n";
7755 pr " unsigned int i;\n";
7757 pr " if (%ss->len == 0)\n" typ;
7758 pr " CAMLreturn (Atom (0));\n";
7760 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
7761 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7762 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
7763 pr " caml_modify (&Field (rv, i), v);\n";
7765 pr " CAMLreturn (rv);\n";
7773 let has_optpercent_col =
7774 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7776 pr "static CAMLprim value\n";
7777 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7779 pr " CAMLparam0 ();\n";
7780 if has_optpercent_col then
7781 pr " CAMLlocal3 (rv, v, v2);\n"
7783 pr " CAMLlocal2 (rv, v);\n";
7785 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
7790 pr " v = caml_copy_string (%s->%s);\n" typ name
7792 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
7793 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7796 pr " v = caml_alloc_string (32);\n";
7797 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
7798 | name, (FBytes|FInt64|FUInt64) ->
7799 pr " v = caml_copy_int64 (%s->%s);\n" typ name
7800 | name, (FInt32|FUInt32) ->
7801 pr " v = caml_copy_int32 (%s->%s);\n" typ name
7802 | name, FOptPercent ->
7803 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7804 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
7805 pr " v = caml_alloc (1, 0);\n";
7806 pr " Store_field (v, 0, v2);\n";
7807 pr " } else /* None */\n";
7808 pr " v = Val_int (0);\n";
7810 pr " v = Val_int (%s->%s);\n" typ name
7812 pr " Store_field (rv, %d, v);\n" i
7814 pr " CAMLreturn (rv);\n";
7819 (* Emit a copy_TYPE_list function definition only if that function is used. *)
7822 | typ, (RStructListOnly | RStructAndList) ->
7823 (* generate the function for typ *)
7824 emit_ocaml_copy_list_function typ
7825 | typ, _ -> () (* empty *)
7826 ) (rstructs_used_by all_functions);
7830 fun (name, style, _, _, _, _, _) ->
7831 pr "/* Automatically generated wrapper for function\n";
7833 generate_ocaml_prototype name style;
7838 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7840 let needs_extra_vs =
7841 match fst style with RConstOptString _ -> true | _ -> false in
7843 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7844 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7845 List.iter (pr ", value %s") (List.tl params); pr ");\n";
7848 pr "CAMLprim value\n";
7849 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7850 List.iter (pr ", value %s") (List.tl params);
7855 | [p1; p2; p3; p4; p5] ->
7856 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
7857 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7858 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7859 pr " CAMLxparam%d (%s);\n"
7860 (List.length rest) (String.concat ", " rest)
7862 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7864 if not needs_extra_vs then
7865 pr " CAMLlocal1 (rv);\n"
7867 pr " CAMLlocal3 (rv, v, v2);\n";
7870 pr " guestfs_h *g = Guestfs_val (gv);\n";
7871 pr " if (g == NULL)\n";
7872 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
7878 | Device n | Dev_or_Path n
7882 pr " const char *%s = String_val (%sv);\n" n n
7884 pr " const char *%s =\n" n;
7885 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7887 | StringList n | DeviceList n ->
7888 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7890 pr " int %s = Bool_val (%sv);\n" n n
7892 pr " int %s = Int_val (%sv);\n" n n
7894 pr " int64_t %s = Int64_val (%sv);\n" n n
7897 match fst style with
7898 | RErr -> pr " int r;\n"; "-1"
7899 | RInt _ -> pr " int r;\n"; "-1"
7900 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7901 | RBool _ -> pr " int r;\n"; "-1"
7902 | RConstString _ | RConstOptString _ ->
7903 pr " const char *r;\n"; "NULL"
7904 | RString _ -> pr " char *r;\n"; "NULL"
7909 | RStruct (_, typ) ->
7910 pr " struct guestfs_%s *r;\n" typ; "NULL"
7911 | RStructList (_, typ) ->
7912 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7919 pr " size_t size;\n";
7923 pr " caml_enter_blocking_section ();\n";
7924 pr " r = guestfs_%s " name;
7925 generate_c_call_args ~handle:"g" style;
7927 pr " caml_leave_blocking_section ();\n";
7931 | StringList n | DeviceList n ->
7932 pr " ocaml_guestfs_free_strings (%s);\n" n;
7933 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7934 | Bool _ | Int _ | Int64 _
7935 | FileIn _ | FileOut _ -> ()
7938 pr " if (r == %s)\n" error_code;
7939 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7942 (match fst style with
7943 | RErr -> pr " rv = Val_unit;\n"
7944 | RInt _ -> pr " rv = Val_int (r);\n"
7946 pr " rv = caml_copy_int64 (r);\n"
7947 | RBool _ -> pr " rv = Val_bool (r);\n"
7949 pr " rv = caml_copy_string (r);\n"
7950 | RConstOptString _ ->
7951 pr " if (r) { /* Some string */\n";
7952 pr " v = caml_alloc (1, 0);\n";
7953 pr " v2 = caml_copy_string (r);\n";
7954 pr " Store_field (v, 0, v2);\n";
7955 pr " } else /* None */\n";
7956 pr " v = Val_int (0);\n";
7958 pr " rv = caml_copy_string (r);\n";
7961 pr " rv = caml_copy_string_array ((const char **) r);\n";
7962 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7964 | RStruct (_, typ) ->
7965 pr " rv = copy_%s (r);\n" typ;
7966 pr " guestfs_free_%s (r);\n" typ;
7967 | RStructList (_, typ) ->
7968 pr " rv = copy_%s_list (r);\n" typ;
7969 pr " guestfs_free_%s_list (r);\n" typ;
7971 pr " rv = copy_table (r);\n";
7972 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7975 pr " rv = caml_alloc_string (size);\n";
7976 pr " memcpy (String_val (rv), r, size);\n";
7979 pr " CAMLreturn (rv);\n";
7983 if List.length params > 5 then (
7984 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7985 pr "CAMLprim value ";
7986 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7987 pr "CAMLprim value\n";
7988 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7990 pr " return ocaml_guestfs_%s (argv[0]" name;
7991 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7996 ) all_functions_sorted
7998 and generate_ocaml_structure_decls () =
8001 pr "type %s = {\n" typ;
8004 | name, FString -> pr " %s : string;\n" name
8005 | name, FBuffer -> pr " %s : string;\n" name
8006 | name, FUUID -> pr " %s : string;\n" name
8007 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8008 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8009 | name, FChar -> pr " %s : char;\n" name
8010 | name, FOptPercent -> pr " %s : float option;\n" name
8016 and generate_ocaml_prototype ?(is_external = false) name style =
8017 if is_external then pr "external " else pr "val ";
8018 pr "%s : t -> " name;
8021 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8022 | OptString _ -> pr "string option -> "
8023 | StringList _ | DeviceList _ -> pr "string array -> "
8024 | Bool _ -> pr "bool -> "
8025 | Int _ -> pr "int -> "
8026 | Int64 _ -> pr "int64 -> "
8028 (match fst style with
8029 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8030 | RInt _ -> pr "int"
8031 | RInt64 _ -> pr "int64"
8032 | RBool _ -> pr "bool"
8033 | RConstString _ -> pr "string"
8034 | RConstOptString _ -> pr "string option"
8035 | RString _ | RBufferOut _ -> pr "string"
8036 | RStringList _ -> pr "string array"
8037 | RStruct (_, typ) -> pr "%s" typ
8038 | RStructList (_, typ) -> pr "%s array" typ
8039 | RHashtable _ -> pr "(string * string) list"
8041 if is_external then (
8043 if List.length (snd style) + 1 > 5 then
8044 pr "\"ocaml_guestfs_%s_byte\" " name;
8045 pr "\"ocaml_guestfs_%s\"" name
8049 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8050 and generate_perl_xs () =
8051 generate_header CStyle LGPLv2plus;
8054 #include \"EXTERN.h\"
8058 #include <guestfs.h>
8061 #define PRId64 \"lld\"
8065 my_newSVll(long long val) {
8066 #ifdef USE_64_BIT_ALL
8067 return newSViv(val);
8071 len = snprintf(buf, 100, \"%%\" PRId64, val);
8072 return newSVpv(buf, len);
8077 #define PRIu64 \"llu\"
8081 my_newSVull(unsigned long long val) {
8082 #ifdef USE_64_BIT_ALL
8083 return newSVuv(val);
8087 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8088 return newSVpv(buf, len);
8092 /* http://www.perlmonks.org/?node_id=680842 */
8094 XS_unpack_charPtrPtr (SV *arg) {
8099 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8100 croak (\"array reference expected\");
8102 av = (AV *)SvRV (arg);
8103 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8105 croak (\"malloc failed\");
8107 for (i = 0; i <= av_len (av); i++) {
8108 SV **elem = av_fetch (av, i, 0);
8110 if (!elem || !*elem)
8111 croak (\"missing element in list\");
8113 ret[i] = SvPV_nolen (*elem);
8121 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8128 RETVAL = guestfs_create ();
8130 croak (\"could not create guestfs handle\");
8131 guestfs_set_error_handler (RETVAL, NULL, NULL);
8144 fun (name, style, _, _, _, _, _) ->
8145 (match fst style with
8146 | RErr -> pr "void\n"
8147 | RInt _ -> pr "SV *\n"
8148 | RInt64 _ -> pr "SV *\n"
8149 | RBool _ -> pr "SV *\n"
8150 | RConstString _ -> pr "SV *\n"
8151 | RConstOptString _ -> pr "SV *\n"
8152 | RString _ -> pr "SV *\n"
8153 | RBufferOut _ -> pr "SV *\n"
8155 | RStruct _ | RStructList _
8157 pr "void\n" (* all lists returned implictly on the stack *)
8159 (* Call and arguments. *)
8161 generate_c_call_args ~handle:"g" ~decl:true style;
8163 pr " guestfs_h *g;\n";
8167 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8170 (* http://www.perlmonks.org/?node_id=554277
8171 * Note that the implicit handle argument means we have
8172 * to add 1 to the ST(x) operator.
8174 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8175 | StringList n | DeviceList n -> pr " char **%s;\n" n
8176 | Bool n -> pr " int %s;\n" n
8177 | Int n -> pr " int %s;\n" n
8178 | Int64 n -> pr " int64_t %s;\n" n
8181 let do_cleanups () =
8184 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8185 | Bool _ | Int _ | Int64 _
8186 | FileIn _ | FileOut _ -> ()
8187 | StringList n | DeviceList n -> pr " free (%s);\n" n
8192 (match fst style with
8197 pr " r = guestfs_%s " name;
8198 generate_c_call_args ~handle:"g" style;
8201 pr " if (r == -1)\n";
8202 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8208 pr " %s = guestfs_%s " n name;
8209 generate_c_call_args ~handle:"g" style;
8212 pr " if (%s == -1)\n" n;
8213 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8214 pr " RETVAL = newSViv (%s);\n" n;
8219 pr " int64_t %s;\n" n;
8221 pr " %s = guestfs_%s " n name;
8222 generate_c_call_args ~handle:"g" style;
8225 pr " if (%s == -1)\n" n;
8226 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8227 pr " RETVAL = my_newSVll (%s);\n" n;
8232 pr " const char *%s;\n" n;
8234 pr " %s = guestfs_%s " n name;
8235 generate_c_call_args ~handle:"g" style;
8238 pr " if (%s == NULL)\n" n;
8239 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8240 pr " RETVAL = newSVpv (%s, 0);\n" n;
8243 | RConstOptString n ->
8245 pr " const char *%s;\n" n;
8247 pr " %s = guestfs_%s " n name;
8248 generate_c_call_args ~handle:"g" style;
8251 pr " if (%s == NULL)\n" n;
8252 pr " RETVAL = &PL_sv_undef;\n";
8254 pr " RETVAL = newSVpv (%s, 0);\n" n;
8259 pr " char *%s;\n" n;
8261 pr " %s = guestfs_%s " n name;
8262 generate_c_call_args ~handle:"g" style;
8265 pr " if (%s == NULL)\n" n;
8266 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8267 pr " RETVAL = newSVpv (%s, 0);\n" n;
8268 pr " free (%s);\n" n;
8271 | RStringList n | RHashtable n ->
8273 pr " char **%s;\n" n;
8276 pr " %s = guestfs_%s " n name;
8277 generate_c_call_args ~handle:"g" style;
8280 pr " if (%s == NULL)\n" n;
8281 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8282 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8283 pr " EXTEND (SP, n);\n";
8284 pr " for (i = 0; i < n; ++i) {\n";
8285 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8286 pr " free (%s[i]);\n" n;
8288 pr " free (%s);\n" n;
8289 | RStruct (n, typ) ->
8290 let cols = cols_of_struct typ in
8291 generate_perl_struct_code typ cols name style n do_cleanups
8292 | RStructList (n, typ) ->
8293 let cols = cols_of_struct typ in
8294 generate_perl_struct_list_code typ cols name style n do_cleanups
8297 pr " char *%s;\n" n;
8298 pr " size_t size;\n";
8300 pr " %s = guestfs_%s " n name;
8301 generate_c_call_args ~handle:"g" style;
8304 pr " if (%s == NULL)\n" n;
8305 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8306 pr " RETVAL = newSVpv (%s, size);\n" n;
8307 pr " free (%s);\n" n;
8315 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8317 pr " struct guestfs_%s_list *%s;\n" typ n;
8321 pr " %s = guestfs_%s " n name;
8322 generate_c_call_args ~handle:"g" style;
8325 pr " if (%s == NULL)\n" n;
8326 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8327 pr " EXTEND (SP, %s->len);\n" n;
8328 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8329 pr " hv = newHV ();\n";
8333 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8334 name (String.length name) n name
8336 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8337 name (String.length name) n name
8339 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8340 name (String.length name) n name n name
8341 | name, (FBytes|FUInt64) ->
8342 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8343 name (String.length name) n name
8345 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8346 name (String.length name) n name
8347 | name, (FInt32|FUInt32) ->
8348 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8349 name (String.length name) n name
8351 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8352 name (String.length name) n name
8353 | name, FOptPercent ->
8354 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8355 name (String.length name) n name
8357 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8359 pr " guestfs_free_%s_list (%s);\n" typ n
8361 and generate_perl_struct_code typ cols name style n do_cleanups =
8363 pr " struct guestfs_%s *%s;\n" typ n;
8365 pr " %s = guestfs_%s " n name;
8366 generate_c_call_args ~handle:"g" style;
8369 pr " if (%s == NULL)\n" n;
8370 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8371 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8373 fun ((name, _) as col) ->
8374 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8378 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8381 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8384 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8386 | name, (FBytes|FUInt64) ->
8387 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8390 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8392 | name, (FInt32|FUInt32) ->
8393 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8396 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8398 | name, FOptPercent ->
8399 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8402 pr " free (%s);\n" n
8404 (* Generate Sys/Guestfs.pm. *)
8405 and generate_perl_pm () =
8406 generate_header HashStyle LGPLv2plus;
8413 Sys::Guestfs - Perl bindings for libguestfs
8419 my $h = Sys::Guestfs->new ();
8420 $h->add_drive ('guest.img');
8422 $h->mount ('/dev/sda1', '/');
8423 $h->touch ('/hello');
8428 The C<Sys::Guestfs> module provides a Perl XS binding to the
8429 libguestfs API for examining and modifying virtual machine
8432 Amongst the things this is good for: making batch configuration
8433 changes to guests, getting disk used/free statistics (see also:
8434 virt-df), migrating between virtualization systems (see also:
8435 virt-p2v), performing partial backups, performing partial guest
8436 clones, cloning guests and changing registry/UUID/hostname info, and
8439 Libguestfs uses Linux kernel and qemu code, and can access any type of
8440 guest filesystem that Linux and qemu can, including but not limited
8441 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8442 schemes, qcow, qcow2, vmdk.
8444 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8445 LVs, what filesystem is in each LV, etc.). It can also run commands
8446 in the context of the guest. Also you can access filesystems over
8449 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8450 functions for using libguestfs from Perl, including integration
8455 All errors turn into calls to C<croak> (see L<Carp(3)>).
8463 package Sys::Guestfs;
8469 XSLoader::load ('Sys::Guestfs');
8471 =item $h = Sys::Guestfs->new ();
8473 Create a new guestfs handle.
8479 my $class = ref ($proto) || $proto;
8481 my $self = Sys::Guestfs::_create ();
8482 bless $self, $class;
8488 (* Actions. We only need to print documentation for these as
8489 * they are pulled in from the XS code automatically.
8492 fun (name, style, _, flags, _, _, longdesc) ->
8493 if not (List.mem NotInDocs flags) then (
8494 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8496 generate_perl_prototype name style;
8498 pr "%s\n\n" longdesc;
8499 if List.mem ProtocolLimitWarning flags then
8500 pr "%s\n\n" protocol_limit_warning;
8501 if List.mem DangerWillRobinson flags then
8502 pr "%s\n\n" danger_will_robinson;
8503 match deprecation_notice flags with
8505 | Some txt -> pr "%s\n\n" txt
8507 ) all_functions_sorted;
8519 Copyright (C) %s Red Hat Inc.
8523 Please see the file COPYING.LIB for the full license.
8529 L<http://libguestfs.org>,
8530 L<Sys::Guestfs::Lib(3)>.
8535 and generate_perl_prototype name style =
8536 (match fst style with
8544 | RBufferOut n -> pr "$%s = " n
8546 | RHashtable n -> pr "%%%s = " n
8548 | RStructList (n,_) -> pr "@%s = " n
8551 let comma = ref false in
8554 if !comma then pr ", ";
8557 | Pathname n | Device n | Dev_or_Path n | String n
8558 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8560 | StringList n | DeviceList n ->
8565 (* Generate Python C module. *)
8566 and generate_python_c () =
8567 generate_header CStyle LGPLv2plus;
8576 #include \"guestfs.h\"
8584 get_handle (PyObject *obj)
8587 assert (obj != Py_None);
8588 return ((Pyguestfs_Object *) obj)->g;
8592 put_handle (guestfs_h *g)
8596 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8599 /* This list should be freed (but not the strings) after use. */
8601 get_string_list (PyObject *obj)
8608 if (!PyList_Check (obj)) {
8609 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8613 len = PyList_Size (obj);
8614 r = malloc (sizeof (char *) * (len+1));
8616 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8620 for (i = 0; i < len; ++i)
8621 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8628 put_string_list (char * const * const argv)
8633 for (argc = 0; argv[argc] != NULL; ++argc)
8636 list = PyList_New (argc);
8637 for (i = 0; i < argc; ++i)
8638 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8644 put_table (char * const * const argv)
8646 PyObject *list, *item;
8649 for (argc = 0; argv[argc] != NULL; ++argc)
8652 list = PyList_New (argc >> 1);
8653 for (i = 0; i < argc; i += 2) {
8654 item = PyTuple_New (2);
8655 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8656 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8657 PyList_SetItem (list, i >> 1, item);
8664 free_strings (char **argv)
8668 for (argc = 0; argv[argc] != NULL; ++argc)
8674 py_guestfs_create (PyObject *self, PyObject *args)
8678 g = guestfs_create ();
8680 PyErr_SetString (PyExc_RuntimeError,
8681 \"guestfs.create: failed to allocate handle\");
8684 guestfs_set_error_handler (g, NULL, NULL);
8685 return put_handle (g);
8689 py_guestfs_close (PyObject *self, PyObject *args)
8694 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8696 g = get_handle (py_g);
8700 Py_INCREF (Py_None);
8706 let emit_put_list_function typ =
8707 pr "static PyObject *\n";
8708 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8710 pr " PyObject *list;\n";
8713 pr " list = PyList_New (%ss->len);\n" typ;
8714 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8715 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8716 pr " return list;\n";
8721 (* Structures, turned into Python dictionaries. *)
8724 pr "static PyObject *\n";
8725 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8727 pr " PyObject *dict;\n";
8729 pr " dict = PyDict_New ();\n";
8733 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8734 pr " PyString_FromString (%s->%s));\n"
8737 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8738 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8741 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8742 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
8744 | name, (FBytes|FUInt64) ->
8745 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8746 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
8749 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8750 pr " PyLong_FromLongLong (%s->%s));\n"
8753 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8754 pr " PyLong_FromUnsignedLong (%s->%s));\n"
8757 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8758 pr " PyLong_FromLong (%s->%s));\n"
8760 | name, FOptPercent ->
8761 pr " if (%s->%s >= 0)\n" typ name;
8762 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8763 pr " PyFloat_FromDouble ((double) %s->%s));\n"
8766 pr " Py_INCREF (Py_None);\n";
8767 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8770 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8771 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8773 pr " return dict;\n";
8779 (* Emit a put_TYPE_list function definition only if that function is used. *)
8782 | typ, (RStructListOnly | RStructAndList) ->
8783 (* generate the function for typ *)
8784 emit_put_list_function typ
8785 | typ, _ -> () (* empty *)
8786 ) (rstructs_used_by all_functions);
8788 (* Python wrapper functions. *)
8790 fun (name, style, _, _, _, _, _) ->
8791 pr "static PyObject *\n";
8792 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8795 pr " PyObject *py_g;\n";
8796 pr " guestfs_h *g;\n";
8797 pr " PyObject *py_r;\n";
8800 match fst style with
8801 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8802 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8803 | RConstString _ | RConstOptString _ ->
8804 pr " const char *r;\n"; "NULL"
8805 | RString _ -> pr " char *r;\n"; "NULL"
8806 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8807 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8808 | RStructList (_, typ) ->
8809 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8812 pr " size_t size;\n";
8817 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8818 pr " const char *%s;\n" n
8819 | OptString n -> pr " const char *%s;\n" n
8820 | StringList n | DeviceList n ->
8821 pr " PyObject *py_%s;\n" n;
8822 pr " char **%s;\n" n
8823 | Bool n -> pr " int %s;\n" n
8824 | Int n -> pr " int %s;\n" n
8825 | Int64 n -> pr " long long %s;\n" n
8830 (* Convert the parameters. *)
8831 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
8834 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8835 | OptString _ -> pr "z"
8836 | StringList _ | DeviceList _ -> pr "O"
8837 | Bool _ -> pr "i" (* XXX Python has booleans? *)
8839 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8840 * emulate C's int/long/long long in Python?
8843 pr ":guestfs_%s\",\n" name;
8847 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8848 | OptString n -> pr ", &%s" n
8849 | StringList n | DeviceList n -> pr ", &py_%s" n
8850 | Bool n -> pr ", &%s" n
8851 | Int n -> pr ", &%s" n
8852 | Int64 n -> pr ", &%s" n
8856 pr " return NULL;\n";
8858 pr " g = get_handle (py_g);\n";
8861 | Pathname _ | Device _ | Dev_or_Path _ | String _
8862 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8863 | StringList n | DeviceList n ->
8864 pr " %s = get_string_list (py_%s);\n" n n;
8865 pr " if (!%s) return NULL;\n" n
8870 pr " r = guestfs_%s " name;
8871 generate_c_call_args ~handle:"g" style;
8876 | Pathname _ | Device _ | Dev_or_Path _ | String _
8877 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8878 | StringList n | DeviceList n ->
8879 pr " free (%s);\n" n
8882 pr " if (r == %s) {\n" error_code;
8883 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8884 pr " return NULL;\n";
8888 (match fst style with
8890 pr " Py_INCREF (Py_None);\n";
8891 pr " py_r = Py_None;\n"
8893 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
8894 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
8895 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
8896 | RConstOptString _ ->
8898 pr " py_r = PyString_FromString (r);\n";
8900 pr " Py_INCREF (Py_None);\n";
8901 pr " py_r = Py_None;\n";
8904 pr " py_r = PyString_FromString (r);\n";
8907 pr " py_r = put_string_list (r);\n";
8908 pr " free_strings (r);\n"
8909 | RStruct (_, typ) ->
8910 pr " py_r = put_%s (r);\n" typ;
8911 pr " guestfs_free_%s (r);\n" typ
8912 | RStructList (_, typ) ->
8913 pr " py_r = put_%s_list (r);\n" typ;
8914 pr " guestfs_free_%s_list (r);\n" typ
8916 pr " py_r = put_table (r);\n";
8917 pr " free_strings (r);\n"
8919 pr " py_r = PyString_FromStringAndSize (r, size);\n";
8923 pr " return py_r;\n";
8928 (* Table of functions. *)
8929 pr "static PyMethodDef methods[] = {\n";
8930 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8931 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8933 fun (name, _, _, _, _, _, _) ->
8934 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8937 pr " { NULL, NULL, 0, NULL }\n";
8941 (* Init function. *)
8944 initlibguestfsmod (void)
8946 static int initialized = 0;
8948 if (initialized) return;
8949 Py_InitModule ((char *) \"libguestfsmod\", methods);
8954 (* Generate Python module. *)
8955 and generate_python_py () =
8956 generate_header HashStyle LGPLv2plus;
8959 u\"\"\"Python bindings for libguestfs
8962 g = guestfs.GuestFS ()
8963 g.add_drive (\"guest.img\")
8965 parts = g.list_partitions ()
8967 The guestfs module provides a Python binding to the libguestfs API
8968 for examining and modifying virtual machine disk images.
8970 Amongst the things this is good for: making batch configuration
8971 changes to guests, getting disk used/free statistics (see also:
8972 virt-df), migrating between virtualization systems (see also:
8973 virt-p2v), performing partial backups, performing partial guest
8974 clones, cloning guests and changing registry/UUID/hostname info, and
8977 Libguestfs uses Linux kernel and qemu code, and can access any type of
8978 guest filesystem that Linux and qemu can, including but not limited
8979 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8980 schemes, qcow, qcow2, vmdk.
8982 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8983 LVs, what filesystem is in each LV, etc.). It can also run commands
8984 in the context of the guest. Also you can access filesystems over
8987 Errors which happen while using the API are turned into Python
8988 RuntimeError exceptions.
8990 To create a guestfs handle you usually have to perform the following
8993 # Create the handle, call add_drive at least once, and possibly
8994 # several times if the guest has multiple block devices:
8995 g = guestfs.GuestFS ()
8996 g.add_drive (\"guest.img\")
8998 # Launch the qemu subprocess and wait for it to become ready:
9001 # Now you can issue commands, for example:
9006 import libguestfsmod
9009 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9011 def __init__ (self):
9012 \"\"\"Create a new libguestfs handle.\"\"\"
9013 self._o = libguestfsmod.create ()
9016 libguestfsmod.close (self._o)
9021 fun (name, style, _, flags, _, _, longdesc) ->
9023 generate_py_call_args ~handle:"self" (snd style);
9026 if not (List.mem NotInDocs flags) then (
9027 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9029 match fst style with
9030 | RErr | RInt _ | RInt64 _ | RBool _
9031 | RConstOptString _ | RConstString _
9032 | RString _ | RBufferOut _ -> doc
9034 doc ^ "\n\nThis function returns a list of strings."
9035 | RStruct (_, typ) ->
9036 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9037 | RStructList (_, typ) ->
9038 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9040 doc ^ "\n\nThis function returns a dictionary." in
9042 if List.mem ProtocolLimitWarning flags then
9043 doc ^ "\n\n" ^ protocol_limit_warning
9046 if List.mem DangerWillRobinson flags then
9047 doc ^ "\n\n" ^ danger_will_robinson
9050 match deprecation_notice flags with
9052 | Some txt -> doc ^ "\n\n" ^ txt in
9053 let doc = pod2text ~width:60 name doc in
9054 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9055 let doc = String.concat "\n " doc in
9056 pr " u\"\"\"%s\"\"\"\n" doc;
9058 pr " return libguestfsmod.%s " name;
9059 generate_py_call_args ~handle:"self._o" (snd style);
9064 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9065 and generate_py_call_args ~handle args =
9067 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9070 (* Useful if you need the longdesc POD text as plain text. Returns a
9073 * Because this is very slow (the slowest part of autogeneration),
9074 * we memoize the results.
9076 and pod2text ~width name longdesc =
9077 let key = width, name, longdesc in
9078 try Hashtbl.find pod2text_memo key
9080 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9081 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9083 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9084 let chan = open_process_in cmd in
9085 let lines = ref [] in
9087 let line = input_line chan in
9088 if i = 1 then (* discard the first line of output *)
9091 let line = triml line in
9092 lines := line :: !lines;
9095 let lines = try loop 1 with End_of_file -> List.rev !lines in
9097 (match close_process_in chan with
9100 failwithf "pod2text: process exited with non-zero status (%d)" i
9101 | WSIGNALED i | WSTOPPED i ->
9102 failwithf "pod2text: process signalled or stopped by signal %d" i
9104 Hashtbl.add pod2text_memo key lines;
9105 pod2text_memo_updated ();
9108 (* Generate ruby bindings. *)
9109 and generate_ruby_c () =
9110 generate_header CStyle LGPLv2plus;
9118 #include \"guestfs.h\"
9120 #include \"extconf.h\"
9122 /* For Ruby < 1.9 */
9124 #define RARRAY_LEN(r) (RARRAY((r))->len)
9127 static VALUE m_guestfs; /* guestfs module */
9128 static VALUE c_guestfs; /* guestfs_h handle */
9129 static VALUE e_Error; /* used for all errors */
9131 static void ruby_guestfs_free (void *p)
9134 guestfs_close ((guestfs_h *) p);
9137 static VALUE ruby_guestfs_create (VALUE m)
9141 g = guestfs_create ();
9143 rb_raise (e_Error, \"failed to create guestfs handle\");
9145 /* Don't print error messages to stderr by default. */
9146 guestfs_set_error_handler (g, NULL, NULL);
9148 /* Wrap it, and make sure the close function is called when the
9151 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9154 static VALUE ruby_guestfs_close (VALUE gv)
9157 Data_Get_Struct (gv, guestfs_h, g);
9159 ruby_guestfs_free (g);
9160 DATA_PTR (gv) = NULL;
9168 fun (name, style, _, _, _, _, _) ->
9169 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9170 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9173 pr " guestfs_h *g;\n";
9174 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9176 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9182 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9183 pr " Check_Type (%sv, T_STRING);\n" n;
9184 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9186 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9187 pr " \"%s\", \"%s\");\n" n name
9189 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9190 | StringList n | DeviceList n ->
9191 pr " char **%s;\n" n;
9192 pr " Check_Type (%sv, T_ARRAY);\n" n;
9194 pr " int i, len;\n";
9195 pr " len = RARRAY_LEN (%sv);\n" n;
9196 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9198 pr " for (i = 0; i < len; ++i) {\n";
9199 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9200 pr " %s[i] = StringValueCStr (v);\n" n;
9202 pr " %s[len] = NULL;\n" n;
9205 pr " int %s = RTEST (%sv);\n" n n
9207 pr " int %s = NUM2INT (%sv);\n" n n
9209 pr " long long %s = NUM2LL (%sv);\n" n n
9214 match fst style with
9215 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9216 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9217 | RConstString _ | RConstOptString _ ->
9218 pr " const char *r;\n"; "NULL"
9219 | RString _ -> pr " char *r;\n"; "NULL"
9220 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9221 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9222 | RStructList (_, typ) ->
9223 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9226 pr " size_t size;\n";
9230 pr " r = guestfs_%s " name;
9231 generate_c_call_args ~handle:"g" style;
9236 | Pathname _ | Device _ | Dev_or_Path _ | String _
9237 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9238 | StringList n | DeviceList n ->
9239 pr " free (%s);\n" n
9242 pr " if (r == %s)\n" error_code;
9243 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9246 (match fst style with
9248 pr " return Qnil;\n"
9249 | RInt _ | RBool _ ->
9250 pr " return INT2NUM (r);\n"
9252 pr " return ULL2NUM (r);\n"
9254 pr " return rb_str_new2 (r);\n";
9255 | RConstOptString _ ->
9257 pr " return rb_str_new2 (r);\n";
9259 pr " return Qnil;\n";
9261 pr " VALUE rv = rb_str_new2 (r);\n";
9265 pr " int i, len = 0;\n";
9266 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9267 pr " VALUE rv = rb_ary_new2 (len);\n";
9268 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9269 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9270 pr " free (r[i]);\n";
9274 | RStruct (_, typ) ->
9275 let cols = cols_of_struct typ in
9276 generate_ruby_struct_code typ cols
9277 | RStructList (_, typ) ->
9278 let cols = cols_of_struct typ in
9279 generate_ruby_struct_list_code typ cols
9281 pr " VALUE rv = rb_hash_new ();\n";
9283 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9284 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9285 pr " free (r[i]);\n";
9286 pr " free (r[i+1]);\n";
9291 pr " VALUE rv = rb_str_new (r, size);\n";
9301 /* Initialize the module. */
9302 void Init__guestfs ()
9304 m_guestfs = rb_define_module (\"Guestfs\");
9305 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9306 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9308 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9309 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9312 (* Define the rest of the methods. *)
9314 fun (name, style, _, _, _, _, _) ->
9315 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9316 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9321 (* Ruby code to return a struct. *)
9322 and generate_ruby_struct_code typ cols =
9323 pr " VALUE rv = rb_hash_new ();\n";
9327 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9329 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9331 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9332 | name, (FBytes|FUInt64) ->
9333 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9335 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9337 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9339 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9340 | name, FOptPercent ->
9341 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9342 | name, FChar -> (* XXX wrong? *)
9343 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9345 pr " guestfs_free_%s (r);\n" typ;
9348 (* Ruby code to return a struct list. *)
9349 and generate_ruby_struct_list_code typ cols =
9350 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9352 pr " for (i = 0; i < r->len; ++i) {\n";
9353 pr " VALUE hv = rb_hash_new ();\n";
9357 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9359 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, r->val[i].%s_len));\n" name name name
9361 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9362 | name, (FBytes|FUInt64) ->
9363 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9365 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9367 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9369 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9370 | name, FOptPercent ->
9371 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9372 | name, FChar -> (* XXX wrong? *)
9373 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9375 pr " rb_ary_push (rv, hv);\n";
9377 pr " guestfs_free_%s_list (r);\n" typ;
9380 (* Generate Java bindings GuestFS.java file. *)
9381 and generate_java_java () =
9382 generate_header CStyle LGPLv2plus;
9385 package com.redhat.et.libguestfs;
9387 import java.util.HashMap;
9388 import com.redhat.et.libguestfs.LibGuestFSException;
9389 import com.redhat.et.libguestfs.PV;
9390 import com.redhat.et.libguestfs.VG;
9391 import com.redhat.et.libguestfs.LV;
9392 import com.redhat.et.libguestfs.Stat;
9393 import com.redhat.et.libguestfs.StatVFS;
9394 import com.redhat.et.libguestfs.IntBool;
9395 import com.redhat.et.libguestfs.Dirent;
9398 * The GuestFS object is a libguestfs handle.
9402 public class GuestFS {
9403 // Load the native code.
9405 System.loadLibrary (\"guestfs_jni\");
9409 * The native guestfs_h pointer.
9414 * Create a libguestfs handle.
9416 * @throws LibGuestFSException
9418 public GuestFS () throws LibGuestFSException
9422 private native long _create () throws LibGuestFSException;
9425 * Close a libguestfs handle.
9427 * You can also leave handles to be collected by the garbage
9428 * collector, but this method ensures that the resources used
9429 * by the handle are freed up immediately. If you call any
9430 * other methods after closing the handle, you will get an
9433 * @throws LibGuestFSException
9435 public void close () throws LibGuestFSException
9441 private native void _close (long g) throws LibGuestFSException;
9443 public void finalize () throws LibGuestFSException
9451 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9452 if not (List.mem NotInDocs flags); then (
9453 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9455 if List.mem ProtocolLimitWarning flags then
9456 doc ^ "\n\n" ^ protocol_limit_warning
9459 if List.mem DangerWillRobinson flags then
9460 doc ^ "\n\n" ^ danger_will_robinson
9463 match deprecation_notice flags with
9465 | Some txt -> doc ^ "\n\n" ^ txt in
9466 let doc = pod2text ~width:60 name doc in
9467 let doc = List.map ( (* RHBZ#501883 *)
9470 | nonempty -> nonempty
9472 let doc = String.concat "\n * " doc in
9475 pr " * %s\n" shortdesc;
9478 pr " * @throws LibGuestFSException\n";
9482 generate_java_prototype ~public:true ~semicolon:false name style;
9485 pr " if (g == 0)\n";
9486 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9489 if fst style <> RErr then pr "return ";
9491 generate_java_call_args ~handle:"g" (snd style);
9495 generate_java_prototype ~privat:true ~native:true name style;
9502 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9503 and generate_java_call_args ~handle args =
9505 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9508 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9509 ?(semicolon=true) name style =
9510 if privat then pr "private ";
9511 if public then pr "public ";
9512 if native then pr "native ";
9515 (match fst style with
9516 | RErr -> pr "void ";
9517 | RInt _ -> pr "int ";
9518 | RInt64 _ -> pr "long ";
9519 | RBool _ -> pr "boolean ";
9520 | RConstString _ | RConstOptString _ | RString _
9521 | RBufferOut _ -> pr "String ";
9522 | RStringList _ -> pr "String[] ";
9523 | RStruct (_, typ) ->
9524 let name = java_name_of_struct typ in
9526 | RStructList (_, typ) ->
9527 let name = java_name_of_struct typ in
9529 | RHashtable _ -> pr "HashMap<String,String> ";
9532 if native then pr "_%s " name else pr "%s " name;
9534 let needs_comma = ref false in
9543 if !needs_comma then pr ", ";
9544 needs_comma := true;
9548 | Device n | Dev_or_Path n
9554 | StringList n | DeviceList n ->
9565 pr " throws LibGuestFSException";
9566 if semicolon then pr ";"
9568 and generate_java_struct jtyp cols () =
9569 generate_header CStyle LGPLv2plus;
9572 package com.redhat.et.libguestfs;
9575 * Libguestfs %s structure.
9587 | name, FBuffer -> pr " public String %s;\n" name
9588 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9589 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9590 | name, FChar -> pr " public char %s;\n" name
9591 | name, FOptPercent ->
9592 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9593 pr " public float %s;\n" name
9598 and generate_java_c () =
9599 generate_header CStyle LGPLv2plus;
9606 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9607 #include \"guestfs.h\"
9609 /* Note that this function returns. The exception is not thrown
9610 * until after the wrapper function returns.
9613 throw_exception (JNIEnv *env, const char *msg)
9616 cl = (*env)->FindClass (env,
9617 \"com/redhat/et/libguestfs/LibGuestFSException\");
9618 (*env)->ThrowNew (env, cl, msg);
9621 JNIEXPORT jlong JNICALL
9622 Java_com_redhat_et_libguestfs_GuestFS__1create
9623 (JNIEnv *env, jobject obj)
9627 g = guestfs_create ();
9629 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9632 guestfs_set_error_handler (g, NULL, NULL);
9633 return (jlong) (long) g;
9636 JNIEXPORT void JNICALL
9637 Java_com_redhat_et_libguestfs_GuestFS__1close
9638 (JNIEnv *env, jobject obj, jlong jg)
9640 guestfs_h *g = (guestfs_h *) (long) jg;
9647 fun (name, style, _, _, _, _, _) ->
9649 (match fst style with
9650 | RErr -> pr "void ";
9651 | RInt _ -> pr "jint ";
9652 | RInt64 _ -> pr "jlong ";
9653 | RBool _ -> pr "jboolean ";
9654 | RConstString _ | RConstOptString _ | RString _
9655 | RBufferOut _ -> pr "jstring ";
9656 | RStruct _ | RHashtable _ ->
9658 | RStringList _ | RStructList _ ->
9662 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9663 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9665 pr " (JNIEnv *env, jobject obj, jlong jg";
9669 | Device n | Dev_or_Path n
9674 pr ", jstring j%s" n
9675 | StringList n | DeviceList n ->
9676 pr ", jobjectArray j%s" n
9678 pr ", jboolean j%s" n
9686 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9687 let error_code, no_ret =
9688 match fst style with
9689 | RErr -> pr " int r;\n"; "-1", ""
9691 | RInt _ -> pr " int r;\n"; "-1", "0"
9692 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9693 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9694 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9696 pr " jstring jr;\n";
9697 pr " char *r;\n"; "NULL", "NULL"
9699 pr " jobjectArray jr;\n";
9702 pr " jstring jstr;\n";
9703 pr " char **r;\n"; "NULL", "NULL"
9704 | RStruct (_, typ) ->
9705 pr " jobject jr;\n";
9707 pr " jfieldID fl;\n";
9708 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9709 | RStructList (_, typ) ->
9710 pr " jobjectArray jr;\n";
9712 pr " jfieldID fl;\n";
9713 pr " jobject jfl;\n";
9714 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9715 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9717 pr " jstring jr;\n";
9719 pr " size_t size;\n";
9724 | Device n | Dev_or_Path n
9729 pr " const char *%s;\n" n
9730 | StringList n | DeviceList n ->
9731 pr " int %s_len;\n" n;
9732 pr " const char **%s;\n" n
9737 pr " int64_t %s;\n" n
9741 (match fst style with
9742 | RStringList _ | RStructList _ -> true
9743 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9745 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9746 List.exists (function
9747 | StringList _ -> true
9748 | DeviceList _ -> true
9749 | _ -> false) (snd style) in
9755 (* Get the parameters. *)
9759 | Device n | Dev_or_Path n
9763 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9765 (* This is completely undocumented, but Java null becomes
9768 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9769 | StringList n | DeviceList n ->
9770 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9771 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9772 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9773 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9775 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9777 pr " %s[%s_len] = NULL;\n" n n;
9781 pr " %s = j%s;\n" n n
9784 (* Make the call. *)
9785 pr " r = guestfs_%s " name;
9786 generate_c_call_args ~handle:"g" style;
9789 (* Release the parameters. *)
9793 | Device n | Dev_or_Path n
9797 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9800 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9801 | StringList n | DeviceList n ->
9802 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9803 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9805 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9807 pr " free (%s);\n" n
9813 (* Check for errors. *)
9814 pr " if (r == %s) {\n" error_code;
9815 pr " throw_exception (env, guestfs_last_error (g));\n";
9816 pr " return %s;\n" no_ret;
9820 (match fst style with
9822 | RInt _ -> pr " return (jint) r;\n"
9823 | RBool _ -> pr " return (jboolean) r;\n"
9824 | RInt64 _ -> pr " return (jlong) r;\n"
9825 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
9826 | RConstOptString _ ->
9827 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9829 pr " jr = (*env)->NewStringUTF (env, r);\n";
9833 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9834 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9835 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
9836 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9837 pr " for (i = 0; i < r_len; ++i) {\n";
9838 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
9839 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9840 pr " free (r[i]);\n";
9844 | RStruct (_, typ) ->
9845 let jtyp = java_name_of_struct typ in
9846 let cols = cols_of_struct typ in
9847 generate_java_struct_return typ jtyp cols
9848 | RStructList (_, typ) ->
9849 let jtyp = java_name_of_struct typ in
9850 let cols = cols_of_struct typ in
9851 generate_java_struct_list_return typ jtyp cols
9854 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9855 pr " return NULL;\n"
9857 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9866 and generate_java_struct_return typ jtyp cols =
9867 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9868 pr " jr = (*env)->AllocObject (env, cl);\n";
9872 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9873 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9876 pr " char s[33];\n";
9877 pr " memcpy (s, r->%s, 32);\n" name;
9879 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9880 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9884 pr " int len = r->%s_len;\n" name;
9885 pr " char s[len+1];\n";
9886 pr " memcpy (s, r->%s, len);\n" name;
9887 pr " s[len] = 0;\n";
9888 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9889 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9891 | name, (FBytes|FUInt64|FInt64) ->
9892 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9893 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9894 | name, (FUInt32|FInt32) ->
9895 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9896 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9897 | name, FOptPercent ->
9898 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9899 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9901 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9902 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9907 and generate_java_struct_list_return typ jtyp cols =
9908 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9909 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9910 pr " for (i = 0; i < r->len; ++i) {\n";
9911 pr " jfl = (*env)->AllocObject (env, cl);\n";
9915 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9916 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9919 pr " char s[33];\n";
9920 pr " memcpy (s, r->val[i].%s, 32);\n" name;
9922 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9923 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9927 pr " int len = r->val[i].%s_len;\n" name;
9928 pr " char s[len+1];\n";
9929 pr " memcpy (s, r->val[i].%s, len);\n" name;
9930 pr " s[len] = 0;\n";
9931 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9932 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9934 | name, (FBytes|FUInt64|FInt64) ->
9935 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9936 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9937 | name, (FUInt32|FInt32) ->
9938 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9939 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9940 | name, FOptPercent ->
9941 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9942 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9944 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9945 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9947 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9949 pr " guestfs_free_%s_list (r);\n" typ;
9952 and generate_java_makefile_inc () =
9953 generate_header HashStyle GPLv2plus;
9955 pr "java_built_sources = \\\n";
9958 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9960 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9962 and generate_haskell_hs () =
9963 generate_header HaskellStyle LGPLv2plus;
9965 (* XXX We only know how to generate partial FFI for Haskell
9966 * at the moment. Please help out!
9968 let can_generate style =
9972 | RInt64 _, _ -> true
9975 | RConstOptString _, _
9981 | RBufferOut _, _ -> false in
9984 {-# INCLUDE <guestfs.h> #-}
9985 {-# LANGUAGE ForeignFunctionInterface #-}
9990 (* List out the names of the actions we want to export. *)
9992 fun (name, style, _, _, _, _, _) ->
9993 if can_generate style then pr ",\n %s" name
9999 -- Unfortunately some symbols duplicate ones already present
10000 -- in Prelude. We don't know which, so we hard-code a list
10002 import Prelude hiding (truncate)
10006 import Foreign.C.Types
10008 import Control.Exception
10009 import Data.Typeable
10011 data GuestfsS = GuestfsS -- represents the opaque C struct
10012 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10013 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10015 -- XXX define properly later XXX
10019 data IntBool = IntBool
10021 data StatVFS = StatVFS
10022 data Hashtable = Hashtable
10024 foreign import ccall unsafe \"guestfs_create\" c_create
10026 foreign import ccall unsafe \"&guestfs_close\" c_close
10027 :: FunPtr (GuestfsP -> IO ())
10028 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10029 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10031 create :: IO GuestfsH
10034 c_set_error_handler p nullPtr nullPtr
10035 h <- newForeignPtr c_close p
10038 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10039 :: GuestfsP -> IO CString
10041 -- last_error :: GuestfsH -> IO (Maybe String)
10042 -- last_error h = do
10043 -- str <- withForeignPtr h (\\p -> c_last_error p)
10044 -- maybePeek peekCString str
10046 last_error :: GuestfsH -> IO (String)
10048 str <- withForeignPtr h (\\p -> c_last_error p)
10049 if (str == nullPtr)
10050 then return \"no error\"
10051 else peekCString str
10055 (* Generate wrappers for each foreign function. *)
10057 fun (name, style, _, _, _, _, _) ->
10058 if can_generate style then (
10059 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10061 generate_haskell_prototype ~handle:"GuestfsP" style;
10065 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10067 pr "%s %s = do\n" name
10068 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10070 (* Convert pointer arguments using with* functions. *)
10075 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10076 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10077 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10078 | Bool _ | Int _ | Int64 _ -> ()
10080 (* Convert integer arguments. *)
10084 | Bool n -> sprintf "(fromBool %s)" n
10085 | Int n -> sprintf "(fromIntegral %s)" n
10086 | Int64 n -> sprintf "(fromIntegral %s)" n
10087 | FileIn n | FileOut n
10088 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10090 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10091 (String.concat " " ("p" :: args));
10092 (match fst style with
10093 | RErr | RInt _ | RInt64 _ | RBool _ ->
10094 pr " if (r == -1)\n";
10096 pr " err <- last_error h\n";
10098 | RConstString _ | RConstOptString _ | RString _
10099 | RStringList _ | RStruct _
10100 | RStructList _ | RHashtable _ | RBufferOut _ ->
10101 pr " if (r == nullPtr)\n";
10103 pr " err <- last_error h\n";
10106 (match fst style with
10108 pr " else return ()\n"
10110 pr " else return (fromIntegral r)\n"
10112 pr " else return (fromIntegral r)\n"
10114 pr " else return (toBool r)\n"
10116 | RConstOptString _
10123 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10129 and generate_haskell_prototype ~handle ?(hs = false) style =
10130 pr "%s -> " handle;
10131 let string = if hs then "String" else "CString" in
10132 let int = if hs then "Int" else "CInt" in
10133 let bool = if hs then "Bool" else "CInt" in
10134 let int64 = if hs then "Integer" else "Int64" in
10138 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10139 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10140 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10141 | Bool _ -> pr "%s" bool
10142 | Int _ -> pr "%s" int
10143 | Int64 _ -> pr "%s" int
10144 | FileIn _ -> pr "%s" string
10145 | FileOut _ -> pr "%s" string
10150 (match fst style with
10151 | RErr -> if not hs then pr "CInt"
10152 | RInt _ -> pr "%s" int
10153 | RInt64 _ -> pr "%s" int64
10154 | RBool _ -> pr "%s" bool
10155 | RConstString _ -> pr "%s" string
10156 | RConstOptString _ -> pr "Maybe %s" string
10157 | RString _ -> pr "%s" string
10158 | RStringList _ -> pr "[%s]" string
10159 | RStruct (_, typ) ->
10160 let name = java_name_of_struct typ in
10162 | RStructList (_, typ) ->
10163 let name = java_name_of_struct typ in
10165 | RHashtable _ -> pr "Hashtable"
10166 | RBufferOut _ -> pr "%s" string
10170 and generate_csharp () =
10171 generate_header CPlusPlusStyle LGPLv2plus;
10173 (* XXX Make this configurable by the C# assembly users. *)
10174 let library = "libguestfs.so.0" in
10177 // These C# bindings are highly experimental at present.
10179 // Firstly they only work on Linux (ie. Mono). In order to get them
10180 // to work on Windows (ie. .Net) you would need to port the library
10181 // itself to Windows first.
10183 // The second issue is that some calls are known to be incorrect and
10184 // can cause Mono to segfault. Particularly: calls which pass or
10185 // return string[], or return any structure value. This is because
10186 // we haven't worked out the correct way to do this from C#.
10188 // The third issue is that when compiling you get a lot of warnings.
10189 // We are not sure whether the warnings are important or not.
10191 // Fourthly we do not routinely build or test these bindings as part
10192 // of the make && make check cycle, which means that regressions might
10195 // Suggestions and patches are welcome.
10199 // gmcs Libguestfs.cs
10200 // mono Libguestfs.exe
10202 // (You'll probably want to add a Test class / static main function
10203 // otherwise this won't do anything useful).
10207 using System.Runtime.InteropServices;
10208 using System.Runtime.Serialization;
10209 using System.Collections;
10213 class Error : System.ApplicationException
10215 public Error (string message) : base (message) {}
10216 protected Error (SerializationInfo info, StreamingContext context) {}
10223 [DllImport (\"%s\")]
10224 static extern IntPtr guestfs_create ();
10228 _handle = guestfs_create ();
10229 if (_handle == IntPtr.Zero)
10230 throw new Error (\"could not create guestfs handle\");
10233 [DllImport (\"%s\")]
10234 static extern void guestfs_close (IntPtr h);
10238 guestfs_close (_handle);
10241 [DllImport (\"%s\")]
10242 static extern string guestfs_last_error (IntPtr h);
10244 " library library library;
10246 (* Generate C# structure bindings. We prefix struct names with
10247 * underscore because C# cannot have conflicting struct names and
10248 * method names (eg. "class stat" and "stat").
10252 pr " [StructLayout (LayoutKind.Sequential)]\n";
10253 pr " public class _%s {\n" typ;
10256 | name, FChar -> pr " char %s;\n" name
10257 | name, FString -> pr " string %s;\n" name
10259 pr " uint %s_len;\n" name;
10260 pr " string %s;\n" name
10262 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10263 pr " string %s;\n" name
10264 | name, FUInt32 -> pr " uint %s;\n" name
10265 | name, FInt32 -> pr " int %s;\n" name
10266 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10267 | name, FInt64 -> pr " long %s;\n" name
10268 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10274 (* Generate C# function bindings. *)
10276 fun (name, style, _, _, _, shortdesc, _) ->
10277 let rec csharp_return_type () =
10278 match fst style with
10280 | RBool n -> "bool"
10282 | RInt64 n -> "long"
10284 | RConstOptString n
10286 | RBufferOut n -> "string"
10287 | RStruct (_,n) -> "_" ^ n
10288 | RHashtable n -> "Hashtable"
10289 | RStringList n -> "string[]"
10290 | RStructList (_,n) -> sprintf "_%s[]" n
10292 and c_return_type () =
10293 match fst style with
10297 | RInt64 _ -> "long"
10299 | RConstOptString _
10301 | RBufferOut _ -> "string"
10302 | RStruct (_,n) -> "_" ^ n
10304 | RStringList _ -> "string[]"
10305 | RStructList (_,n) -> sprintf "_%s[]" n
10307 and c_error_comparison () =
10308 match fst style with
10312 | RInt64 _ -> "== -1"
10314 | RConstOptString _
10320 | RStructList (_,_) -> "== null"
10322 and generate_extern_prototype () =
10323 pr " static extern %s guestfs_%s (IntPtr h"
10324 (c_return_type ()) name;
10327 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10328 | FileIn n | FileOut n ->
10329 pr ", [In] string %s" n
10330 | StringList n | DeviceList n ->
10331 pr ", [In] string[] %s" n
10341 and generate_public_prototype () =
10342 pr " public %s %s (" (csharp_return_type ()) name;
10343 let comma = ref false in
10345 if !comma then pr ", ";
10350 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10351 | FileIn n | FileOut n ->
10352 next (); pr "string %s" n
10353 | StringList n | DeviceList n ->
10354 next (); pr "string[] %s" n
10356 next (); pr "bool %s" n
10358 next (); pr "int %s" n
10360 next (); pr "long %s" n
10364 and generate_call () =
10365 pr "guestfs_%s (_handle" name;
10366 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10370 pr " [DllImport (\"%s\")]\n" library;
10371 generate_extern_prototype ();
10373 pr " /// <summary>\n";
10374 pr " /// %s\n" shortdesc;
10375 pr " /// </summary>\n";
10376 generate_public_prototype ();
10378 pr " %s r;\n" (c_return_type ());
10381 pr " if (r %s)\n" (c_error_comparison ());
10382 pr " throw new Error (guestfs_last_error (_handle));\n";
10383 (match fst style with
10386 pr " return r != 0 ? true : false;\n"
10388 pr " Hashtable rr = new Hashtable ();\n";
10389 pr " for (int i = 0; i < r.Length; i += 2)\n";
10390 pr " rr.Add (r[i], r[i+1]);\n";
10392 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10393 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10399 ) all_functions_sorted;
10405 and generate_bindtests () =
10406 generate_header CStyle LGPLv2plus;
10410 #include <stdlib.h>
10411 #include <inttypes.h>
10412 #include <string.h>
10414 #include \"guestfs.h\"
10415 #include \"guestfs-internal.h\"
10416 #include \"guestfs-internal-actions.h\"
10417 #include \"guestfs_protocol.h\"
10419 #define error guestfs_error
10420 #define safe_calloc guestfs_safe_calloc
10421 #define safe_malloc guestfs_safe_malloc
10424 print_strings (char *const *argv)
10429 for (argc = 0; argv[argc] != NULL; ++argc) {
10430 if (argc > 0) printf (\", \");
10431 printf (\"\\\"%%s\\\"\", argv[argc]);
10436 /* The test0 function prints its parameters to stdout. */
10440 match test_functions with
10441 | [] -> assert false
10442 | test0 :: tests -> test0, tests in
10445 let (name, style, _, _, _, _, _) = test0 in
10446 generate_prototype ~extern:false ~semicolon:false ~newline:true
10447 ~handle:"g" ~prefix:"guestfs__" name style;
10452 | Device n | Dev_or_Path n
10455 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10456 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10457 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10458 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10459 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10460 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10462 pr " /* Java changes stdout line buffering so we need this: */\n";
10463 pr " fflush (stdout);\n";
10469 fun (name, style, _, _, _, _, _) ->
10470 if String.sub name (String.length name - 3) 3 <> "err" then (
10471 pr "/* Test normal return. */\n";
10472 generate_prototype ~extern:false ~semicolon:false ~newline:true
10473 ~handle:"g" ~prefix:"guestfs__" name style;
10475 (match fst style with
10480 pr " sscanf (val, \"%%d\", &r);\n";
10483 pr " int64_t r;\n";
10484 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10487 pr " return STREQ (val, \"true\");\n"
10489 | RConstOptString _ ->
10490 (* Can't return the input string here. Return a static
10491 * string so we ensure we get a segfault if the caller
10492 * tries to free it.
10494 pr " return \"static string\";\n"
10496 pr " return strdup (val);\n"
10498 pr " char **strs;\n";
10500 pr " sscanf (val, \"%%d\", &n);\n";
10501 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10502 pr " for (i = 0; i < n; ++i) {\n";
10503 pr " strs[i] = safe_malloc (g, 16);\n";
10504 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10506 pr " strs[n] = NULL;\n";
10507 pr " return strs;\n"
10508 | RStruct (_, typ) ->
10509 pr " struct guestfs_%s *r;\n" typ;
10510 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10512 | RStructList (_, typ) ->
10513 pr " struct guestfs_%s_list *r;\n" typ;
10514 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10515 pr " sscanf (val, \"%%d\", &r->len);\n";
10516 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10519 pr " char **strs;\n";
10521 pr " sscanf (val, \"%%d\", &n);\n";
10522 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10523 pr " for (i = 0; i < n; ++i) {\n";
10524 pr " strs[i*2] = safe_malloc (g, 16);\n";
10525 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10526 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10527 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10529 pr " strs[n*2] = NULL;\n";
10530 pr " return strs;\n"
10532 pr " return strdup (val);\n"
10537 pr "/* Test error return. */\n";
10538 generate_prototype ~extern:false ~semicolon:false ~newline:true
10539 ~handle:"g" ~prefix:"guestfs__" name style;
10541 pr " error (g, \"error\");\n";
10542 (match fst style with
10543 | RErr | RInt _ | RInt64 _ | RBool _ ->
10545 | RConstString _ | RConstOptString _
10546 | RString _ | RStringList _ | RStruct _
10550 pr " return NULL;\n"
10557 and generate_ocaml_bindtests () =
10558 generate_header OCamlStyle GPLv2plus;
10562 let g = Guestfs.create () in
10566 String.concat " " (
10569 | CallString s -> "\"" ^ s ^ "\""
10570 | CallOptString None -> "None"
10571 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10572 | CallStringList xs ->
10573 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10574 | CallInt i when i >= 0 -> string_of_int i
10575 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10576 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10577 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10578 | CallBool b -> string_of_bool b
10583 generate_lang_bindtests (
10584 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10587 pr "print_endline \"EOF\"\n"
10589 and generate_perl_bindtests () =
10590 pr "#!/usr/bin/perl -w\n";
10591 generate_header HashStyle GPLv2plus;
10598 my $g = Sys::Guestfs->new ();
10602 String.concat ", " (
10605 | CallString s -> "\"" ^ s ^ "\""
10606 | CallOptString None -> "undef"
10607 | CallOptString (Some s) -> sprintf "\"%s\"" s
10608 | CallStringList xs ->
10609 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10610 | CallInt i -> string_of_int i
10611 | CallInt64 i -> Int64.to_string i
10612 | CallBool b -> if b then "1" else "0"
10617 generate_lang_bindtests (
10618 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10621 pr "print \"EOF\\n\"\n"
10623 and generate_python_bindtests () =
10624 generate_header HashStyle GPLv2plus;
10629 g = guestfs.GuestFS ()
10633 String.concat ", " (
10636 | CallString s -> "\"" ^ s ^ "\""
10637 | CallOptString None -> "None"
10638 | CallOptString (Some s) -> sprintf "\"%s\"" s
10639 | CallStringList xs ->
10640 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10641 | CallInt i -> string_of_int i
10642 | CallInt64 i -> Int64.to_string i
10643 | CallBool b -> if b then "1" else "0"
10648 generate_lang_bindtests (
10649 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10652 pr "print \"EOF\"\n"
10654 and generate_ruby_bindtests () =
10655 generate_header HashStyle GPLv2plus;
10660 g = Guestfs::create()
10664 String.concat ", " (
10667 | CallString s -> "\"" ^ s ^ "\""
10668 | CallOptString None -> "nil"
10669 | CallOptString (Some s) -> sprintf "\"%s\"" s
10670 | CallStringList xs ->
10671 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10672 | CallInt i -> string_of_int i
10673 | CallInt64 i -> Int64.to_string i
10674 | CallBool b -> string_of_bool b
10679 generate_lang_bindtests (
10680 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10683 pr "print \"EOF\\n\"\n"
10685 and generate_java_bindtests () =
10686 generate_header CStyle GPLv2plus;
10689 import com.redhat.et.libguestfs.*;
10691 public class Bindtests {
10692 public static void main (String[] argv)
10695 GuestFS g = new GuestFS ();
10699 String.concat ", " (
10702 | CallString s -> "\"" ^ s ^ "\""
10703 | CallOptString None -> "null"
10704 | CallOptString (Some s) -> sprintf "\"%s\"" s
10705 | CallStringList xs ->
10707 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10708 | CallInt i -> string_of_int i
10709 | CallInt64 i -> Int64.to_string i
10710 | CallBool b -> string_of_bool b
10715 generate_lang_bindtests (
10716 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
10720 System.out.println (\"EOF\");
10722 catch (Exception exn) {
10723 System.err.println (exn);
10730 and generate_haskell_bindtests () =
10731 generate_header HaskellStyle GPLv2plus;
10734 module Bindtests where
10735 import qualified Guestfs
10738 g <- Guestfs.create
10742 String.concat " " (
10745 | CallString s -> "\"" ^ s ^ "\""
10746 | CallOptString None -> "Nothing"
10747 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10748 | CallStringList xs ->
10749 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10750 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10751 | CallInt i -> string_of_int i
10752 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10753 | CallInt64 i -> Int64.to_string i
10754 | CallBool true -> "True"
10755 | CallBool false -> "False"
10760 generate_lang_bindtests (
10761 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
10764 pr " putStrLn \"EOF\"\n"
10766 (* Language-independent bindings tests - we do it this way to
10767 * ensure there is parity in testing bindings across all languages.
10769 and generate_lang_bindtests call =
10770 call "test0" [CallString "abc"; CallOptString (Some "def");
10771 CallStringList []; CallBool false;
10772 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10773 call "test0" [CallString "abc"; CallOptString None;
10774 CallStringList []; CallBool false;
10775 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10776 call "test0" [CallString ""; CallOptString (Some "def");
10777 CallStringList []; CallBool false;
10778 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10779 call "test0" [CallString ""; CallOptString (Some "");
10780 CallStringList []; CallBool false;
10781 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10782 call "test0" [CallString "abc"; CallOptString (Some "def");
10783 CallStringList ["1"]; CallBool false;
10784 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10785 call "test0" [CallString "abc"; CallOptString (Some "def");
10786 CallStringList ["1"; "2"]; CallBool false;
10787 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10788 call "test0" [CallString "abc"; CallOptString (Some "def");
10789 CallStringList ["1"]; CallBool true;
10790 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10791 call "test0" [CallString "abc"; CallOptString (Some "def");
10792 CallStringList ["1"]; CallBool false;
10793 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10794 call "test0" [CallString "abc"; CallOptString (Some "def");
10795 CallStringList ["1"]; CallBool false;
10796 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10797 call "test0" [CallString "abc"; CallOptString (Some "def");
10798 CallStringList ["1"]; CallBool false;
10799 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10800 call "test0" [CallString "abc"; CallOptString (Some "def");
10801 CallStringList ["1"]; CallBool false;
10802 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10803 call "test0" [CallString "abc"; CallOptString (Some "def");
10804 CallStringList ["1"]; CallBool false;
10805 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10806 call "test0" [CallString "abc"; CallOptString (Some "def");
10807 CallStringList ["1"]; CallBool false;
10808 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10810 (* XXX Add here tests of the return and error functions. *)
10812 (* Code to generator bindings for virt-inspector. Currently only
10813 * implemented for OCaml code (for virt-p2v 2.0).
10815 let rng_input = "inspector/virt-inspector.rng"
10817 (* Read the input file and parse it into internal structures. This is
10818 * by no means a complete RELAX NG parser, but is just enough to be
10819 * able to parse the specific input file.
10822 | Element of string * rng list (* <element name=name/> *)
10823 | Attribute of string * rng list (* <attribute name=name/> *)
10824 | Interleave of rng list (* <interleave/> *)
10825 | ZeroOrMore of rng (* <zeroOrMore/> *)
10826 | OneOrMore of rng (* <oneOrMore/> *)
10827 | Optional of rng (* <optional/> *)
10828 | Choice of string list (* <choice><value/>*</choice> *)
10829 | Value of string (* <value>str</value> *)
10830 | Text (* <text/> *)
10832 let rec string_of_rng = function
10833 | Element (name, xs) ->
10834 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10835 | Attribute (name, xs) ->
10836 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10837 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10838 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10839 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10840 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10841 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10842 | Value value -> "Value \"" ^ value ^ "\""
10845 and string_of_rng_list xs =
10846 String.concat ", " (List.map string_of_rng xs)
10848 let rec parse_rng ?defines context = function
10850 | Xml.Element ("element", ["name", name], children) :: rest ->
10851 Element (name, parse_rng ?defines context children)
10852 :: parse_rng ?defines context rest
10853 | Xml.Element ("attribute", ["name", name], children) :: rest ->
10854 Attribute (name, parse_rng ?defines context children)
10855 :: parse_rng ?defines context rest
10856 | Xml.Element ("interleave", [], children) :: rest ->
10857 Interleave (parse_rng ?defines context children)
10858 :: parse_rng ?defines context rest
10859 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10860 let rng = parse_rng ?defines context [child] in
10862 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10864 failwithf "%s: <zeroOrMore> contains more than one child element"
10867 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10868 let rng = parse_rng ?defines context [child] in
10870 | [child] -> OneOrMore child :: parse_rng ?defines context rest
10872 failwithf "%s: <oneOrMore> contains more than one child element"
10875 | Xml.Element ("optional", [], [child]) :: rest ->
10876 let rng = parse_rng ?defines context [child] in
10878 | [child] -> Optional child :: parse_rng ?defines context rest
10880 failwithf "%s: <optional> contains more than one child element"
10883 | Xml.Element ("choice", [], children) :: rest ->
10884 let values = List.map (
10885 function Xml.Element ("value", [], [Xml.PCData value]) -> value
10887 failwithf "%s: can't handle anything except <value> in <choice>"
10891 :: parse_rng ?defines context rest
10892 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10893 Value value :: parse_rng ?defines context rest
10894 | Xml.Element ("text", [], []) :: rest ->
10895 Text :: parse_rng ?defines context rest
10896 | Xml.Element ("ref", ["name", name], []) :: rest ->
10897 (* Look up the reference. Because of limitations in this parser,
10898 * we can't handle arbitrarily nested <ref> yet. You can only
10899 * use <ref> from inside <start>.
10901 (match defines with
10903 failwithf "%s: contains <ref>, but no refs are defined yet" context
10905 let rng = StringMap.find name map in
10906 rng @ parse_rng ?defines context rest
10909 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10912 let xml = Xml.parse_file rng_input in
10914 | Xml.Element ("grammar", _,
10915 Xml.Element ("start", _, gram) :: defines) ->
10916 (* The <define/> elements are referenced in the <start> section,
10917 * so build a map of those first.
10919 let defines = List.fold_left (
10921 function Xml.Element ("define", ["name", name], defn) ->
10922 StringMap.add name defn map
10924 failwithf "%s: expected <define name=name/>" rng_input
10925 ) StringMap.empty defines in
10926 let defines = StringMap.mapi parse_rng defines in
10928 (* Parse the <start> clause, passing the defines. *)
10929 parse_rng ~defines "<start>" gram
10931 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
10934 let name_of_field = function
10935 | Element (name, _) | Attribute (name, _)
10936 | ZeroOrMore (Element (name, _))
10937 | OneOrMore (Element (name, _))
10938 | Optional (Element (name, _)) -> name
10939 | Optional (Attribute (name, _)) -> name
10940 | Text -> (* an unnamed field in an element *)
10943 failwithf "name_of_field failed at: %s" (string_of_rng rng)
10945 (* At the moment this function only generates OCaml types. However we
10946 * should parameterize it later so it can generate types/structs in a
10947 * variety of languages.
10949 let generate_types xs =
10950 (* A simple type is one that can be printed out directly, eg.
10951 * "string option". A complex type is one which has a name and has
10952 * to be defined via another toplevel definition, eg. a struct.
10954 * generate_type generates code for either simple or complex types.
10955 * In the simple case, it returns the string ("string option"). In
10956 * the complex case, it returns the name ("mountpoint"). In the
10957 * complex case it has to print out the definition before returning,
10958 * so it should only be called when we are at the beginning of a
10959 * new line (BOL context).
10961 let rec generate_type = function
10962 | Text -> (* string *)
10964 | Choice values -> (* [`val1|`val2|...] *)
10965 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
10966 | ZeroOrMore rng -> (* <rng> list *)
10967 let t, is_simple = generate_type rng in
10968 t ^ " list (* 0 or more *)", is_simple
10969 | OneOrMore rng -> (* <rng> list *)
10970 let t, is_simple = generate_type rng in
10971 t ^ " list (* 1 or more *)", is_simple
10972 (* virt-inspector hack: bool *)
10973 | Optional (Attribute (name, [Value "1"])) ->
10975 | Optional rng -> (* <rng> list *)
10976 let t, is_simple = generate_type rng in
10977 t ^ " option", is_simple
10978 (* type name = { fields ... } *)
10979 | Element (name, fields) when is_attrs_interleave fields ->
10980 generate_type_struct name (get_attrs_interleave fields)
10981 | Element (name, [field]) (* type name = field *)
10982 | Attribute (name, [field]) ->
10983 let t, is_simple = generate_type field in
10984 if is_simple then (t, true)
10986 pr "type %s = %s\n" name t;
10989 | Element (name, fields) -> (* type name = { fields ... } *)
10990 generate_type_struct name fields
10992 failwithf "generate_type failed at: %s" (string_of_rng rng)
10994 and is_attrs_interleave = function
10995 | [Interleave _] -> true
10996 | Attribute _ :: fields -> is_attrs_interleave fields
10997 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11000 and get_attrs_interleave = function
11001 | [Interleave fields] -> fields
11002 | ((Attribute _) as field) :: fields
11003 | ((Optional (Attribute _)) as field) :: fields ->
11004 field :: get_attrs_interleave fields
11005 | _ -> assert false
11007 and generate_types xs =
11008 List.iter (fun x -> ignore (generate_type x)) xs
11010 and generate_type_struct name fields =
11011 (* Calculate the types of the fields first. We have to do this
11012 * before printing anything so we are still in BOL context.
11014 let types = List.map fst (List.map generate_type fields) in
11016 (* Special case of a struct containing just a string and another
11017 * field. Turn it into an assoc list.
11020 | ["string"; other] ->
11021 let fname1, fname2 =
11023 | [f1; f2] -> name_of_field f1, name_of_field f2
11024 | _ -> assert false in
11025 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11029 pr "type %s = {\n" name;
11031 fun (field, ftype) ->
11032 let fname = name_of_field field in
11033 pr " %s_%s : %s;\n" name fname ftype
11034 ) (List.combine fields types);
11036 (* Return the name of this type, and
11037 * false because it's not a simple type.
11044 let generate_parsers xs =
11045 (* As for generate_type above, generate_parser makes a parser for
11046 * some type, and returns the name of the parser it has generated.
11047 * Because it (may) need to print something, it should always be
11048 * called in BOL context.
11050 let rec generate_parser = function
11051 | Text -> (* string *)
11052 "string_child_or_empty"
11053 | Choice values -> (* [`val1|`val2|...] *)
11054 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11056 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11057 | ZeroOrMore rng -> (* <rng> list *)
11058 let pa = generate_parser rng in
11059 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11060 | OneOrMore rng -> (* <rng> list *)
11061 let pa = generate_parser rng in
11062 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11063 (* virt-inspector hack: bool *)
11064 | Optional (Attribute (name, [Value "1"])) ->
11065 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11066 | Optional rng -> (* <rng> list *)
11067 let pa = generate_parser rng in
11068 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11069 (* type name = { fields ... } *)
11070 | Element (name, fields) when is_attrs_interleave fields ->
11071 generate_parser_struct name (get_attrs_interleave fields)
11072 | Element (name, [field]) -> (* type name = field *)
11073 let pa = generate_parser field in
11074 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11075 pr "let %s =\n" parser_name;
11077 pr "let parse_%s = %s\n" name parser_name;
11079 | Attribute (name, [field]) ->
11080 let pa = generate_parser field in
11081 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11082 pr "let %s =\n" parser_name;
11084 pr "let parse_%s = %s\n" name parser_name;
11086 | Element (name, fields) -> (* type name = { fields ... } *)
11087 generate_parser_struct name ([], fields)
11089 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11091 and is_attrs_interleave = function
11092 | [Interleave _] -> true
11093 | Attribute _ :: fields -> is_attrs_interleave fields
11094 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11097 and get_attrs_interleave = function
11098 | [Interleave fields] -> [], fields
11099 | ((Attribute _) as field) :: fields
11100 | ((Optional (Attribute _)) as field) :: fields ->
11101 let attrs, interleaves = get_attrs_interleave fields in
11102 (field :: attrs), interleaves
11103 | _ -> assert false
11105 and generate_parsers xs =
11106 List.iter (fun x -> ignore (generate_parser x)) xs
11108 and generate_parser_struct name (attrs, interleaves) =
11109 (* Generate parsers for the fields first. We have to do this
11110 * before printing anything so we are still in BOL context.
11112 let fields = attrs @ interleaves in
11113 let pas = List.map generate_parser fields in
11115 (* Generate an intermediate tuple from all the fields first.
11116 * If the type is just a string + another field, then we will
11117 * return this directly, otherwise it is turned into a record.
11119 * RELAX NG note: This code treats <interleave> and plain lists of
11120 * fields the same. In other words, it doesn't bother enforcing
11121 * any ordering of fields in the XML.
11123 pr "let parse_%s x =\n" name;
11124 pr " let t = (\n ";
11125 let comma = ref false in
11128 if !comma then pr ",\n ";
11131 | Optional (Attribute (fname, [field])), pa ->
11133 | Optional (Element (fname, [field])), pa ->
11134 pr "%s (optional_child %S x)" pa fname
11135 | Attribute (fname, [Text]), _ ->
11136 pr "attribute %S x" fname
11137 | (ZeroOrMore _ | OneOrMore _), pa ->
11142 let fname = name_of_field field in
11143 pr "%s (child %S x)" pa fname
11144 ) (List.combine fields pas);
11148 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11152 pr " (Obj.magic t : %s)\n" name
11156 | (Optional (Attribute (fname, [field])), pa) ->
11157 pr " %s_%s =\n" name fname;
11159 | (Optional (Element (fname, [field])), pa) ->
11160 pr " %s_%s =\n" name fname;
11161 pr " (let x = optional_child %S x in\n" fname;
11164 let fname = name_of_field field in
11165 pr " %s_%s =\n" name fname;
11166 pr " (let x = child %S x in\n" fname;
11168 ) (List.combine fields pas);
11172 sprintf "parse_%s" name
11175 generate_parsers xs
11177 (* Generate ocaml/guestfs_inspector.mli. *)
11178 let generate_ocaml_inspector_mli () =
11179 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11182 (** This is an OCaml language binding to the external [virt-inspector]
11185 For more information, please read the man page [virt-inspector(1)].
11190 generate_types grammar;
11191 pr "(** The nested information returned from the {!inspect} function. *)\n";
11195 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11196 (** To inspect a libvirt domain called [name], pass a singleton
11197 list: [inspect [name]]. When using libvirt only, you may
11198 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11200 To inspect a disk image or images, pass a list of the filenames
11201 of the disk images: [inspect filenames]
11203 This function inspects the given guest or disk images and
11204 returns a list of operating system(s) found and a large amount
11205 of information about them. In the vast majority of cases,
11206 a virtual machine only contains a single operating system.
11208 If the optional [~xml] parameter is given, then this function
11209 skips running the external virt-inspector program and just
11210 parses the given XML directly (which is expected to be XML
11211 produced from a previous run of virt-inspector). The list of
11212 names and connect URI are ignored in this case.
11214 This function can throw a wide variety of exceptions, for example
11215 if the external virt-inspector program cannot be found, or if
11216 it doesn't generate valid XML.
11220 (* Generate ocaml/guestfs_inspector.ml. *)
11221 let generate_ocaml_inspector_ml () =
11222 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11227 generate_types grammar;
11231 (* Misc functions which are used by the parser code below. *)
11232 let first_child = function
11233 | Xml.Element (_, _, c::_) -> c
11234 | Xml.Element (name, _, []) ->
11235 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11236 | Xml.PCData str ->
11237 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11239 let string_child_or_empty = function
11240 | Xml.Element (_, _, [Xml.PCData s]) -> s
11241 | Xml.Element (_, _, []) -> \"\"
11242 | Xml.Element (x, _, _) ->
11243 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11245 | Xml.PCData str ->
11246 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11248 let optional_child name xml =
11249 let children = Xml.children xml in
11251 Some (List.find (function
11252 | Xml.Element (n, _, _) when n = name -> true
11253 | _ -> false) children)
11257 let child name xml =
11258 match optional_child name xml with
11261 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11263 let attribute name xml =
11264 try Xml.attrib xml name
11265 with Xml.No_attribute _ ->
11266 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11270 generate_parsers grammar;
11274 (* Run external virt-inspector, then use parser to parse the XML. *)
11275 let inspect ?connect ?xml names =
11279 if names = [] then invalid_arg \"inspect: no names given\";
11280 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11281 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11283 let cmd = List.map Filename.quote cmd in
11284 let cmd = String.concat \" \" cmd in
11285 let chan = open_process_in cmd in
11286 let xml = Xml.parse_in chan in
11287 (match close_process_in chan with
11289 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11290 | WSIGNALED i | WSTOPPED i ->
11291 failwith (\"external virt-inspector command died or stopped on sig \" ^
11296 Xml.parse_string doc in
11297 parse_operatingsystems xml
11300 (* This is used to generate the src/MAX_PROC_NR file which
11301 * contains the maximum procedure number, a surrogate for the
11302 * ABI version number. See src/Makefile.am for the details.
11304 and generate_max_proc_nr () =
11305 let proc_nrs = List.map (
11306 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11307 ) daemon_functions in
11309 let max_proc_nr = List.fold_left max 0 proc_nrs in
11311 pr "%d\n" max_proc_nr
11313 let output_to filename k =
11314 let filename_new = filename ^ ".new" in
11315 chan := open_out filename_new;
11318 chan := Pervasives.stdout;
11320 (* Is the new file different from the current file? *)
11321 if Sys.file_exists filename && files_equal filename filename_new then
11322 unlink filename_new (* same, so skip it *)
11324 (* different, overwrite old one *)
11325 (try chmod filename 0o644 with Unix_error _ -> ());
11326 rename filename_new filename;
11327 chmod filename 0o444;
11328 printf "written %s\n%!" filename;
11331 let perror msg = function
11332 | Unix_error (err, _, _) ->
11333 eprintf "%s: %s\n" msg (error_message err)
11335 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11337 (* Main program. *)
11340 try openfile "HACKING" [O_RDWR] 0
11342 | Unix_error (ENOENT, _, _) ->
11344 You are probably running this from the wrong directory.
11345 Run it from the top source directory using the command
11350 perror "open: HACKING" exn;
11353 (* Acquire a lock so parallel builds won't try to run the generator
11354 * twice at the same time. Subsequent builds will wait for the first
11355 * one to finish. Note the lock is released implicitly when the
11358 (try lockf lock_fd F_LOCK 1
11360 perror "lock: HACKING" exn;
11363 check_functions ();
11365 output_to "src/guestfs_protocol.x" generate_xdr;
11366 output_to "src/guestfs-structs.h" generate_structs_h;
11367 output_to "src/guestfs-actions.h" generate_actions_h;
11368 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11369 output_to "src/guestfs-actions.c" generate_client_actions;
11370 output_to "src/guestfs-bindtests.c" generate_bindtests;
11371 output_to "src/guestfs-structs.pod" generate_structs_pod;
11372 output_to "src/guestfs-actions.pod" generate_actions_pod;
11373 output_to "src/guestfs-availability.pod" generate_availability_pod;
11374 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11375 output_to "src/libguestfs.syms" generate_linker_script;
11376 output_to "daemon/actions.h" generate_daemon_actions_h;
11377 output_to "daemon/stubs.c" generate_daemon_actions;
11378 output_to "daemon/names.c" generate_daemon_names;
11379 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11380 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11381 output_to "capitests/tests.c" generate_tests;
11382 output_to "fish/cmds.c" generate_fish_cmds;
11383 output_to "fish/completion.c" generate_fish_completion;
11384 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11385 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11386 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11387 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11388 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11389 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11390 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11391 output_to "perl/Guestfs.xs" generate_perl_xs;
11392 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11393 output_to "perl/bindtests.pl" generate_perl_bindtests;
11394 output_to "python/guestfs-py.c" generate_python_c;
11395 output_to "python/guestfs.py" generate_python_py;
11396 output_to "python/bindtests.py" generate_python_bindtests;
11397 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11398 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11399 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11403 let cols = cols_of_struct typ in
11404 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11405 output_to filename (generate_java_struct jtyp cols);
11408 output_to "java/Makefile.inc" generate_java_makefile_inc;
11409 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11410 output_to "java/Bindtests.java" generate_java_bindtests;
11411 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11412 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11413 output_to "csharp/Libguestfs.cs" generate_csharp;
11415 (* Always generate this file last, and unconditionally. It's used
11416 * by the Makefile to know when we must re-run the generator.
11418 let chan = open_out "src/stamp-generator" in
11419 fprintf chan "1\n";
11422 printf "generated %d lines of code\n" !lines